@burdenoff/microfe-channel 2026.1013.2 → 2026.1107.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 +0 -2
- package/dist/channel/ChannelRoot.js +9 -6
- package/dist/channel/ChannelRoot.js.map +1 -1
- package/dist/channel/ChannelRoutes.d.ts +1 -2
- package/dist/channel/ChannelRoutes.js +5 -6
- package/dist/channel/ChannelRoutes.js.map +1 -1
- package/dist/channel/components/AdapterCredentialsForm.d.ts +2 -4
- package/dist/channel/components/AdapterCredentialsForm.js +1 -2
- package/dist/channel/components/AdapterCredentialsForm.js.map +1 -1
- package/dist/channel/components/FeatureNotEnabled.d.ts +1 -2
- package/dist/channel/components/FeatureNotEnabled.js +1 -2
- package/dist/channel/components/FeatureNotEnabled.js.map +1 -1
- package/dist/channel/components/MarkdownEditor.d.ts +1 -2
- package/dist/channel/components/MarkdownEditor.js +2 -5
- package/dist/channel/components/MarkdownEditor.js.map +1 -1
- package/dist/channel/components/PermissionGuard.d.ts +0 -2
- package/dist/channel/components/PermissionGuard.js +1 -2
- package/dist/channel/components/PermissionGuard.js.map +1 -1
- package/dist/channel/config/adapterCredentials.d.ts +0 -2
- package/dist/channel/config/adapterCredentials.js +3 -7
- package/dist/channel/config/adapterCredentials.js.map +1 -1
- package/dist/channel/constants/permissions.d.ts +0 -1
- package/dist/channel/constants/permissions.js +1 -2
- package/dist/channel/constants/permissions.js.map +1 -1
- package/dist/channel/graphql/global-client.d.ts +0 -2
- package/dist/channel/graphql/global-client.js +5 -6
- package/dist/channel/graphql/global-client.js.map +1 -1
- package/dist/channel/hooks/useChannelOrgSettings.d.ts +0 -2
- package/dist/channel/hooks/useChannelOrgSettings.js +20 -21
- package/dist/channel/hooks/useChannelOrgSettings.js.map +1 -1
- package/dist/channel/hooks/useChannelSubscription.d.ts +0 -1
- package/dist/channel/hooks/useChannelSubscription.js +7 -12
- package/dist/channel/hooks/useChannelSubscription.js.map +1 -1
- package/dist/channel/hooks/useChannels.d.ts +20 -30
- package/dist/channel/hooks/useChannels.js +100 -101
- package/dist/channel/hooks/useChannels.js.map +1 -1
- package/dist/channel/hooks/useTr.d.ts +0 -1
- package/dist/channel/hooks/useTr.js +1 -2
- package/dist/channel/hooks/useTr.js.map +1 -1
- package/dist/channel/index.d.ts +0 -1
- package/dist/channel/index.js +3 -2
- package/dist/channel/modules/channels/hooks/useExport.d.ts +0 -2
- package/dist/channel/modules/channels/hooks/useExport.js +77 -80
- package/dist/channel/modules/channels/hooks/useExport.js.map +1 -1
- package/dist/channel/modules/channels/i18n.d.ts +0 -2
- package/dist/channel/modules/channels/i18n.js +1 -2
- package/dist/channel/modules/channels/i18n.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.js +10 -11
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelDetailsPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/ChannelDetailsPage.js +400 -401
- package/dist/channel/modules/channels/pages/ChannelDetailsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.js +8 -7
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/ChannelUsersPage.js +5 -10
- package/dist/channel/modules/channels/pages/ChannelUsersPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelsListPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/ChannelsListPage.js +287 -288
- package/dist/channel/modules/channels/pages/ChannelsListPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js +11 -12
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionsListPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/ConnectionsListPage.js +1 -2
- package/dist/channel/modules/channels/pages/ConnectionsListPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/CreateChannelPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/CreateChannelPage.js +4 -5
- package/dist/channel/modules/channels/pages/CreateChannelPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/CreateConnectionPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/CreateConnectionPage.js +37 -38
- package/dist/channel/modules/channels/pages/CreateConnectionPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/DeliveryHistoryPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js +7 -12
- package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/EditChannelPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/EditChannelPage.js +105 -103
- package/dist/channel/modules/channels/pages/EditChannelPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/EditConnectionPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/EditConnectionPage.js +22 -23
- package/dist/channel/modules/channels/pages/EditConnectionPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/SendMessagePage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/SendMessagePage.js +180 -187
- package/dist/channel/modules/channels/pages/SendMessagePage.js.map +1 -1
- package/dist/channel/modules/channels/pages/WebhookEventsPage.d.ts +1 -2
- package/dist/channel/modules/channels/pages/WebhookEventsPage.js +144 -149
- package/dist/channel/modules/channels/pages/WebhookEventsPage.js.map +1 -1
- package/dist/channel/pages/ChannelLandingPage.d.ts +1 -2
- package/dist/channel/pages/ChannelLandingPage.js +20 -21
- package/dist/channel/pages/ChannelLandingPage.js.map +1 -1
- package/dist/channel/providers/ChannelProvider.d.ts +0 -2
- package/dist/channel/providers/ChannelProvider.js +1 -2
- package/dist/channel/providers/ChannelProvider.js.map +1 -1
- package/dist/channel/types/index.d.ts +0 -2
- package/dist/channel/utils/shellBridge.d.ts +0 -1
- package/dist/channel/utils/shellBridge.js +1 -2
- package/dist/channel/utils/shellBridge.js.map +1 -1
- package/dist/dev/App.d.ts +1 -2
- package/dist/dev/main.d.ts +0 -2
- package/dist/generated/global-operations.d.ts +885 -336
- package/dist/generated/global-operations.js +2 -3
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.d.ts +2 -22
- package/dist/generated/global-types.js +1 -2
- package/dist/generated/global-types.js.map +1 -1
- package/dist/generated/wspace-operations.d.ts +4 -2
- package/dist/generated/wspace-types.d.ts +4 -24
- package/dist/index.d.ts +0 -1
- package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js +1 -2
- package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +1 -1
- package/dist/node_modules/@apollo/client/errors/utils.js +1 -2
- package/dist/node_modules/@apollo/client/errors/utils.js.map +1 -1
- package/dist/translations/en.d.ts +0 -1
- package/dist/utils/nativeBridge.d.ts +0 -1
- package/dist/utils/nativeBridge.js +1 -2
- package/package.json +65 -43
- package/dist/channel/ChannelRoot.d.ts.map +0 -1
- package/dist/channel/ChannelRoutes.d.ts.map +0 -1
- package/dist/channel/components/AdapterCredentialsForm.d.ts.map +0 -1
- package/dist/channel/components/FeatureNotEnabled.d.ts.map +0 -1
- package/dist/channel/components/MarkdownEditor.d.ts.map +0 -1
- package/dist/channel/components/PermissionGuard.d.ts.map +0 -1
- package/dist/channel/config/adapterCredentials.d.ts.map +0 -1
- package/dist/channel/constants/permissions.d.ts.map +0 -1
- package/dist/channel/graphql/global-client.d.ts.map +0 -1
- package/dist/channel/hooks/useChannelOrgSettings.d.ts.map +0 -1
- package/dist/channel/hooks/useChannelSubscription.d.ts.map +0 -1
- package/dist/channel/hooks/useChannels.d.ts.map +0 -1
- package/dist/channel/hooks/useTr.d.ts.map +0 -1
- package/dist/channel/index.d.ts.map +0 -1
- package/dist/channel/modules/channels/hooks/useExport.d.ts.map +0 -1
- package/dist/channel/modules/channels/i18n.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/ChannelDetailsPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/ChannelsListPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/ConnectionsListPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/CreateChannelPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/CreateConnectionPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/DeliveryHistoryPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/EditChannelPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/EditConnectionPage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/SendMessagePage.d.ts.map +0 -1
- package/dist/channel/modules/channels/pages/WebhookEventsPage.d.ts.map +0 -1
- package/dist/channel/pages/ChannelLandingPage.d.ts.map +0 -1
- package/dist/channel/providers/ChannelProvider.d.ts.map +0 -1
- package/dist/channel/types/index.d.ts.map +0 -1
- package/dist/channel/utils/shellBridge.d.ts.map +0 -1
- package/dist/dev/App.d.ts.map +0 -1
- package/dist/dev/main.d.ts.map +0 -1
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/global-types.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts.map +0 -1
- package/dist/generated/wspace-types.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/translations/en.d.ts.map +0 -1
- package/dist/utils/nativeBridge.d.ts.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { useTr as e } from "../../../hooks/useTr.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useChannel as t, useChannels as n } from "../../../hooks/useChannels.js";
|
|
3
|
+
import { nativeImpact as r, nativeNotify as i } from "../../../../utils/nativeBridge.js";
|
|
4
4
|
import { PermissionGuard as a } from "../../../components/PermissionGuard.js";
|
|
5
5
|
import { CHANNEL_PERMISSIONS as o } from "../../../constants/permissions.js";
|
|
6
6
|
import { MarkdownEditor as ee } from "../../../components/MarkdownEditor.js";
|
|
7
|
-
import { useEffect as
|
|
8
|
-
import { AlertCircle as
|
|
9
|
-
import { useNavigate as
|
|
10
|
-
import { Fragment as
|
|
11
|
-
import { EmphasisPanel as
|
|
12
|
-
|
|
7
|
+
import { useEffect as te, useMemo as s, useRef as c, useState as l } from "react";
|
|
8
|
+
import { AlertCircle as u, ArrowLeft as ne, Bell as re, Hash as ie, Inbox as d, Loader2 as f, Mail as p, MessageCircle as m, MessageSquare as h, Save as g, Send as ae, Smartphone as _, Trash2 as v, Users as y } from "lucide-react";
|
|
9
|
+
import { useNavigate as b, useParams as x } from "react-router";
|
|
10
|
+
import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
11
|
+
import { EmphasisPanel as T, GlassCard as oe, PagePurpose as se } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
// src/channel/modules/channels/pages/EditChannelPage.tsx
|
|
13
13
|
function E() {
|
|
14
|
-
let E =
|
|
14
|
+
let E = b(), { channelId: D } = x(), { channel: O, isLoading: ce, error: le } = t(D), { updateChannel: k, deleteChannel: A } = n(), j = e(), M = s(() => [
|
|
15
15
|
{
|
|
16
16
|
value: "EMAIL",
|
|
17
17
|
labelKey: "channel.platformLabel.email",
|
|
@@ -64,7 +64,7 @@ function E() {
|
|
|
64
64
|
labelFallback: "SMS",
|
|
65
65
|
descriptionKey: "channel.platformDescription.smsDescription",
|
|
66
66
|
descriptionFallback: "Send text messages",
|
|
67
|
-
icon:
|
|
67
|
+
icon: _,
|
|
68
68
|
color: "text-status-success-text bg-status-success-bg-subtle border-status-success-border/30",
|
|
69
69
|
adapters: [
|
|
70
70
|
{
|
|
@@ -105,7 +105,7 @@ function E() {
|
|
|
105
105
|
labelFallback: "Push",
|
|
106
106
|
descriptionKey: "channel.platformDescription.pushDescription",
|
|
107
107
|
descriptionFallback: "Mobile & web push",
|
|
108
|
-
icon:
|
|
108
|
+
icon: re,
|
|
109
109
|
color: "text-accent-purple bg-accent-purple-subtle border-accent-purple/30",
|
|
110
110
|
adapters: [
|
|
111
111
|
{
|
|
@@ -136,7 +136,7 @@ function E() {
|
|
|
136
136
|
labelFallback: "In-App",
|
|
137
137
|
descriptionKey: "channel.platformDescription.inAppDescription",
|
|
138
138
|
descriptionFallback: "Internal in-app notifications",
|
|
139
|
-
icon:
|
|
139
|
+
icon: d,
|
|
140
140
|
color: "text-status-warning-text bg-status-warning-bg-subtle border-status-warning-border/30",
|
|
141
141
|
adapters: [{
|
|
142
142
|
value: "INAPP_NATIVE",
|
|
@@ -168,7 +168,7 @@ function E() {
|
|
|
168
168
|
labelFallback: "Slack",
|
|
169
169
|
descriptionKey: "channel.platformDescription.slackDescription",
|
|
170
170
|
descriptionFallback: "Slack bot & channels",
|
|
171
|
-
icon:
|
|
171
|
+
icon: ie,
|
|
172
172
|
color: "text-accent-purple bg-accent-purple-subtle border-accent-purple/30",
|
|
173
173
|
adapters: [{
|
|
174
174
|
value: "SLACK_BOT",
|
|
@@ -182,7 +182,7 @@ function E() {
|
|
|
182
182
|
labelFallback: "Teams",
|
|
183
183
|
descriptionKey: "channel.platformDescription.teamsDescription",
|
|
184
184
|
descriptionFallback: "Microsoft Teams",
|
|
185
|
-
icon:
|
|
185
|
+
icon: y,
|
|
186
186
|
color: "text-status-info-text bg-status-info-bg-subtle border-status-info-border",
|
|
187
187
|
adapters: [{
|
|
188
188
|
value: "TEAMS_BOT",
|
|
@@ -224,7 +224,7 @@ function E() {
|
|
|
224
224
|
labelFallback: "Webhook",
|
|
225
225
|
descriptionKey: "channel.platformDescription.webhookDescription",
|
|
226
226
|
descriptionFallback: "Generic HTTP webhook",
|
|
227
|
-
icon:
|
|
227
|
+
icon: ae,
|
|
228
228
|
color: "text-text-secondary bg-bg-sunken/50 border-border-subtle",
|
|
229
229
|
adapters: [{
|
|
230
230
|
value: "WEBHOOK_HTTP",
|
|
@@ -232,7 +232,7 @@ function E() {
|
|
|
232
232
|
labelFallback: "HTTP Webhook"
|
|
233
233
|
}]
|
|
234
234
|
}
|
|
235
|
-
], []), N =
|
|
235
|
+
], []), N = s(() => [
|
|
236
236
|
{
|
|
237
237
|
value: 0,
|
|
238
238
|
label: j("channel.priorityLabel.lowest", "0 - Lowest")
|
|
@@ -253,100 +253,100 @@ function E() {
|
|
|
253
253
|
value: 4,
|
|
254
254
|
label: j("channel.priorityLabel.highest", "4 - Highest")
|
|
255
255
|
}
|
|
256
|
-
], [j]), [P, F] =
|
|
257
|
-
|
|
256
|
+
], [j]), [P, F] = l(""), [I, L] = l(""), [R, z] = l("AWS_SES"), [B, V] = l(2), [H, U] = l("INACTIVE"), [W, G] = l(!1), [K, q] = l(!1), [J, Y] = l(null), [X, Z] = l(!1), Q = c(null);
|
|
257
|
+
te(() => {
|
|
258
258
|
O && O.id !== Q.current && (Q.current = O.id, Promise.resolve().then(() => {
|
|
259
259
|
F(O.name || ""), L(O.description || ""), z(O.adapterType || "AWS_SES"), V(O.priority || 2), U(O.status || "INACTIVE");
|
|
260
260
|
}));
|
|
261
261
|
}, [O]);
|
|
262
262
|
let ue = O?.platform || "EMAIL", $ = M.find((e) => e.value === ue);
|
|
263
|
-
return ce ? /* @__PURE__ */
|
|
263
|
+
return ce ? /* @__PURE__ */ C("div", {
|
|
264
264
|
className: "flex items-center justify-center min-h-screen",
|
|
265
|
-
children: /* @__PURE__ */
|
|
266
|
-
}) : le || !O ? /* @__PURE__ */
|
|
265
|
+
children: /* @__PURE__ */ C(f, { className: "size-8 animate-spin text-text-secondary" })
|
|
266
|
+
}) : le || !O ? /* @__PURE__ */ w("div", {
|
|
267
267
|
className: "flex flex-col items-center justify-center min-h-screen gap-4",
|
|
268
268
|
children: [
|
|
269
|
-
/* @__PURE__ */
|
|
270
|
-
/* @__PURE__ */
|
|
269
|
+
/* @__PURE__ */ C(u, { className: "size-12 text-status-error-text" }),
|
|
270
|
+
/* @__PURE__ */ C("h1", {
|
|
271
271
|
className: "text-xl font-semibold",
|
|
272
272
|
children: j("channel.channelNotFound", "Channel not found")
|
|
273
273
|
}),
|
|
274
|
-
/* @__PURE__ */
|
|
274
|
+
/* @__PURE__ */ C("button", {
|
|
275
275
|
type: "button",
|
|
276
276
|
onClick: () => E("../list"),
|
|
277
277
|
className: "text-primary hover:underline",
|
|
278
278
|
children: j("channel.backToChannels", "Back to channels")
|
|
279
279
|
})
|
|
280
280
|
]
|
|
281
|
-
}) : /* @__PURE__ */
|
|
281
|
+
}) : /* @__PURE__ */ C(a, {
|
|
282
282
|
permission: o.CHANNEL_UPDATE,
|
|
283
|
-
children: /* @__PURE__ */
|
|
283
|
+
children: /* @__PURE__ */ w("div", {
|
|
284
284
|
className: "min-h-screen bg-bg-surface",
|
|
285
|
-
children: [/* @__PURE__ */
|
|
285
|
+
children: [/* @__PURE__ */ C("div", {
|
|
286
286
|
className: "border-b bg-bg-surface",
|
|
287
|
-
children: /* @__PURE__ */
|
|
287
|
+
children: /* @__PURE__ */ C("div", {
|
|
288
288
|
className: "container mx-auto px-6 py-4",
|
|
289
|
-
children: /* @__PURE__ */
|
|
289
|
+
children: /* @__PURE__ */ w("div", {
|
|
290
290
|
className: "flex items-center gap-4",
|
|
291
|
-
children: [/* @__PURE__ */
|
|
291
|
+
children: [/* @__PURE__ */ C("button", {
|
|
292
292
|
type: "button",
|
|
293
293
|
onClick: () => E(`/channels/${D}`),
|
|
294
294
|
className: "p-2 hover:bg-bg-sunken rounded-lg transition-colors",
|
|
295
|
-
children: /* @__PURE__ */
|
|
296
|
-
}), /* @__PURE__ */
|
|
295
|
+
children: /* @__PURE__ */ C(ne, { className: "size-5 " })
|
|
296
|
+
}), /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("h1", {
|
|
297
297
|
className: "text-2xl font-bold",
|
|
298
298
|
children: j("channel.editChannel", "Edit Channel")
|
|
299
|
-
}), /* @__PURE__ */
|
|
299
|
+
}), /* @__PURE__ */ C("p", {
|
|
300
300
|
className: "text-sm text-text-secondary",
|
|
301
301
|
children: j("channel.updateChannelConfig", "Update channel configuration")
|
|
302
302
|
})] })]
|
|
303
303
|
})
|
|
304
304
|
})
|
|
305
|
-
}), /* @__PURE__ */
|
|
305
|
+
}), /* @__PURE__ */ C("div", {
|
|
306
306
|
className: "container mx-auto px-6 py-8 max-w-2xl",
|
|
307
|
-
children: /* @__PURE__ */
|
|
307
|
+
children: /* @__PURE__ */ w("div", {
|
|
308
308
|
className: "space-y-6",
|
|
309
309
|
children: [
|
|
310
|
-
/* @__PURE__ */
|
|
311
|
-
icon: /* @__PURE__ */
|
|
310
|
+
/* @__PURE__ */ C(se, {
|
|
311
|
+
icon: /* @__PURE__ */ C(g, {
|
|
312
312
|
size: 15,
|
|
313
313
|
"aria-hidden": "true"
|
|
314
314
|
}),
|
|
315
315
|
children: j("channel.editChannelPurpose", "Change how this channel behaves — its name, description, priority and status. The platform and provider stay fixed (they define what the channel is); to swap credentials use the channel's connection instead. Use this to rename a channel, bump its priority, or temporarily deactivate it without deleting it.")
|
|
316
316
|
}),
|
|
317
|
-
J && /* @__PURE__ */
|
|
317
|
+
J && /* @__PURE__ */ w("div", {
|
|
318
318
|
className: "p-4 rounded-lg bg-status-error-bg/10 border border-status-error-border/20 flex items-center gap-3",
|
|
319
|
-
children: [/* @__PURE__ */
|
|
319
|
+
children: [/* @__PURE__ */ C(u, { className: "size-5 text-status-error-text shrink-0" }), /* @__PURE__ */ C("p", {
|
|
320
320
|
className: "text-sm text-status-error-text",
|
|
321
321
|
children: J
|
|
322
322
|
})]
|
|
323
323
|
}),
|
|
324
|
-
/* @__PURE__ */
|
|
324
|
+
/* @__PURE__ */ w(oe, {
|
|
325
325
|
treatment: "insight",
|
|
326
326
|
className: "p-4 border-border-seam space-y-2",
|
|
327
|
-
children: [/* @__PURE__ */
|
|
327
|
+
children: [/* @__PURE__ */ C("div", {
|
|
328
328
|
className: "flex items-center gap-2",
|
|
329
|
-
children: $ && /* @__PURE__ */
|
|
329
|
+
children: $ && /* @__PURE__ */ w(S, { children: [(() => {
|
|
330
330
|
let e = $.icon;
|
|
331
|
-
return /* @__PURE__ */
|
|
332
|
-
})(), /* @__PURE__ */
|
|
331
|
+
return /* @__PURE__ */ C(e, { className: "size-5 text-text-secondary" });
|
|
332
|
+
})(), /* @__PURE__ */ C("span", {
|
|
333
333
|
className: "font-medium",
|
|
334
334
|
children: j($.labelKey, $.labelFallback)
|
|
335
335
|
})] })
|
|
336
|
-
}), /* @__PURE__ */
|
|
336
|
+
}), /* @__PURE__ */ C("p", {
|
|
337
337
|
className: "text-sm text-text-secondary",
|
|
338
338
|
children: j("channel.platformLockedHint", "Platform cannot be changed after channel creation. Create a new channel to use a different platform.")
|
|
339
339
|
})]
|
|
340
340
|
}),
|
|
341
|
-
/* @__PURE__ */ T
|
|
341
|
+
/* @__PURE__ */ w(T, {
|
|
342
342
|
className: "p-5 space-y-6",
|
|
343
343
|
children: [
|
|
344
|
-
/* @__PURE__ */
|
|
344
|
+
/* @__PURE__ */ w("div", {
|
|
345
345
|
className: "space-y-2",
|
|
346
|
-
children: [/* @__PURE__ */
|
|
346
|
+
children: [/* @__PURE__ */ w("label", {
|
|
347
347
|
className: "text-sm font-medium",
|
|
348
348
|
children: [j("channel.channelName", "Channel Name"), " *"]
|
|
349
|
-
}), /* @__PURE__ */
|
|
349
|
+
}), /* @__PURE__ */ C("input", {
|
|
350
350
|
"aria-label": j("channel.editNamePlaceholder", "e.g., Production Email, Customer SMS"),
|
|
351
351
|
type: "text",
|
|
352
352
|
value: P,
|
|
@@ -355,13 +355,13 @@ function E() {
|
|
|
355
355
|
className: "w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary"
|
|
356
356
|
})]
|
|
357
357
|
}),
|
|
358
|
-
/* @__PURE__ */
|
|
358
|
+
/* @__PURE__ */ w("div", {
|
|
359
359
|
className: "space-y-2",
|
|
360
|
-
children: [/* @__PURE__ */
|
|
360
|
+
children: [/* @__PURE__ */ C("label", {
|
|
361
361
|
htmlFor: "channel-edit-description",
|
|
362
362
|
className: "text-sm font-medium",
|
|
363
363
|
children: j("channel.description", "Description")
|
|
364
|
-
}), /* @__PURE__ */
|
|
364
|
+
}), /* @__PURE__ */ C(ee, {
|
|
365
365
|
id: "channel-edit-description",
|
|
366
366
|
value: I,
|
|
367
367
|
onChange: L,
|
|
@@ -370,63 +370,63 @@ function E() {
|
|
|
370
370
|
rows: 3
|
|
371
371
|
})]
|
|
372
372
|
}),
|
|
373
|
-
$ && /* @__PURE__ */
|
|
373
|
+
$ && /* @__PURE__ */ w("div", {
|
|
374
374
|
className: "space-y-2",
|
|
375
|
-
children: [/* @__PURE__ */
|
|
375
|
+
children: [/* @__PURE__ */ C("label", {
|
|
376
376
|
className: "text-sm font-medium",
|
|
377
377
|
children: j("channel.adapterProvider", "Adapter / Provider")
|
|
378
|
-
}), /* @__PURE__ */
|
|
378
|
+
}), /* @__PURE__ */ C("select", {
|
|
379
379
|
value: R,
|
|
380
380
|
onChange: (e) => z(e.target.value),
|
|
381
381
|
className: "w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary",
|
|
382
|
-
children: $.adapters.map((e) => /* @__PURE__ */
|
|
382
|
+
children: $.adapters.map((e) => /* @__PURE__ */ C("option", {
|
|
383
383
|
value: e.value,
|
|
384
384
|
children: j(e.labelKey, e.labelFallback)
|
|
385
385
|
}, e.value))
|
|
386
386
|
})]
|
|
387
387
|
}),
|
|
388
|
-
/* @__PURE__ */
|
|
388
|
+
/* @__PURE__ */ w("div", {
|
|
389
389
|
className: "grid grid-cols-2 gap-4",
|
|
390
|
-
children: [/* @__PURE__ */
|
|
390
|
+
children: [/* @__PURE__ */ w("div", {
|
|
391
391
|
className: "space-y-2",
|
|
392
392
|
children: [
|
|
393
|
-
/* @__PURE__ */
|
|
393
|
+
/* @__PURE__ */ C("label", {
|
|
394
394
|
className: "text-sm font-medium",
|
|
395
395
|
children: j("channel.priority", "Priority")
|
|
396
396
|
}),
|
|
397
|
-
/* @__PURE__ */
|
|
397
|
+
/* @__PURE__ */ C("select", {
|
|
398
398
|
value: B,
|
|
399
399
|
onChange: (e) => V(Number(e.target.value)),
|
|
400
400
|
className: "w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary",
|
|
401
|
-
children: N.map((e) => /* @__PURE__ */
|
|
401
|
+
children: N.map((e) => /* @__PURE__ */ C("option", {
|
|
402
402
|
value: e.value,
|
|
403
403
|
children: e.label
|
|
404
404
|
}, e.value))
|
|
405
405
|
}),
|
|
406
|
-
/* @__PURE__ */
|
|
406
|
+
/* @__PURE__ */ C("p", {
|
|
407
407
|
className: "text-xs text-text-secondary",
|
|
408
408
|
children: j("channel.priorityFailoverHint", "Higher priority channels are used first in failover")
|
|
409
409
|
})
|
|
410
410
|
]
|
|
411
|
-
}), /* @__PURE__ */
|
|
411
|
+
}), /* @__PURE__ */ w("div", {
|
|
412
412
|
className: "space-y-2",
|
|
413
|
-
children: [/* @__PURE__ */
|
|
413
|
+
children: [/* @__PURE__ */ C("label", {
|
|
414
414
|
className: "text-sm font-medium",
|
|
415
415
|
children: j("channel.status", "Status")
|
|
416
|
-
}), /* @__PURE__ */
|
|
416
|
+
}), /* @__PURE__ */ w("select", {
|
|
417
417
|
value: H,
|
|
418
418
|
onChange: (e) => U(e.target.value),
|
|
419
419
|
className: "w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary",
|
|
420
420
|
children: [
|
|
421
|
-
/* @__PURE__ */
|
|
421
|
+
/* @__PURE__ */ C("option", {
|
|
422
422
|
value: "INACTIVE",
|
|
423
423
|
children: j("channel.statusLabel.inactive", "Inactive")
|
|
424
424
|
}),
|
|
425
|
-
/* @__PURE__ */
|
|
425
|
+
/* @__PURE__ */ C("option", {
|
|
426
426
|
value: "ACTIVE",
|
|
427
427
|
children: j("channel.statusLabel.active", "Active")
|
|
428
428
|
}),
|
|
429
|
-
/* @__PURE__ */
|
|
429
|
+
/* @__PURE__ */ C("option", {
|
|
430
430
|
value: "SUSPENDED",
|
|
431
431
|
children: j("channel.statusLabel.suspended", "Suspended")
|
|
432
432
|
})
|
|
@@ -436,80 +436,83 @@ function E() {
|
|
|
436
436
|
})
|
|
437
437
|
]
|
|
438
438
|
}),
|
|
439
|
-
/* @__PURE__ */
|
|
439
|
+
/* @__PURE__ */ w("div", {
|
|
440
440
|
className: "flex items-center justify-between pt-6 border-t",
|
|
441
|
-
children: [/* @__PURE__ */
|
|
441
|
+
children: [/* @__PURE__ */ C("div", { children: X ? /* @__PURE__ */ w("div", {
|
|
442
442
|
className: "flex items-center gap-2",
|
|
443
443
|
children: [
|
|
444
|
-
/* @__PURE__ */
|
|
444
|
+
/* @__PURE__ */ C("span", {
|
|
445
445
|
className: "text-sm text-text-secondary",
|
|
446
446
|
children: j("channel.confirmDelete", "Confirm delete?")
|
|
447
447
|
}),
|
|
448
|
-
/* @__PURE__ */
|
|
448
|
+
/* @__PURE__ */ w("button", {
|
|
449
449
|
type: "button",
|
|
450
450
|
onClick: async () => {
|
|
451
|
-
if (
|
|
452
|
-
|
|
451
|
+
if (D && X) {
|
|
452
|
+
r("medium"), q(!0);
|
|
453
453
|
try {
|
|
454
|
-
await A(D) ? (
|
|
454
|
+
await A(D) ? (i("success"), E("../list")) : i("error");
|
|
455
455
|
} catch (e) {
|
|
456
|
-
|
|
456
|
+
i("error");
|
|
457
|
+
let t = e instanceof Error ? e.message : j("channel.deleteFailed", "Failed to delete channel");
|
|
458
|
+
Y(t), q(!1);
|
|
457
459
|
}
|
|
458
460
|
}
|
|
459
461
|
},
|
|
460
462
|
disabled: K,
|
|
461
463
|
className: "px-4 py-2 text-sm bg-status-error-bg text-status-error-text rounded-lg hover:bg-status-error-bg/90 transition-colors flex items-center gap-2",
|
|
462
|
-
children: [K ? /* @__PURE__ */
|
|
464
|
+
children: [K ? /* @__PURE__ */ C(f, { className: "size-4 animate-spin" }) : /* @__PURE__ */ C(v, { className: "size-4 " }), j("channel.delete", "Delete")]
|
|
463
465
|
}),
|
|
464
|
-
/* @__PURE__ */
|
|
466
|
+
/* @__PURE__ */ C("button", {
|
|
465
467
|
type: "button",
|
|
466
468
|
onClick: () => Z(!1),
|
|
467
469
|
className: "px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-lg transition-colors",
|
|
468
470
|
children: j("channel.cancel", "Cancel")
|
|
469
471
|
})
|
|
470
472
|
]
|
|
471
|
-
}) : /* @__PURE__ */
|
|
473
|
+
}) : /* @__PURE__ */ C(a, {
|
|
472
474
|
permission: o.CHANNEL_DELETE,
|
|
473
|
-
children: /* @__PURE__ */
|
|
475
|
+
children: /* @__PURE__ */ w("button", {
|
|
474
476
|
type: "button",
|
|
475
477
|
onClick: () => Z(!0),
|
|
476
478
|
className: "px-4 py-2 text-sm text-status-error-text hover:bg-status-error-bg/10 rounded-lg transition-colors flex items-center gap-2",
|
|
477
|
-
children: [/* @__PURE__ */
|
|
479
|
+
children: [/* @__PURE__ */ C(v, { className: "size-4 " }), j("channel.deleteChannel", "Delete Channel")]
|
|
478
480
|
})
|
|
479
|
-
}) }), /* @__PURE__ */
|
|
481
|
+
}) }), /* @__PURE__ */ w("div", {
|
|
480
482
|
className: "flex items-center gap-3",
|
|
481
|
-
children: [/* @__PURE__ */
|
|
483
|
+
children: [/* @__PURE__ */ C("button", {
|
|
482
484
|
type: "button",
|
|
483
485
|
onClick: () => E(`/channels/${D}`),
|
|
484
486
|
className: "px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-lg transition-colors",
|
|
485
487
|
children: j("channel.cancel", "Cancel")
|
|
486
|
-
}), /* @__PURE__ */
|
|
488
|
+
}), /* @__PURE__ */ w("button", {
|
|
487
489
|
type: "button",
|
|
488
490
|
onClick: async () => {
|
|
489
491
|
if (D) {
|
|
490
|
-
if (!P.trim())
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
492
|
+
if (!P.trim()) Y(j("channel.validation.nameRequired", "Channel name is required"));
|
|
493
|
+
else {
|
|
494
|
+
G(!0), Y(null);
|
|
495
|
+
try {
|
|
496
|
+
let e = {
|
|
497
|
+
name: P.trim(),
|
|
498
|
+
description: I.trim() || void 0,
|
|
499
|
+
adapterType: R,
|
|
500
|
+
priority: B,
|
|
501
|
+
status: H
|
|
502
|
+
};
|
|
503
|
+
await k(D, e) ? E(`/channels/${D}`) : Y(j("channel.updateFailed", "Failed to update channel"));
|
|
504
|
+
} catch (e) {
|
|
505
|
+
let t = e instanceof Error ? e.message : j("channel.updateFailed", "Failed to update channel");
|
|
506
|
+
Y(t);
|
|
507
|
+
} finally {
|
|
508
|
+
G(!1);
|
|
509
|
+
}
|
|
507
510
|
}
|
|
508
511
|
}
|
|
509
512
|
},
|
|
510
513
|
disabled: W || !P.trim(),
|
|
511
514
|
className: "px-6 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-colors flex items-center gap-2 disabled:opacity-50",
|
|
512
|
-
children: [W ? /* @__PURE__ */
|
|
515
|
+
children: [W ? /* @__PURE__ */ C(f, { className: "size-4 animate-spin" }) : /* @__PURE__ */ C(g, { className: "size-4 " }), j("channel.saveChanges", "Save Changes")]
|
|
513
516
|
})]
|
|
514
517
|
})]
|
|
515
518
|
})
|
|
@@ -519,7 +522,6 @@ function E() {
|
|
|
519
522
|
})
|
|
520
523
|
});
|
|
521
524
|
}
|
|
522
|
-
//#endregion
|
|
523
525
|
export { E as EditChannelPage };
|
|
524
526
|
|
|
525
527
|
//# sourceMappingURL=EditChannelPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditChannelPage.js","names":[],"sources":["../../../../../src/channel/modules/channels/pages/EditChannelPage.tsx"],"sourcesContent":["/**\n * Edit Channel Page\n *\n * Allows editing an existing channel's configuration.\n * Uses the same form structure as CreateChannelPage but pre-fills existing values.\n */\n\nimport { useState, useEffect, useRef, useMemo } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport { useTr } from '../../../hooks/useTr';\nimport {\n ArrowLeft,\n Save,\n Loader2,\n AlertCircle,\n Mail,\n Smartphone,\n Bell,\n Inbox,\n MessageSquare,\n Hash,\n Users,\n MessageCircle,\n Send,\n Trash2,\n} from 'lucide-react';\nimport { useChannel, useChannels } from '../../../hooks/useChannels';\nimport {\n type ChannelPlatform,\n type AdapterType,\n type ChannelStatus,\n type UpdateChannelInput,\n} from '../../../hooks/useChannels';\nimport { EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { nativeImpact, nativeNotify } from '../../../../utils/nativeBridge';\nimport { PermissionGuard } from '../../../components/PermissionGuard';\nimport { CHANNEL_PERMISSIONS } from '../../../constants/permissions';\nimport { MarkdownEditor } from '../../../components/MarkdownEditor';\n\ntype PlatformOption = {\n value: ChannelPlatform;\n labelKey: string;\n labelFallback: string;\n descriptionKey: string;\n descriptionFallback: string;\n icon: typeof Mail;\n color: string;\n adapters: { value: AdapterType; labelKey: string; labelFallback: string }[];\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function EditChannelPage() {\n const navigate = useNavigate();\n const { channelId } = useParams<{ channelId: string }>();\n const { channel, isLoading, error } = useChannel(channelId!);\n const { updateChannel, deleteChannel } = useChannels();\n const tr = useTr();\n\n const PLATFORM_OPTIONS: PlatformOption[] = useMemo(\n () => [\n {\n value: 'EMAIL',\n labelKey: 'channel.platformLabel.email',\n labelFallback: 'Email',\n descriptionKey: 'channel.platformDescription.emailDescription',\n descriptionFallback: 'Send emails via various providers',\n icon: Mail,\n color: 'text-status-info-text bg-status-info-bg-subtle border-status-info-border',\n adapters: [\n { value: 'AWS_SES', labelKey: 'channel.adapter.awsSes', labelFallback: 'AWS SES' },\n { value: 'MAILGUN', labelKey: 'channel.adapter.mailgun', labelFallback: 'Mailgun' },\n { value: 'POSTMARK', labelKey: 'channel.adapter.postmark', labelFallback: 'Postmark' },\n { value: 'MANDRILL', labelKey: 'channel.adapter.mandrill', labelFallback: 'Mandrill' },\n { value: 'RESEND', labelKey: 'channel.adapter.resend', labelFallback: 'Resend' },\n {\n value: 'AZURE_ACS',\n labelKey: 'channel.adapter.azureAcs',\n labelFallback: 'Azure Communication Services',\n },\n { value: 'SMTP', labelKey: 'channel.adapter.smtp', labelFallback: 'Custom SMTP' },\n ],\n },\n {\n value: 'SMS',\n labelKey: 'channel.platformLabel.sms',\n labelFallback: 'SMS',\n descriptionKey: 'channel.platformDescription.smsDescription',\n descriptionFallback: 'Send text messages',\n icon: Smartphone,\n color:\n 'text-status-success-text bg-status-success-bg-subtle border-status-success-border/30',\n adapters: [\n { value: 'TWILIO_SMS', labelKey: 'channel.adapter.twilio', labelFallback: 'Twilio' },\n { value: 'AWS_SNS', labelKey: 'channel.adapter.awsSns', labelFallback: 'AWS SNS' },\n { value: 'VONAGE', labelKey: 'channel.adapter.vonage', labelFallback: 'Vonage' },\n { value: 'PLIVO', labelKey: 'channel.adapter.plivo', labelFallback: 'Plivo' },\n {\n value: 'MESSAGEBIRD',\n labelKey: 'channel.adapter.messagebird',\n labelFallback: 'MessageBird',\n },\n { value: 'INFOBIP', labelKey: 'channel.adapter.infobip', labelFallback: 'Infobip' },\n ],\n },\n {\n value: 'PUSH',\n labelKey: 'channel.platformLabel.push',\n labelFallback: 'Push',\n descriptionKey: 'channel.platformDescription.pushDescription',\n descriptionFallback: 'Mobile & web push',\n icon: Bell,\n color: 'text-accent-purple bg-accent-purple-subtle border-accent-purple/30',\n adapters: [\n {\n value: 'FCM',\n labelKey: 'channel.adapter.fcm',\n labelFallback: 'Firebase Cloud Messaging',\n },\n {\n value: 'APNS',\n labelKey: 'channel.adapter.apns',\n labelFallback: 'Apple Push Notification Service',\n },\n { value: 'ONESIGNAL', labelKey: 'channel.adapter.onesignal', labelFallback: 'OneSignal' },\n { value: 'EXPO', labelKey: 'channel.adapter.expo', labelFallback: 'Expo Push' },\n ],\n },\n {\n value: 'INAPP',\n labelKey: 'channel.platformLabel.inApp',\n labelFallback: 'In-App',\n descriptionKey: 'channel.platformDescription.inAppDescription',\n descriptionFallback: 'Internal in-app notifications',\n icon: Inbox,\n color:\n 'text-status-warning-text bg-status-warning-bg-subtle border-status-warning-border/30',\n adapters: [\n {\n value: 'INAPP_NATIVE',\n labelKey: 'channel.adapter.inAppNative',\n labelFallback: 'Native In-App',\n },\n ],\n },\n {\n value: 'WHATSAPP',\n labelKey: 'channel.platformLabel.whatsapp',\n labelFallback: 'WhatsApp',\n descriptionKey: 'channel.platformDescription.whatsappDescription',\n descriptionFallback: 'WhatsApp Business messaging',\n icon: MessageSquare,\n color:\n 'text-status-success-text bg-status-success-bg-subtle border-status-success-border/30',\n adapters: [\n {\n value: 'WHATSAPP_CLOUD',\n labelKey: 'channel.adapter.whatsappCloud',\n labelFallback: 'WhatsApp Cloud API',\n },\n {\n value: 'WHATSAPP_TWILIO',\n labelKey: 'channel.adapter.whatsappTwilio',\n labelFallback: 'WhatsApp via Twilio',\n },\n ],\n },\n {\n value: 'SLACK',\n labelKey: 'channel.platformLabel.slack',\n labelFallback: 'Slack',\n descriptionKey: 'channel.platformDescription.slackDescription',\n descriptionFallback: 'Slack bot & channels',\n icon: Hash,\n color: 'text-accent-purple bg-accent-purple-subtle border-accent-purple/30',\n adapters: [\n { value: 'SLACK_BOT', labelKey: 'channel.adapter.slackBot', labelFallback: 'Slack Bot' },\n ],\n },\n {\n value: 'TEAMS',\n labelKey: 'channel.platformLabel.teams',\n labelFallback: 'Teams',\n descriptionKey: 'channel.platformDescription.teamsDescription',\n descriptionFallback: 'Microsoft Teams',\n icon: Users,\n color: 'text-status-info-text bg-status-info-bg-subtle border-status-info-border',\n adapters: [\n { value: 'TEAMS_BOT', labelKey: 'channel.adapter.teamsBot', labelFallback: 'Teams Bot' },\n ],\n },\n {\n value: 'DISCORD',\n labelKey: 'channel.platformLabel.discord',\n labelFallback: 'Discord',\n descriptionKey: 'channel.platformDescription.discordDescription',\n descriptionFallback: 'Discord bots & webhooks',\n icon: MessageCircle,\n color: 'text-accent-indigo bg-accent-indigo-subtle border-accent-indigo/30',\n adapters: [\n {\n value: 'DISCORD_BOT',\n labelKey: 'channel.adapter.discordBot',\n labelFallback: 'Discord Bot',\n },\n ],\n },\n {\n value: 'WEBCHAT',\n labelKey: 'channel.platformLabel.webchat',\n labelFallback: 'Webchat',\n descriptionKey: 'channel.platformDescription.webchatDescription',\n descriptionFallback: 'Website live chat',\n icon: MessageSquare,\n color: 'text-accent-teal bg-accent-teal-subtle border-accent-teal/30',\n adapters: [\n {\n value: 'WEBCHAT_NATIVE',\n labelKey: 'channel.adapter.webchatNative',\n labelFallback: 'Native Webchat',\n },\n ],\n },\n {\n value: 'WEBHOOK',\n labelKey: 'channel.platformLabel.webhook',\n labelFallback: 'Webhook',\n descriptionKey: 'channel.platformDescription.webhookDescription',\n descriptionFallback: 'Generic HTTP webhook',\n icon: Send,\n color: 'text-text-secondary bg-bg-sunken/50 border-border-subtle',\n adapters: [\n {\n value: 'WEBHOOK_HTTP',\n labelKey: 'channel.adapter.webhookHttp',\n labelFallback: 'HTTP Webhook',\n },\n ],\n },\n ],\n []\n );\n\n const PRIORITY_OPTIONS = useMemo(\n () => [\n { value: 0, label: tr('channel.priorityLabel.lowest', '0 - Lowest') },\n { value: 1, label: tr('channel.priorityLabel.low', '1 - Low') },\n { value: 2, label: tr('channel.priorityLabel.normal', '2 - Normal') },\n { value: 3, label: tr('channel.priorityLabel.high', '3 - High') },\n { value: 4, label: tr('channel.priorityLabel.highest', '4 - Highest') },\n ],\n [tr]\n );\n\n // Form state\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [adapterType, setAdapterType] = useState<AdapterType>('AWS_SES');\n const [priority, setPriority] = useState(2);\n const [status, setStatus] = useState<ChannelStatus>('INACTIVE');\n\n // UI state\n const [isSaving, setIsSaving] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [deleteConfirm, setDeleteConfirm] = useState(false);\n\n // Load channel data into form — guard against re-initialization and defer\n // the state update to a microtask so setState does not run synchronously\n // inside the effect body (react-hooks/set-state-in-effect).\n const loadedChannelIdRef = useRef<string | null>(null);\n useEffect(() => {\n if (channel && channel.id !== loadedChannelIdRef.current) {\n loadedChannelIdRef.current = channel.id;\n void Promise.resolve().then(() => {\n setName(channel.name || '');\n setDescription(channel.description || '');\n setAdapterType((channel.adapterType || 'AWS_SES') as AdapterType);\n setPriority(channel.priority || 2);\n setStatus((channel.status || 'INACTIVE') as ChannelStatus);\n });\n }\n }, [channel]);\n\n // Update adapter options when platform changes\n const currentPlatform = (channel?.platform || 'EMAIL') as ChannelPlatform;\n const selectedPlatform = PLATFORM_OPTIONS.find((p) => p.value === currentPlatform);\n\n const handleSave = async () => {\n if (!channelId) return;\n\n if (!name.trim()) {\n setSaveError(tr('channel.validation.nameRequired', 'Channel name is required'));\n return;\n }\n\n setIsSaving(true);\n setSaveError(null);\n\n try {\n const input: UpdateChannelInput = {\n name: name.trim(),\n description: description.trim() || undefined,\n adapterType,\n priority,\n status,\n };\n\n const result = await updateChannel(channelId, input);\n if (result) {\n navigate(`/channels/${channelId}`);\n } else {\n setSaveError(tr('channel.updateFailed', 'Failed to update channel'));\n }\n } catch (err: unknown) {\n const message =\n err instanceof Error ? err.message : tr('channel.updateFailed', 'Failed to update channel');\n setSaveError(message);\n } finally {\n setIsSaving(false);\n }\n };\n\n const handleDelete = async () => {\n if (!channelId || !deleteConfirm) return;\n void nativeImpact('medium');\n\n setIsDeleting(true);\n try {\n const success = await deleteChannel(channelId);\n if (success) {\n void nativeNotify('success');\n navigate('../list');\n } else {\n void nativeNotify('error');\n }\n } catch (err: unknown) {\n void nativeNotify('error');\n const message =\n err instanceof Error ? err.message : tr('channel.deleteFailed', 'Failed to delete channel');\n setSaveError(message);\n setIsDeleting(false);\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center min-h-screen\">\n <Loader2 className=\"size-8 animate-spin text-text-secondary\" />\n </div>\n );\n }\n\n if (error || !channel) {\n return (\n <div className=\"flex flex-col items-center justify-center min-h-screen gap-4\">\n <AlertCircle className=\"size-12 text-status-error-text\" />\n <h1 className=\"text-xl font-semibold\">\n {tr('channel.channelNotFound', 'Channel not found')}\n </h1>\n <button\n type=\"button\"\n onClick={() => navigate('../list')}\n className=\"text-primary hover:underline\"\n >\n {tr('channel.backToChannels', 'Back to channels')}\n </button>\n </div>\n );\n }\n\n return (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_UPDATE}>\n <div className=\"min-h-screen bg-bg-surface\">\n {/* Header */}\n <div className=\"border-b bg-bg-surface\">\n <div className=\"container mx-auto px-6 py-4\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={() => navigate(`/channels/${channelId}`)}\n className=\"p-2 hover:bg-bg-sunken rounded-lg transition-colors\"\n >\n <ArrowLeft className=\"size-5 \" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold\">{tr('channel.editChannel', 'Edit Channel')}</h1>\n <p className=\"text-sm text-text-secondary\">\n {tr('channel.updateChannelConfig', 'Update channel configuration')}\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {/* Form */}\n <div className=\"container mx-auto px-6 py-8 max-w-2xl\">\n <div className=\"space-y-6\">\n {/* Page purpose */}\n <PagePurpose icon={<Save size={15} aria-hidden=\"true\" />}>\n {tr(\n 'channel.editChannelPurpose',\n \"Change how this channel behaves — its name, description, priority and status. The platform and provider stay fixed (they define what the channel is); to swap credentials use the channel's connection instead. Use this to rename a channel, bump its priority, or temporarily deactivate it without deleting it.\"\n )}\n </PagePurpose>\n\n {/* Error Alert */}\n {saveError && (\n <div className=\"p-4 rounded-lg bg-status-error-bg/10 border border-status-error-border/20 flex items-center gap-3\">\n <AlertCircle className=\"size-5 text-status-error-text shrink-0\" />\n <p className=\"text-sm text-status-error-text\">{saveError}</p>\n </div>\n )}\n\n {/* Channel Info (read-only) */}\n <GlassCard treatment=\"insight\" className=\"p-4 border-border-seam space-y-2\">\n <div className=\"flex items-center gap-2\">\n {selectedPlatform && (\n <>\n {(() => {\n const Icon = selectedPlatform.icon;\n return <Icon className=\"size-5 text-text-secondary\" />;\n })()}\n <span className=\"font-medium\">\n {tr(selectedPlatform.labelKey, selectedPlatform.labelFallback)}\n </span>\n </>\n )}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'channel.platformLockedHint',\n 'Platform cannot be changed after channel creation. Create a new channel to use a different platform.'\n )}\n </p>\n </GlassCard>\n\n {/* Channel fields — the editable core of this page */}\n <EmphasisPanel className=\"p-5 space-y-6\">\n {/* Name */}\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr('channel.channelName', 'Channel Name')} *\n </label>\n <input\n aria-label={tr(\n 'channel.editNamePlaceholder',\n 'e.g., Production Email, Customer SMS'\n )}\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={tr(\n 'channel.editNamePlaceholder',\n 'e.g., Production Email, Customer SMS'\n )}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </div>\n\n {/* Description */}\n <div className=\"space-y-2\">\n <label htmlFor=\"channel-edit-description\" className=\"text-sm font-medium\">\n {tr('channel.description', 'Description')}\n </label>\n <MarkdownEditor\n id=\"channel-edit-description\"\n value={description}\n onChange={setDescription}\n aria-label={tr(\n 'channel.editDescriptionPlaceholder',\n 'Optional description for this channel'\n )}\n placeholder={tr(\n 'channel.editDescriptionPlaceholder',\n 'Optional description for this channel'\n )}\n rows={3}\n />\n </div>\n\n {/* Adapter Type */}\n {selectedPlatform && (\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr('channel.adapterProvider', 'Adapter / Provider')}\n </label>\n <select\n value={adapterType}\n onChange={(e) => setAdapterType(e.target.value as AdapterType)}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n {selectedPlatform.adapters.map((adapter) => (\n <option key={adapter.value} value={adapter.value}>\n {tr(adapter.labelKey, adapter.labelFallback)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Priority & Status */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr('channel.priority', 'Priority')}\n </label>\n <select\n value={priority}\n onChange={(e) => setPriority(Number(e.target.value))}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n {PRIORITY_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'channel.priorityFailoverHint',\n 'Higher priority channels are used first in failover'\n )}\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">{tr('channel.status', 'Status')}</label>\n <select\n value={status}\n onChange={(e) => setStatus(e.target.value as ChannelStatus)}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"INACTIVE\">\n {tr('channel.statusLabel.inactive', 'Inactive')}\n </option>\n <option value=\"ACTIVE\">{tr('channel.statusLabel.active', 'Active')}</option>\n <option value=\"SUSPENDED\">\n {tr('channel.statusLabel.suspended', 'Suspended')}\n </option>\n </select>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Actions */}\n <div className=\"flex items-center justify-between pt-6 border-t\">\n {/* Delete */}\n <div>\n {!deleteConfirm ? (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_DELETE}>\n <button\n type=\"button\"\n onClick={() => setDeleteConfirm(true)}\n className=\"px-4 py-2 text-sm text-status-error-text hover:bg-status-error-bg/10 rounded-lg transition-colors flex items-center gap-2\"\n >\n <Trash2 className=\"size-4 \" />\n {tr('channel.deleteChannel', 'Delete Channel')}\n </button>\n </PermissionGuard>\n ) : (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">\n {tr('channel.confirmDelete', 'Confirm delete?')}\n </span>\n <button\n type=\"button\"\n onClick={handleDelete}\n disabled={isDeleting}\n className=\"px-4 py-2 text-sm bg-status-error-bg text-status-error-text rounded-lg hover:bg-status-error-bg/90 transition-colors flex items-center gap-2\"\n >\n {isDeleting ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Trash2 className=\"size-4 \" />\n )}\n {tr('channel.delete', 'Delete')}\n </button>\n <button\n type=\"button\"\n onClick={() => setDeleteConfirm(false)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-lg transition-colors\"\n >\n {tr('channel.cancel', 'Cancel')}\n </button>\n </div>\n )}\n </div>\n\n {/* Save */}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(`/channels/${channelId}`)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-lg transition-colors\"\n >\n {tr('channel.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={isSaving || !name.trim()}\n className=\"px-6 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-colors flex items-center gap-2 disabled:opacity-50\"\n >\n {isSaving ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Save className=\"size-4 \" />\n )}\n {tr('channel.saveChanges', 'Save Changes')}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAsDA,SAAgB,IAAkB;CAChC,IAAM,IAAW,GAAa,EACxB,EAAE,iBAAc,GAAkC,EAClD,EAAE,YAAS,eAAW,cAAU,EAAW,EAAW,EACtD,EAAE,kBAAe,qBAAkB,GAAa,EAChD,IAAK,GAAO,EAEZ,IAAqC,QACnC;EACJ;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OAAO;GACP,UAAU;IACR;KAAE,OAAO;KAAW,UAAU;KAA0B,eAAe;KAAW;IAClF;KAAE,OAAO;KAAW,UAAU;KAA2B,eAAe;KAAW;IACnF;KAAE,OAAO;KAAY,UAAU;KAA4B,eAAe;KAAY;IACtF;KAAE,OAAO;KAAY,UAAU;KAA4B,eAAe;KAAY;IACtF;KAAE,OAAO;KAAU,UAAU;KAA0B,eAAe;KAAU;IAChF;KACE,OAAO;KACP,UAAU;KACV,eAAe;KAChB;IACD;KAAE,OAAO;KAAQ,UAAU;KAAwB,eAAe;KAAe;IAClF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OACE;GACF,UAAU;IACR;KAAE,OAAO;KAAc,UAAU;KAA0B,eAAe;KAAU;IACpF;KAAE,OAAO;KAAW,UAAU;KAA0B,eAAe;KAAW;IAClF;KAAE,OAAO;KAAU,UAAU;KAA0B,eAAe;KAAU;IAChF;KAAE,OAAO;KAAS,UAAU;KAAyB,eAAe;KAAS;IAC7E;KACE,OAAO;KACP,UAAU;KACV,eAAe;KAChB;IACD;KAAE,OAAO;KAAW,UAAU;KAA2B,eAAe;KAAW;IACpF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OAAO;GACP,UAAU;IACR;KACE,OAAO;KACP,UAAU;KACV,eAAe;KAChB;IACD;KACE,OAAO;KACP,UAAU;KACV,eAAe;KAChB;IACD;KAAE,OAAO;KAAa,UAAU;KAA6B,eAAe;KAAa;IACzF;KAAE,OAAO;KAAQ,UAAU;KAAwB,eAAe;KAAa;IAChF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OACE;GACF,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;IAChB,CACF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OACE;GACF,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;IAChB,EACD;IACE,OAAO;IACP,UAAU;IACV,eAAe;IAChB,CACF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OAAO;GACP,UAAU,CACR;IAAE,OAAO;IAAa,UAAU;IAA4B,eAAe;IAAa,CACzF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OAAO;GACP,UAAU,CACR;IAAE,OAAO;IAAa,UAAU;IAA4B,eAAe;IAAa,CACzF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OAAO;GACP,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;IAChB,CACF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OAAO;GACP,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;IAChB,CACF;GACF;EACD;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAM;GACN,OAAO;GACP,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;IAChB,CACF;GACF;EACF,EACD,EAAE,CACH,EAEK,IAAmB,QACjB;EACJ;GAAE,OAAO;GAAG,OAAO,EAAG,gCAAgC,aAAa;GAAE;EACrE;GAAE,OAAO;GAAG,OAAO,EAAG,6BAA6B,UAAU;GAAE;EAC/D;GAAE,OAAO;GAAG,OAAO,EAAG,gCAAgC,aAAa;GAA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"}
|
|
1
|
+
{"version":3,"file":"EditChannelPage.js","names":["_Fragment","EditChannelPage","navigate","useNavigate","useParams","useChannel","channelId","useChannels","tr","useTr","PLATFORM_OPTIONS","useMemo","Mail","Smartphone","Bell","Inbox","MessageSquare","Hash","Users","MessageCircle","Send","PRIORITY_OPTIONS","name","setName","useState","description","setDescription","adapterType","setAdapterType","priority","setPriority","status","setStatus","isSaving","setIsSaving","isDeleting","setIsDeleting","saveError","setSaveError","deleteConfirm","setDeleteConfirm","loadedChannelIdRef","useRef","channel","currentPlatform","selectedPlatform","p","isLoading","Loader2","error","AlertCircle","PermissionGuard","CHANNEL_PERMISSIONS","ArrowLeft","PagePurpose","Save","GlassCard","Fragment","Icon","EmphasisPanel","MarkdownEditor","adapter","option","nativeImpact","deleteChannel","nativeNotify","err","message","Trash2","input","updateChannel"],"sources":["../../../../../src/channel/modules/channels/pages/EditChannelPage.tsx"],"sourcesContent":["/**\n * Edit Channel Page\n *\n * Allows editing an existing channel's configuration.\n * Uses the same form structure as CreateChannelPage but pre-fills existing values.\n */\n\nimport { useState, useEffect, useRef, useMemo } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport { useTr } from '../../../hooks/useTr';\nimport {\n ArrowLeft,\n Save,\n Loader2,\n AlertCircle,\n Mail,\n Smartphone,\n Bell,\n Inbox,\n MessageSquare,\n Hash,\n Users,\n MessageCircle,\n Send,\n Trash2,\n} from 'lucide-react';\nimport { useChannel, useChannels } from '../../../hooks/useChannels';\nimport {\n type ChannelPlatform,\n type AdapterType,\n type ChannelStatus,\n type UpdateChannelInput,\n} from '../../../hooks/useChannels';\nimport { EmphasisPanel, GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { nativeImpact, nativeNotify } from '../../../../utils/nativeBridge';\nimport { PermissionGuard } from '../../../components/PermissionGuard';\nimport { CHANNEL_PERMISSIONS } from '../../../constants/permissions';\nimport { MarkdownEditor } from '../../../components/MarkdownEditor';\n\ntype PlatformOption = {\n value: ChannelPlatform;\n labelKey: string;\n labelFallback: string;\n descriptionKey: string;\n descriptionFallback: string;\n icon: typeof Mail;\n color: string;\n adapters: { value: AdapterType; labelKey: string; labelFallback: string }[];\n};\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function EditChannelPage() {\n const navigate = useNavigate();\n const { channelId } = useParams<{ channelId: string }>();\n const { channel, isLoading, error } = useChannel(channelId!);\n const { updateChannel, deleteChannel } = useChannels();\n const tr = useTr();\n\n const PLATFORM_OPTIONS: PlatformOption[] = useMemo(\n () => [\n {\n value: 'EMAIL',\n labelKey: 'channel.platformLabel.email',\n labelFallback: 'Email',\n descriptionKey: 'channel.platformDescription.emailDescription',\n descriptionFallback: 'Send emails via various providers',\n icon: Mail,\n color: 'text-status-info-text bg-status-info-bg-subtle border-status-info-border',\n adapters: [\n { value: 'AWS_SES', labelKey: 'channel.adapter.awsSes', labelFallback: 'AWS SES' },\n { value: 'MAILGUN', labelKey: 'channel.adapter.mailgun', labelFallback: 'Mailgun' },\n { value: 'POSTMARK', labelKey: 'channel.adapter.postmark', labelFallback: 'Postmark' },\n { value: 'MANDRILL', labelKey: 'channel.adapter.mandrill', labelFallback: 'Mandrill' },\n { value: 'RESEND', labelKey: 'channel.adapter.resend', labelFallback: 'Resend' },\n {\n value: 'AZURE_ACS',\n labelKey: 'channel.adapter.azureAcs',\n labelFallback: 'Azure Communication Services',\n },\n { value: 'SMTP', labelKey: 'channel.adapter.smtp', labelFallback: 'Custom SMTP' },\n ],\n },\n {\n value: 'SMS',\n labelKey: 'channel.platformLabel.sms',\n labelFallback: 'SMS',\n descriptionKey: 'channel.platformDescription.smsDescription',\n descriptionFallback: 'Send text messages',\n icon: Smartphone,\n color:\n 'text-status-success-text bg-status-success-bg-subtle border-status-success-border/30',\n adapters: [\n { value: 'TWILIO_SMS', labelKey: 'channel.adapter.twilio', labelFallback: 'Twilio' },\n { value: 'AWS_SNS', labelKey: 'channel.adapter.awsSns', labelFallback: 'AWS SNS' },\n { value: 'VONAGE', labelKey: 'channel.adapter.vonage', labelFallback: 'Vonage' },\n { value: 'PLIVO', labelKey: 'channel.adapter.plivo', labelFallback: 'Plivo' },\n {\n value: 'MESSAGEBIRD',\n labelKey: 'channel.adapter.messagebird',\n labelFallback: 'MessageBird',\n },\n { value: 'INFOBIP', labelKey: 'channel.adapter.infobip', labelFallback: 'Infobip' },\n ],\n },\n {\n value: 'PUSH',\n labelKey: 'channel.platformLabel.push',\n labelFallback: 'Push',\n descriptionKey: 'channel.platformDescription.pushDescription',\n descriptionFallback: 'Mobile & web push',\n icon: Bell,\n color: 'text-accent-purple bg-accent-purple-subtle border-accent-purple/30',\n adapters: [\n {\n value: 'FCM',\n labelKey: 'channel.adapter.fcm',\n labelFallback: 'Firebase Cloud Messaging',\n },\n {\n value: 'APNS',\n labelKey: 'channel.adapter.apns',\n labelFallback: 'Apple Push Notification Service',\n },\n { value: 'ONESIGNAL', labelKey: 'channel.adapter.onesignal', labelFallback: 'OneSignal' },\n { value: 'EXPO', labelKey: 'channel.adapter.expo', labelFallback: 'Expo Push' },\n ],\n },\n {\n value: 'INAPP',\n labelKey: 'channel.platformLabel.inApp',\n labelFallback: 'In-App',\n descriptionKey: 'channel.platformDescription.inAppDescription',\n descriptionFallback: 'Internal in-app notifications',\n icon: Inbox,\n color:\n 'text-status-warning-text bg-status-warning-bg-subtle border-status-warning-border/30',\n adapters: [\n {\n value: 'INAPP_NATIVE',\n labelKey: 'channel.adapter.inAppNative',\n labelFallback: 'Native In-App',\n },\n ],\n },\n {\n value: 'WHATSAPP',\n labelKey: 'channel.platformLabel.whatsapp',\n labelFallback: 'WhatsApp',\n descriptionKey: 'channel.platformDescription.whatsappDescription',\n descriptionFallback: 'WhatsApp Business messaging',\n icon: MessageSquare,\n color:\n 'text-status-success-text bg-status-success-bg-subtle border-status-success-border/30',\n adapters: [\n {\n value: 'WHATSAPP_CLOUD',\n labelKey: 'channel.adapter.whatsappCloud',\n labelFallback: 'WhatsApp Cloud API',\n },\n {\n value: 'WHATSAPP_TWILIO',\n labelKey: 'channel.adapter.whatsappTwilio',\n labelFallback: 'WhatsApp via Twilio',\n },\n ],\n },\n {\n value: 'SLACK',\n labelKey: 'channel.platformLabel.slack',\n labelFallback: 'Slack',\n descriptionKey: 'channel.platformDescription.slackDescription',\n descriptionFallback: 'Slack bot & channels',\n icon: Hash,\n color: 'text-accent-purple bg-accent-purple-subtle border-accent-purple/30',\n adapters: [\n { value: 'SLACK_BOT', labelKey: 'channel.adapter.slackBot', labelFallback: 'Slack Bot' },\n ],\n },\n {\n value: 'TEAMS',\n labelKey: 'channel.platformLabel.teams',\n labelFallback: 'Teams',\n descriptionKey: 'channel.platformDescription.teamsDescription',\n descriptionFallback: 'Microsoft Teams',\n icon: Users,\n color: 'text-status-info-text bg-status-info-bg-subtle border-status-info-border',\n adapters: [\n { value: 'TEAMS_BOT', labelKey: 'channel.adapter.teamsBot', labelFallback: 'Teams Bot' },\n ],\n },\n {\n value: 'DISCORD',\n labelKey: 'channel.platformLabel.discord',\n labelFallback: 'Discord',\n descriptionKey: 'channel.platformDescription.discordDescription',\n descriptionFallback: 'Discord bots & webhooks',\n icon: MessageCircle,\n color: 'text-accent-indigo bg-accent-indigo-subtle border-accent-indigo/30',\n adapters: [\n {\n value: 'DISCORD_BOT',\n labelKey: 'channel.adapter.discordBot',\n labelFallback: 'Discord Bot',\n },\n ],\n },\n {\n value: 'WEBCHAT',\n labelKey: 'channel.platformLabel.webchat',\n labelFallback: 'Webchat',\n descriptionKey: 'channel.platformDescription.webchatDescription',\n descriptionFallback: 'Website live chat',\n icon: MessageSquare,\n color: 'text-accent-teal bg-accent-teal-subtle border-accent-teal/30',\n adapters: [\n {\n value: 'WEBCHAT_NATIVE',\n labelKey: 'channel.adapter.webchatNative',\n labelFallback: 'Native Webchat',\n },\n ],\n },\n {\n value: 'WEBHOOK',\n labelKey: 'channel.platformLabel.webhook',\n labelFallback: 'Webhook',\n descriptionKey: 'channel.platformDescription.webhookDescription',\n descriptionFallback: 'Generic HTTP webhook',\n icon: Send,\n color: 'text-text-secondary bg-bg-sunken/50 border-border-subtle',\n adapters: [\n {\n value: 'WEBHOOK_HTTP',\n labelKey: 'channel.adapter.webhookHttp',\n labelFallback: 'HTTP Webhook',\n },\n ],\n },\n ],\n []\n );\n\n const PRIORITY_OPTIONS = useMemo(\n () => [\n { value: 0, label: tr('channel.priorityLabel.lowest', '0 - Lowest') },\n { value: 1, label: tr('channel.priorityLabel.low', '1 - Low') },\n { value: 2, label: tr('channel.priorityLabel.normal', '2 - Normal') },\n { value: 3, label: tr('channel.priorityLabel.high', '3 - High') },\n { value: 4, label: tr('channel.priorityLabel.highest', '4 - Highest') },\n ],\n [tr]\n );\n\n // Form state\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [adapterType, setAdapterType] = useState<AdapterType>('AWS_SES');\n const [priority, setPriority] = useState(2);\n const [status, setStatus] = useState<ChannelStatus>('INACTIVE');\n\n // UI state\n const [isSaving, setIsSaving] = useState(false);\n const [isDeleting, setIsDeleting] = useState(false);\n const [saveError, setSaveError] = useState<string | null>(null);\n const [deleteConfirm, setDeleteConfirm] = useState(false);\n\n // Load channel data into form — guard against re-initialization and defer\n // the state update to a microtask so setState does not run synchronously\n // inside the effect body (react-hooks/set-state-in-effect).\n const loadedChannelIdRef = useRef<string | null>(null);\n useEffect(() => {\n if (channel && channel.id !== loadedChannelIdRef.current) {\n loadedChannelIdRef.current = channel.id;\n void Promise.resolve().then(() => {\n setName(channel.name || '');\n setDescription(channel.description || '');\n setAdapterType((channel.adapterType || 'AWS_SES') as AdapterType);\n setPriority(channel.priority || 2);\n setStatus((channel.status || 'INACTIVE') as ChannelStatus);\n });\n }\n }, [channel]);\n\n // Update adapter options when platform changes\n const currentPlatform = (channel?.platform || 'EMAIL') as ChannelPlatform;\n const selectedPlatform = PLATFORM_OPTIONS.find((p) => p.value === currentPlatform);\n\n const handleSave = async () => {\n if (!channelId) return;\n\n if (!name.trim()) {\n setSaveError(tr('channel.validation.nameRequired', 'Channel name is required'));\n return;\n }\n\n setIsSaving(true);\n setSaveError(null);\n\n try {\n const input: UpdateChannelInput = {\n name: name.trim(),\n description: description.trim() || undefined,\n adapterType,\n priority,\n status,\n };\n\n const result = await updateChannel(channelId, input);\n if (result) {\n navigate(`/channels/${channelId}`);\n } else {\n setSaveError(tr('channel.updateFailed', 'Failed to update channel'));\n }\n } catch (err: unknown) {\n const message =\n err instanceof Error ? err.message : tr('channel.updateFailed', 'Failed to update channel');\n setSaveError(message);\n } finally {\n setIsSaving(false);\n }\n };\n\n const handleDelete = async () => {\n if (!channelId || !deleteConfirm) return;\n void nativeImpact('medium');\n\n setIsDeleting(true);\n try {\n const success = await deleteChannel(channelId);\n if (success) {\n void nativeNotify('success');\n navigate('../list');\n } else {\n void nativeNotify('error');\n }\n } catch (err: unknown) {\n void nativeNotify('error');\n const message =\n err instanceof Error ? err.message : tr('channel.deleteFailed', 'Failed to delete channel');\n setSaveError(message);\n setIsDeleting(false);\n }\n };\n\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center min-h-screen\">\n <Loader2 className=\"size-8 animate-spin text-text-secondary\" />\n </div>\n );\n }\n\n if (error || !channel) {\n return (\n <div className=\"flex flex-col items-center justify-center min-h-screen gap-4\">\n <AlertCircle className=\"size-12 text-status-error-text\" />\n <h1 className=\"text-xl font-semibold\">\n {tr('channel.channelNotFound', 'Channel not found')}\n </h1>\n <button\n type=\"button\"\n onClick={() => navigate('../list')}\n className=\"text-primary hover:underline\"\n >\n {tr('channel.backToChannels', 'Back to channels')}\n </button>\n </div>\n );\n }\n\n return (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_UPDATE}>\n <div className=\"min-h-screen bg-bg-surface\">\n {/* Header */}\n <div className=\"border-b bg-bg-surface\">\n <div className=\"container mx-auto px-6 py-4\">\n <div className=\"flex items-center gap-4\">\n <button\n type=\"button\"\n onClick={() => navigate(`/channels/${channelId}`)}\n className=\"p-2 hover:bg-bg-sunken rounded-lg transition-colors\"\n >\n <ArrowLeft className=\"size-5 \" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold\">{tr('channel.editChannel', 'Edit Channel')}</h1>\n <p className=\"text-sm text-text-secondary\">\n {tr('channel.updateChannelConfig', 'Update channel configuration')}\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {/* Form */}\n <div className=\"container mx-auto px-6 py-8 max-w-2xl\">\n <div className=\"space-y-6\">\n {/* Page purpose */}\n <PagePurpose icon={<Save size={15} aria-hidden=\"true\" />}>\n {tr(\n 'channel.editChannelPurpose',\n \"Change how this channel behaves — its name, description, priority and status. The platform and provider stay fixed (they define what the channel is); to swap credentials use the channel's connection instead. Use this to rename a channel, bump its priority, or temporarily deactivate it without deleting it.\"\n )}\n </PagePurpose>\n\n {/* Error Alert */}\n {saveError && (\n <div className=\"p-4 rounded-lg bg-status-error-bg/10 border border-status-error-border/20 flex items-center gap-3\">\n <AlertCircle className=\"size-5 text-status-error-text shrink-0\" />\n <p className=\"text-sm text-status-error-text\">{saveError}</p>\n </div>\n )}\n\n {/* Channel Info (read-only) */}\n <GlassCard treatment=\"insight\" className=\"p-4 border-border-seam space-y-2\">\n <div className=\"flex items-center gap-2\">\n {selectedPlatform && (\n <>\n {(() => {\n const Icon = selectedPlatform.icon;\n return <Icon className=\"size-5 text-text-secondary\" />;\n })()}\n <span className=\"font-medium\">\n {tr(selectedPlatform.labelKey, selectedPlatform.labelFallback)}\n </span>\n </>\n )}\n </div>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'channel.platformLockedHint',\n 'Platform cannot be changed after channel creation. Create a new channel to use a different platform.'\n )}\n </p>\n </GlassCard>\n\n {/* Channel fields — the editable core of this page */}\n <EmphasisPanel className=\"p-5 space-y-6\">\n {/* Name */}\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr('channel.channelName', 'Channel Name')} *\n </label>\n <input\n aria-label={tr(\n 'channel.editNamePlaceholder',\n 'e.g., Production Email, Customer SMS'\n )}\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder={tr(\n 'channel.editNamePlaceholder',\n 'e.g., Production Email, Customer SMS'\n )}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary\"\n />\n </div>\n\n {/* Description */}\n <div className=\"space-y-2\">\n <label htmlFor=\"channel-edit-description\" className=\"text-sm font-medium\">\n {tr('channel.description', 'Description')}\n </label>\n <MarkdownEditor\n id=\"channel-edit-description\"\n value={description}\n onChange={setDescription}\n aria-label={tr(\n 'channel.editDescriptionPlaceholder',\n 'Optional description for this channel'\n )}\n placeholder={tr(\n 'channel.editDescriptionPlaceholder',\n 'Optional description for this channel'\n )}\n rows={3}\n />\n </div>\n\n {/* Adapter Type */}\n {selectedPlatform && (\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr('channel.adapterProvider', 'Adapter / Provider')}\n </label>\n <select\n value={adapterType}\n onChange={(e) => setAdapterType(e.target.value as AdapterType)}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n {selectedPlatform.adapters.map((adapter) => (\n <option key={adapter.value} value={adapter.value}>\n {tr(adapter.labelKey, adapter.labelFallback)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Priority & Status */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">\n {tr('channel.priority', 'Priority')}\n </label>\n <select\n value={priority}\n onChange={(e) => setPriority(Number(e.target.value))}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n {PRIORITY_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'channel.priorityFailoverHint',\n 'Higher priority channels are used first in failover'\n )}\n </p>\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">{tr('channel.status', 'Status')}</label>\n <select\n value={status}\n onChange={(e) => setStatus(e.target.value as ChannelStatus)}\n className=\"w-full px-4 py-2 rounded-lg border bg-bg-surface focus:outline-none focus:ring-2 focus:ring-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n >\n <option value=\"INACTIVE\">\n {tr('channel.statusLabel.inactive', 'Inactive')}\n </option>\n <option value=\"ACTIVE\">{tr('channel.statusLabel.active', 'Active')}</option>\n <option value=\"SUSPENDED\">\n {tr('channel.statusLabel.suspended', 'Suspended')}\n </option>\n </select>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Actions */}\n <div className=\"flex items-center justify-between pt-6 border-t\">\n {/* Delete */}\n <div>\n {!deleteConfirm ? (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_DELETE}>\n <button\n type=\"button\"\n onClick={() => setDeleteConfirm(true)}\n className=\"px-4 py-2 text-sm text-status-error-text hover:bg-status-error-bg/10 rounded-lg transition-colors flex items-center gap-2\"\n >\n <Trash2 className=\"size-4 \" />\n {tr('channel.deleteChannel', 'Delete Channel')}\n </button>\n </PermissionGuard>\n ) : (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm text-text-secondary\">\n {tr('channel.confirmDelete', 'Confirm delete?')}\n </span>\n <button\n type=\"button\"\n onClick={handleDelete}\n disabled={isDeleting}\n className=\"px-4 py-2 text-sm bg-status-error-bg text-status-error-text rounded-lg hover:bg-status-error-bg/90 transition-colors flex items-center gap-2\"\n >\n {isDeleting ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Trash2 className=\"size-4 \" />\n )}\n {tr('channel.delete', 'Delete')}\n </button>\n <button\n type=\"button\"\n onClick={() => setDeleteConfirm(false)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-lg transition-colors\"\n >\n {tr('channel.cancel', 'Cancel')}\n </button>\n </div>\n )}\n </div>\n\n {/* Save */}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(`/channels/${channelId}`)}\n className=\"px-4 py-2 text-sm text-text-secondary hover:bg-bg-sunken rounded-lg transition-colors\"\n >\n {tr('channel.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={handleSave}\n disabled={isSaving || !name.trim()}\n className=\"px-6 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg/90 transition-colors flex items-center gap-2 disabled:opacity-50\"\n >\n {isSaving ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Save className=\"size-4 \" />\n )}\n {tr('channel.saveChanges', 'Save Changes')}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAsDA,SAAgBC,IAAkB;CAChC,IAAMC,IAAWC,EAAY,GACvB,EAAE,iBAAcC,EAAiC,GACjD,EAAE,YAAS,eAAW,cAAUC,EAAWC,CAAU,GACrD,EAAE,kBAAe,qBAAkBC,EAAY,GAC/CC,IAAKC,EAAM,GAEXC,IAAqCC,QACnC;EACJ;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OAAO;GACP,UAAU;IACR;KAAE,OAAO;KAAW,UAAU;KAA0B,eAAe;IAAU;IACjF;KAAE,OAAO;KAAW,UAAU;KAA2B,eAAe;IAAU;IAClF;KAAE,OAAO;KAAY,UAAU;KAA4B,eAAe;IAAW;IACrF;KAAE,OAAO;KAAY,UAAU;KAA4B,eAAe;IAAW;IACrF;KAAE,OAAO;KAAU,UAAU;KAA0B,eAAe;IAAS;IAC/E;KACE,OAAO;KACP,UAAU;KACV,eAAe;IACjB;IACA;KAAE,OAAO;KAAQ,UAAU;KAAwB,eAAe;IAAc;GAClF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OACE;GACF,UAAU;IACR;KAAE,OAAO;KAAc,UAAU;KAA0B,eAAe;IAAS;IACnF;KAAE,OAAO;KAAW,UAAU;KAA0B,eAAe;IAAU;IACjF;KAAE,OAAO;KAAU,UAAU;KAA0B,eAAe;IAAS;IAC/E;KAAE,OAAO;KAAS,UAAU;KAAyB,eAAe;IAAQ;IAC5E;KACE,OAAO;KACP,UAAU;KACV,eAAe;IACjB;IACA;KAAE,OAAO;KAAW,UAAU;KAA2B,eAAe;IAAU;GACpF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OAAO;GACP,UAAU;IACR;KACE,OAAO;KACP,UAAU;KACV,eAAe;IACjB;IACA;KACE,OAAO;KACP,UAAU;KACV,eAAe;IACjB;IACA;KAAE,OAAO;KAAa,UAAU;KAA6B,eAAe;IAAY;IACxF;KAAE,OAAO;KAAQ,UAAU;KAAwB,eAAe;IAAY;GAChF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OACE;GACF,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;GACjB,CACF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OACE;GACF,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;GACjB,GACA;IACE,OAAO;IACP,UAAU;IACV,eAAe;GACjB,CACF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OAAO;GACP,UAAU,CACR;IAAE,OAAO;IAAa,UAAU;IAA4B,eAAe;GAAY,CACzF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OAAO;GACP,UAAU,CACR;IAAE,OAAO;IAAa,UAAU;IAA4B,eAAe;GAAY,CACzF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMC;GACN,OAAO;GACP,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;GACjB,CACF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMH;GACN,OAAO;GACP,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;GACjB,CACF;EACF;EACA;GACE,OAAO;GACP,UAAU;GACV,eAAe;GACf,gBAAgB;GAChB,qBAAqB;GACrB,MAAMI;GACN,OAAO;GACP,UAAU,CACR;IACE,OAAO;IACP,UAAU;IACV,eAAe;GACjB,CACF;EACF;CACF,GACA,CAAC,CACH,GAEMC,IAAmBV,QACjB;EACJ;GAAE,OAAO;GAAG,OAAOH,EAAG,gCAAgC,YAAY;EAAE;EACpE;GAAE,OAAO;GAAG,OAAOA,EAAG,6BAA6B,SAAS;EAAE;EAC9D;GAAE,OAAO;GAAG,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"}
|