@burdenoff/microfe-channel 2026.830.1 → 2026.1013.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channel/ChannelRoot.d.ts.map +1 -1
- package/dist/channel/ChannelRoot.js +32 -35
- package/dist/channel/ChannelRoot.js.map +1 -1
- package/dist/channel/components/AdapterCredentialsForm.d.ts.map +1 -1
- package/dist/channel/components/AdapterCredentialsForm.js +52 -58
- package/dist/channel/components/AdapterCredentialsForm.js.map +1 -1
- package/dist/channel/components/FeatureNotEnabled.d.ts.map +1 -1
- package/dist/channel/components/FeatureNotEnabled.js +27 -22
- package/dist/channel/components/FeatureNotEnabled.js.map +1 -1
- package/dist/channel/components/MarkdownEditor.d.ts.map +1 -1
- package/dist/channel/components/MarkdownEditor.js +78 -77
- package/dist/channel/components/MarkdownEditor.js.map +1 -1
- package/dist/channel/components/PermissionGuard.d.ts.map +1 -1
- package/dist/channel/components/PermissionGuard.js +6 -9
- package/dist/channel/components/PermissionGuard.js.map +1 -1
- package/dist/channel/hooks/useTr.d.ts +17 -0
- package/dist/channel/hooks/useTr.d.ts.map +1 -0
- package/dist/channel/hooks/useTr.js +14 -0
- package/dist/channel/hooks/useTr.js.map +1 -0
- package/dist/channel/modules/channels/i18n.js +24 -24
- package/dist/channel/modules/channels/i18n.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.js +2 -2
- package/dist/channel/modules/channels/pages/ChannelDashboardPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.js +232 -226
- package/dist/channel/modules/channels/pages/ChannelSettingsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ChannelUsersPage.js +152 -146
- package/dist/channel/modules/channels/pages/ChannelUsersPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js +112 -114
- package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/CreateChannelPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/CreateChannelPage.js +300 -269
- package/dist/channel/modules/channels/pages/CreateChannelPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/CreateConnectionPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/CreateConnectionPage.js +108 -102
- package/dist/channel/modules/channels/pages/CreateConnectionPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/EditChannelPage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/EditChannelPage.js +384 -343
- package/dist/channel/modules/channels/pages/EditChannelPage.js.map +1 -1
- package/dist/channel/modules/channels/pages/SendMessagePage.d.ts.map +1 -1
- package/dist/channel/modules/channels/pages/SendMessagePage.js +170 -156
- package/dist/channel/modules/channels/pages/SendMessagePage.js.map +1 -1
- package/dist/channel/pages/ChannelLandingPage.d.ts.map +1 -1
- package/dist/channel/pages/ChannelLandingPage.js +47 -50
- package/dist/channel/pages/ChannelLandingPage.js.map +1 -1
- package/dist/translations/en.d.ts +271 -4
- package/dist/translations/en.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChannelRoot.d.ts","sourceRoot":"","sources":["../../src/channel/ChannelRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,OAAO,KAAK,EAAW,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"ChannelRoot.d.ts","sourceRoot":"","sources":["../../src/channel/ChannelRoot.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,OAAO,KAAK,EAAW,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAwF5C,CAAC"}
|
|
@@ -1,75 +1,72 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { useTr as e } from "./hooks/useTr.js";
|
|
2
|
+
import { ChannelProvider as t } from "./providers/ChannelProvider.js";
|
|
3
|
+
import { ChannelRoutes as n } from "./ChannelRoutes.js";
|
|
4
|
+
import { useEffect as r } from "react";
|
|
4
5
|
import { ErrorBoundary as i } from "@burdenoff/fe-libs/shared/components";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { jsx as u } from "react/jsx-runtime";
|
|
6
|
+
import { Cable as a, Radio as o, Send as s, Settings as c } from "lucide-react";
|
|
7
|
+
import { jsx as l } from "react/jsx-runtime";
|
|
8
8
|
//#region src/channel/ChannelRoot.tsx
|
|
9
|
-
var
|
|
10
|
-
let { registerNavItems:
|
|
11
|
-
let n = h(e);
|
|
12
|
-
return n === e ? t : n;
|
|
13
|
-
}, [h]), _ = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
|
|
9
|
+
var u = (u) => {
|
|
10
|
+
let { registerNavItems: d, registerFooterItems: f, basePath: p = "/" } = u, m = e(), h = (e, t) => (e.endsWith("/") ? e.slice(0, -1) : e) + (t.startsWith("/") ? t : `/${t}`);
|
|
14
11
|
return r(() => {
|
|
15
|
-
if (
|
|
12
|
+
if (d) return d([
|
|
16
13
|
{
|
|
17
14
|
id: "channel-channels",
|
|
18
|
-
label:
|
|
19
|
-
path:
|
|
20
|
-
icon: /* @__PURE__ */
|
|
15
|
+
label: m("channel.channels", "Channels"),
|
|
16
|
+
path: p === "/" ? "/" : h(p, "list"),
|
|
17
|
+
icon: /* @__PURE__ */ l(o, { size: 20 }),
|
|
21
18
|
order: 100,
|
|
22
19
|
group: "channel"
|
|
23
20
|
},
|
|
24
21
|
{
|
|
25
22
|
id: "channel-connections",
|
|
26
|
-
label:
|
|
27
|
-
path:
|
|
28
|
-
icon: /* @__PURE__ */
|
|
23
|
+
label: m("channel.connections", "Connections"),
|
|
24
|
+
path: h(p, "connections"),
|
|
25
|
+
icon: /* @__PURE__ */ l(a, { size: 20 }),
|
|
29
26
|
order: 110,
|
|
30
27
|
group: "channel"
|
|
31
28
|
},
|
|
32
29
|
{
|
|
33
30
|
id: "channel-send",
|
|
34
|
-
label:
|
|
35
|
-
path:
|
|
36
|
-
icon: /* @__PURE__ */
|
|
31
|
+
label: m("channel.sendMessage", "Send Message"),
|
|
32
|
+
path: h(p, "send"),
|
|
33
|
+
icon: /* @__PURE__ */ l(s, { size: 20 }),
|
|
37
34
|
order: 120,
|
|
38
35
|
group: "channel"
|
|
39
36
|
},
|
|
40
37
|
{
|
|
41
38
|
id: "channel-settings",
|
|
42
|
-
label:
|
|
43
|
-
path:
|
|
44
|
-
icon: /* @__PURE__ */
|
|
39
|
+
label: m("channel.settings", "Settings"),
|
|
40
|
+
path: h(p, "settings"),
|
|
41
|
+
icon: /* @__PURE__ */ l(c, { size: 20 }),
|
|
45
42
|
order: 130,
|
|
46
43
|
group: "channel"
|
|
47
44
|
}
|
|
48
45
|
]);
|
|
49
46
|
}, [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
d,
|
|
48
|
+
p,
|
|
49
|
+
m
|
|
53
50
|
]), r(() => {
|
|
54
|
-
if (
|
|
51
|
+
if (f) return f([{
|
|
55
52
|
id: "channel-status",
|
|
56
|
-
label:
|
|
53
|
+
label: m("channel.channelsReady", "Channels Ready"),
|
|
57
54
|
type: "status",
|
|
58
55
|
order: 10,
|
|
59
56
|
section: "left"
|
|
60
57
|
}]);
|
|
61
|
-
}, [
|
|
62
|
-
fallback: /* @__PURE__ */
|
|
58
|
+
}, [f, m]), /* @__PURE__ */ l(i, {
|
|
59
|
+
fallback: /* @__PURE__ */ l("div", {
|
|
63
60
|
className: "p-6 text-center text-text-secondary",
|
|
64
61
|
children: "Something went wrong loading this module. Please refresh the page."
|
|
65
62
|
}),
|
|
66
|
-
children: /* @__PURE__ */
|
|
67
|
-
...
|
|
68
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ l(t, {
|
|
64
|
+
...u,
|
|
65
|
+
children: /* @__PURE__ */ l(n, {})
|
|
69
66
|
})
|
|
70
67
|
});
|
|
71
68
|
};
|
|
72
69
|
//#endregion
|
|
73
|
-
export {
|
|
70
|
+
export { u as ChannelRoot };
|
|
74
71
|
|
|
75
72
|
//# sourceMappingURL=ChannelRoot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChannelRoot.js","names":[],"sources":["../../src/channel/ChannelRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect, useCallback } from 'react';\nimport { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';\nimport {
|
|
1
|
+
{"version":3,"file":"ChannelRoot.js","names":[],"sources":["../../src/channel/ChannelRoot.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useEffect, useCallback } from 'react';\nimport { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';\nimport { useTr } from './hooks/useTr';\nimport { Radio, Cable, Send, Settings } from 'lucide-react';\nimport { ChannelProvider } from './providers/ChannelProvider';\nimport type { NavItem, ChannelRootProps } from './types';\nimport { ChannelRoutes } from './ChannelRoutes';\n\n/**\n * Root component for the Channel microfrontend.\n *\n * This is the main entry point that host applications import and render.\n * It sets up the necessary providers and renders the internal routing.\n * Automatically registers navigation items with the shell if registration functions are provided.\n *\n * @example\n * ```tsx\n * import { ChannelRoot, type ChannelRootProps } from '@burdenoff/microfe-channel';\n *\n * function App() {\n * const props: ChannelRootProps = {\n * basePath: '/channels',\n * navigate: (path) => router.push(path),\n * currentUser: { id: '1', email: 'user@example.com', firstName: 'John', lastName: 'Doe' },\n * workspaceId: 'ws-123',\n * organizationId: 'org-123',\n * apiGatewayUrl: 'https://api.example.com/workspaces/graphql',\n * authToken: 'token',\n * registerNavItems: (items) => { return () => {}; },\n * };\n *\n * return <ChannelRoot {...props} />;\n * }\n * ```\n */\nexport const ChannelRoot: FC<ChannelRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/' } = props;\n const tr = useTr();\n\n // Helper to join paths correctly, avoiding double slashes\n const joinPath = (base: string, path: string): string => {\n const cleanBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return cleanBase + cleanPath;\n };\n\n // Register navigation items with the shell\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'channel-channels',\n label: tr('channel.channels', 'Channels'),\n path: basePath === '/' ? '/' : joinPath(basePath, 'list'),\n icon: <Radio size={20} />,\n order: 100,\n group: 'channel',\n },\n {\n id: 'channel-connections',\n label: tr('channel.connections', 'Connections'),\n path: joinPath(basePath, 'connections'),\n icon: <Cable size={20} />,\n order: 110,\n group: 'channel',\n },\n {\n id: 'channel-send',\n label: tr('channel.sendMessage', 'Send Message'),\n path: joinPath(basePath, 'send'),\n icon: <Send size={20} />,\n order: 120,\n group: 'channel',\n },\n {\n id: 'channel-settings',\n label: tr('channel.settings', 'Settings'),\n path: joinPath(basePath, 'settings'),\n icon: <Settings size={20} />,\n order: 130,\n group: 'channel',\n },\n ];\n\n // Register and get cleanup function\n const cleanup = registerNavItems(navItems);\n\n // Return cleanup function to unregister on unmount\n return cleanup;\n }, [registerNavItems, basePath, tr]);\n\n // Register footer items (example: Channel status indicator in left section)\n useEffect(() => {\n if (!registerFooterItems) return;\n\n const footerItems = [\n {\n id: 'channel-status',\n label: tr('channel.channelsReady', 'Channels Ready'),\n type: 'status' as const,\n order: 10,\n section: 'left' as const,\n },\n ];\n\n const cleanup = registerFooterItems(footerItems);\n return cleanup;\n }, [registerFooterItems, tr]);\n\n return (\n <ErrorBoundary\n fallback={\n <div className=\"p-6 text-center text-text-secondary\">\n Something went wrong loading this module. Please refresh the page.\n </div>\n }\n >\n <ChannelProvider {...props}>\n <ChannelRoutes />\n </ChannelProvider>\n </ErrorBoundary>\n );\n};\n"],"mappings":";;;;;;;;AAoCA,IAAa,KAAqC,MAAU;CAC1D,IAAM,EAAE,qBAAkB,wBAAqB,cAAW,QAAQ,GAC5D,IAAK,GAAO,EAGZ,KAAY,GAAc,OACZ,EAAK,SAAS,IAAI,GAAG,EAAK,MAAM,GAAG,GAAG,GAAG,MACzC,EAAK,WAAW,IAAI,GAAG,IAAO,IAAI;AAoEtD,QA/DA,QAAgB;AACT,QAyCL,QAHgB,EApCY;GAC1B;IACE,IAAI;IACJ,OAAO,EAAG,oBAAoB,WAAW;IACzC,MAAM,MAAa,MAAM,MAAM,EAAS,GAAU,OAAO;IACzD,MAAM,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA;IACzB,OAAO;IACP,OAAO;IACR;GACD;IACE,IAAI;IACJ,OAAO,EAAG,uBAAuB,cAAc;IAC/C,MAAM,EAAS,GAAU,cAAc;IACvC,MAAM,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA;IACzB,OAAO;IACP,OAAO;IACR;GACD;IACE,IAAI;IACJ,OAAO,EAAG,uBAAuB,eAAe;IAChD,MAAM,EAAS,GAAU,OAAO;IAChC,MAAM,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;IACxB,OAAO;IACP,OAAO;IACR;GACD;IACE,IAAI;IACJ,OAAO,EAAG,oBAAoB,WAAW;IACzC,MAAM,EAAS,GAAU,WAAW;IACpC,MAAM,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;IAC5B,OAAO;IACP,OAAO;IACR;GACF,CAGyC;IAIzC;EAAC;EAAkB;EAAU;EAAG,CAAC,EAGpC,QAAgB;AACT,QAaL,QADgB,EAVI,CAClB;GACE,IAAI;GACJ,OAAO,EAAG,yBAAyB,iBAAiB;GACpD,MAAM;GACN,OAAO;GACP,SAAS;GACV,CACF,CAE+C;IAE/C,CAAC,GAAqB,EAAG,CAAC,EAG3B,kBAAC,GAAD;EACE,UACE,kBAAC,OAAD;GAAK,WAAU;aAAsC;GAE/C,CAAA;YAGR,kBAAC,GAAD;GAAiB,GAAI;aACnB,kBAAC,GAAD,EAAiB,CAAA;GACD,CAAA;EACJ,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdapterCredentialsForm.d.ts","sourceRoot":"","sources":["../../../src/channel/components/AdapterCredentialsForm.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQxD,UAAU,2BAA2B;IACnC,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACzD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,QAAgB,EAChB,oBAA2B,GAC5B,EAAE,2BAA2B,+
|
|
1
|
+
{"version":3,"file":"AdapterCredentialsForm.d.ts","sourceRoot":"","sources":["../../../src/channel/components/AdapterCredentialsForm.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQxD,UAAU,2BAA2B;IACnC,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACzD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wBAAgB,sBAAsB,CAAC,EACrC,WAAW,EACX,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,QAAgB,EAChB,oBAA2B,GAC5B,EAAE,2BAA2B,+BAsP7B;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,WAAW,EACX,WAAW,GACZ,EAAE;IACD,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC,sCA0BA"}
|
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { useTr as e } from "../hooks/useTr.js";
|
|
2
|
+
import { getAdapterCredentialSchema as t, getDefaultCredentials as n, validateCredentials as r } from "../config/adapterCredentials.js";
|
|
3
|
+
import { useEffect as i, useState as a } from "react";
|
|
4
4
|
import { AlertCircle as o, CheckCircle2 as s, ExternalLink as c, Eye as l, EyeOff as u } from "lucide-react";
|
|
5
5
|
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
6
6
|
//#region src/channel/components/AdapterCredentialsForm.tsx
|
|
7
7
|
function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g, disabled: _ = !1, showPlatformMetadata: v = !0 }) {
|
|
8
|
-
let
|
|
9
|
-
|
|
10
|
-
return n === e ? t : n;
|
|
11
|
-
}, [x, S] = i({}), [C, w] = i({}), T = e(s);
|
|
12
|
-
if (r(() => {
|
|
8
|
+
let y = e(), [b, x] = a({}), [S, C] = a({}), w = t(s);
|
|
9
|
+
if (i(() => {
|
|
13
10
|
if (s) {
|
|
14
11
|
let e = {
|
|
15
|
-
...
|
|
12
|
+
...n(s),
|
|
16
13
|
...m
|
|
17
14
|
};
|
|
18
15
|
JSON.stringify(e) !== JSON.stringify(m) && h(e);
|
|
19
16
|
}
|
|
20
|
-
}, [s]),
|
|
17
|
+
}, [s]), i(() => {
|
|
21
18
|
if (g && s) {
|
|
22
|
-
let { valid: e, errors: t } =
|
|
19
|
+
let { valid: e, errors: t } = r(s, m);
|
|
23
20
|
g(e, t);
|
|
24
21
|
}
|
|
25
22
|
}, [
|
|
@@ -30,10 +27,10 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
30
27
|
className: "text-center py-6 text-text-secondary",
|
|
31
28
|
children: /* @__PURE__ */ f("p", {
|
|
32
29
|
className: "text-sm",
|
|
33
|
-
children:
|
|
30
|
+
children: y("channel.selectAdapterType", "Select an adapter type to configure credentials")
|
|
34
31
|
})
|
|
35
32
|
});
|
|
36
|
-
if (!
|
|
33
|
+
if (!w) return /* @__PURE__ */ f("div", {
|
|
37
34
|
className: "p-4 bg-status-warning-bg-subtle border border-warning-300 rounded-lg",
|
|
38
35
|
children: /* @__PURE__ */ p("div", {
|
|
39
36
|
className: "flex items-start gap-2",
|
|
@@ -43,33 +40,33 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
43
40
|
}), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ p("p", {
|
|
44
41
|
className: "text-sm font-medium text-warning-700",
|
|
45
42
|
children: [
|
|
46
|
-
|
|
43
|
+
y("channel.noCredentialSchema", "No credential schema defined for"),
|
|
47
44
|
" ",
|
|
48
45
|
s
|
|
49
46
|
]
|
|
50
47
|
}), /* @__PURE__ */ f("p", {
|
|
51
48
|
className: "text-xs text-warning-600 mt-1",
|
|
52
|
-
children:
|
|
49
|
+
children: y("channel.enterCredentialsAsJson", "You can still enter credentials as JSON in the raw format below.")
|
|
53
50
|
})] })]
|
|
54
51
|
})
|
|
55
52
|
});
|
|
56
|
-
let
|
|
53
|
+
let T = (e, t) => {
|
|
57
54
|
h({
|
|
58
55
|
...m,
|
|
59
56
|
[e]: t
|
|
60
57
|
});
|
|
61
|
-
},
|
|
62
|
-
|
|
58
|
+
}, E = (e) => {
|
|
59
|
+
C((t) => ({
|
|
63
60
|
...t,
|
|
64
61
|
[e]: !0
|
|
65
62
|
}));
|
|
66
|
-
},
|
|
67
|
-
|
|
63
|
+
}, D = (e) => {
|
|
64
|
+
x((t) => ({
|
|
68
65
|
...t,
|
|
69
66
|
[e]: !t[e]
|
|
70
67
|
}));
|
|
71
|
-
},
|
|
72
|
-
let t = m[e.key], n =
|
|
68
|
+
}, O = (e) => {
|
|
69
|
+
let t = m[e.key], n = S[e.key] && e.required && !t, r = `w-full px-3 py-2 text-sm bg-surface border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-primary disabled:opacity-50 disabled:cursor-not-allowed ${n ? "border-status-error-border" : "border-border-subtle"}`, i = `adapter-cred-${e.key}`;
|
|
73
70
|
return /* @__PURE__ */ p("div", { children: [
|
|
74
71
|
/* @__PURE__ */ p("label", {
|
|
75
72
|
htmlFor: i,
|
|
@@ -84,8 +81,8 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
84
81
|
"aria-label": e.displayName,
|
|
85
82
|
type: "text",
|
|
86
83
|
value: t || "",
|
|
87
|
-
onChange: (t) =>
|
|
88
|
-
onBlur: () =>
|
|
84
|
+
onChange: (t) => T(e.key, t.target.value),
|
|
85
|
+
onBlur: () => E(e.key),
|
|
89
86
|
disabled: _,
|
|
90
87
|
placeholder: e.placeholder,
|
|
91
88
|
className: r
|
|
@@ -95,28 +92,28 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
95
92
|
children: [/* @__PURE__ */ f("input", {
|
|
96
93
|
id: i,
|
|
97
94
|
"aria-label": e.displayName,
|
|
98
|
-
type:
|
|
95
|
+
type: b[e.key] ? "text" : "password",
|
|
99
96
|
value: t || "",
|
|
100
|
-
onChange: (t) =>
|
|
101
|
-
onBlur: () =>
|
|
97
|
+
onChange: (t) => T(e.key, t.target.value),
|
|
98
|
+
onBlur: () => E(e.key),
|
|
102
99
|
disabled: _,
|
|
103
100
|
placeholder: e.placeholder,
|
|
104
101
|
className: `${r} pr-10`
|
|
105
102
|
}), /* @__PURE__ */ f("button", {
|
|
106
103
|
type: "button",
|
|
107
|
-
onClick: () =>
|
|
108
|
-
"aria-label":
|
|
104
|
+
onClick: () => D(e.key),
|
|
105
|
+
"aria-label": b[e.key] ? y("channel.hideField", "Hide {{field}}", { field: e.displayName }) : y("channel.showField", "Show {{field}}", { field: e.displayName }),
|
|
109
106
|
className: "absolute right-2 top-1/2 -translate-y-1/2 p-1 text-text-secondary hover:text-text-primary",
|
|
110
107
|
tabIndex: -1,
|
|
111
|
-
children:
|
|
108
|
+
children: b[e.key] ? /* @__PURE__ */ f(u, { size: 16 }) : /* @__PURE__ */ f(l, { size: 16 })
|
|
112
109
|
})]
|
|
113
110
|
}),
|
|
114
111
|
e.type === "textarea" && /* @__PURE__ */ f("textarea", {
|
|
115
112
|
id: i,
|
|
116
113
|
"aria-label": e.displayName,
|
|
117
114
|
value: t || "",
|
|
118
|
-
onChange: (t) =>
|
|
119
|
-
onBlur: () =>
|
|
115
|
+
onChange: (t) => T(e.key, t.target.value),
|
|
116
|
+
onBlur: () => E(e.key),
|
|
120
117
|
disabled: _,
|
|
121
118
|
placeholder: e.placeholder,
|
|
122
119
|
rows: 4,
|
|
@@ -127,8 +124,8 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
127
124
|
"aria-label": e.displayName,
|
|
128
125
|
type: "number",
|
|
129
126
|
value: t ?? e.defaultValue ?? "",
|
|
130
|
-
onChange: (t) =>
|
|
131
|
-
onBlur: () =>
|
|
127
|
+
onChange: (t) => T(e.key, t.target.value ? Number(t.target.value) : void 0),
|
|
128
|
+
onBlur: () => E(e.key),
|
|
132
129
|
disabled: _,
|
|
133
130
|
placeholder: e.placeholder,
|
|
134
131
|
className: r
|
|
@@ -138,7 +135,7 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
138
135
|
children: [/* @__PURE__ */ f("input", {
|
|
139
136
|
type: "checkbox",
|
|
140
137
|
checked: t ?? e.defaultValue ?? !1,
|
|
141
|
-
onChange: (t) =>
|
|
138
|
+
onChange: (t) => T(e.key, t.target.checked),
|
|
142
139
|
disabled: _,
|
|
143
140
|
className: "size-4 rounded border-border-subtle text-accent-primary focus:ring-accent-primary"
|
|
144
141
|
}), /* @__PURE__ */ f("span", {
|
|
@@ -150,14 +147,14 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
150
147
|
id: i,
|
|
151
148
|
"aria-label": e.displayName,
|
|
152
149
|
value: t ?? e.defaultValue ?? "",
|
|
153
|
-
onChange: (t) =>
|
|
154
|
-
onBlur: () =>
|
|
150
|
+
onChange: (t) => T(e.key, t.target.value),
|
|
151
|
+
onBlur: () => E(e.key),
|
|
155
152
|
disabled: _,
|
|
156
153
|
className: `${r} bg-bg-surface`,
|
|
157
154
|
children: [/* @__PURE__ */ p("option", {
|
|
158
155
|
value: "",
|
|
159
156
|
children: [
|
|
160
|
-
|
|
157
|
+
y("channel.select", "Select"),
|
|
161
158
|
" ",
|
|
162
159
|
e.displayName.toLowerCase()
|
|
163
160
|
]
|
|
@@ -172,7 +169,7 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
172
169
|
}),
|
|
173
170
|
n && /* @__PURE__ */ f("p", {
|
|
174
171
|
className: "mt-1 text-xs text-status-error-text",
|
|
175
|
-
children:
|
|
172
|
+
children: y("channel.fieldRequired", "This field is required")
|
|
176
173
|
})
|
|
177
174
|
] }, e.key);
|
|
178
175
|
};
|
|
@@ -182,43 +179,40 @@ function m({ adapterType: s, credentials: m, onChange: h, onValidationChange: g,
|
|
|
182
179
|
className: "flex items-start justify-between",
|
|
183
180
|
children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h3", {
|
|
184
181
|
className: "text-sm font-semibold text-text-primary",
|
|
185
|
-
children:
|
|
182
|
+
children: w.displayName
|
|
186
183
|
}), /* @__PURE__ */ f("p", {
|
|
187
184
|
className: "text-xs text-text-secondary mt-0.5",
|
|
188
|
-
children:
|
|
189
|
-
})] }),
|
|
190
|
-
href:
|
|
185
|
+
children: w.description
|
|
186
|
+
})] }), w.docUrl && /* @__PURE__ */ p("a", {
|
|
187
|
+
href: w.docUrl,
|
|
191
188
|
target: "_blank",
|
|
192
189
|
rel: "noopener noreferrer",
|
|
193
190
|
className: "flex items-center gap-1 text-xs text-accent-primary hover:text-accent-primary-hover",
|
|
194
|
-
children: [/* @__PURE__ */ f("span", { children:
|
|
191
|
+
children: [/* @__PURE__ */ f("span", { children: y("channel.docs", "Docs") }), /* @__PURE__ */ f(c, { size: 12 })]
|
|
195
192
|
})]
|
|
196
193
|
}), /* @__PURE__ */ p("div", {
|
|
197
194
|
className: "space-y-4",
|
|
198
|
-
children: [
|
|
195
|
+
children: [w.credentials.length > 0 && /* @__PURE__ */ f("div", {
|
|
199
196
|
className: "space-y-4",
|
|
200
|
-
children:
|
|
201
|
-
}), v &&
|
|
197
|
+
children: w.credentials.map(O)
|
|
198
|
+
}), v && w.platformMetadata && w.platformMetadata.length > 0 && /* @__PURE__ */ f(d, { children: /* @__PURE__ */ p("div", {
|
|
202
199
|
className: "border-t border-border-subtle pt-4 mt-4",
|
|
203
200
|
children: [/* @__PURE__ */ f("p", {
|
|
204
201
|
className: "text-xs font-medium text-text-secondary mb-3",
|
|
205
|
-
children:
|
|
202
|
+
children: y("channel.optionalSettings", "Optional Settings")
|
|
206
203
|
}), /* @__PURE__ */ f("div", {
|
|
207
204
|
className: "space-y-4",
|
|
208
|
-
children:
|
|
205
|
+
children: w.platformMetadata.map(O)
|
|
209
206
|
})]
|
|
210
207
|
}) })]
|
|
211
208
|
})]
|
|
212
209
|
});
|
|
213
210
|
}
|
|
214
|
-
function h({ adapterType:
|
|
215
|
-
let
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (!e) return null;
|
|
220
|
-
let { valid: c, errors: l } = n(e, t);
|
|
221
|
-
return c ? /* @__PURE__ */ p("div", {
|
|
211
|
+
function h({ adapterType: t, credentials: n }) {
|
|
212
|
+
let i = e();
|
|
213
|
+
if (!t) return null;
|
|
214
|
+
let { valid: a, errors: c } = r(t, n);
|
|
215
|
+
return a ? /* @__PURE__ */ p("div", {
|
|
222
216
|
className: "flex items-center gap-1.5 text-status-success-text",
|
|
223
217
|
children: [/* @__PURE__ */ f(s, { size: 14 }), /* @__PURE__ */ f("span", {
|
|
224
218
|
className: "text-xs",
|
|
@@ -229,7 +223,7 @@ function h({ adapterType: e, credentials: t }) {
|
|
|
229
223
|
children: [/* @__PURE__ */ f(o, { size: 14 }), /* @__PURE__ */ p("span", {
|
|
230
224
|
className: "text-xs",
|
|
231
225
|
children: [
|
|
232
|
-
|
|
226
|
+
c.length,
|
|
233
227
|
" ",
|
|
234
228
|
i("channel.fieldsNeedAttention", "field(s) need attention")
|
|
235
229
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdapterCredentialsForm.js","names":[],"sources":["../../../src/channel/components/AdapterCredentialsForm.tsx"],"sourcesContent":["/**\n * Adapter Credentials Form\n *\n * Dynamic form that renders credential fields based on the selected adapter type.\n * Field names match exactly what the backend adapters expect.\n */\n\nimport { useState, useEffect } from 'react';\nimport { ExternalLink, Eye, EyeOff, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport type { AdapterType } from '../hooks/useChannels';\nimport {\n getAdapterCredentialSchema,\n getDefaultCredentials,\n validateCredentials,\n type CredentialField,\n} from '../config/adapterCredentials';\n\ninterface AdapterCredentialsFormProps {\n adapterType: AdapterType | undefined;\n credentials: Record<string, unknown>;\n onChange: (credentials: Record<string, unknown>) => void;\n onValidationChange?: (isValid: boolean, errors: string[]) => void;\n disabled?: boolean;\n showPlatformMetadata?: boolean;\n}\n\nexport function AdapterCredentialsForm({\n adapterType,\n credentials,\n onChange,\n onValidationChange,\n disabled = false,\n showPlatformMetadata = true,\n}: AdapterCredentialsFormProps) {\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 [showPasswords, setShowPasswords] = useState<Record<string, boolean>>({});\n const [touched, setTouched] = useState<Record<string, boolean>>({});\n\n const schema = getAdapterCredentialSchema(adapterType);\n\n // Initialize with default values when adapter type changes\n useEffect(() => {\n if (adapterType) {\n const defaults = getDefaultCredentials(adapterType);\n const merged = { ...defaults, ...credentials };\n if (JSON.stringify(merged) !== JSON.stringify(credentials)) {\n onChange(merged);\n }\n }\n }, [adapterType]);\n\n // Validate on change\n useEffect(() => {\n if (onValidationChange && adapterType) {\n const { valid, errors } = validateCredentials(adapterType, credentials);\n onValidationChange(valid, errors);\n }\n }, [credentials, adapterType, onValidationChange]);\n\n if (!adapterType) {\n return (\n <div className=\"text-center py-6 text-text-secondary\">\n <p className=\"text-sm\">\n {tr('channel.selectAdapterType', 'Select an adapter type to configure credentials')}\n </p>\n </div>\n );\n }\n\n if (!schema) {\n return (\n <div className=\"p-4 bg-status-warning-bg-subtle border border-warning-300 rounded-lg\">\n <div className=\"flex items-start gap-2\">\n <AlertCircle size={16} className=\"text-status-warning-text mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-warning-700\">\n {tr('channel.noCredentialSchema', 'No credential schema defined for')} {adapterType}\n </p>\n <p className=\"text-xs text-warning-600 mt-1\">\n {tr(\n 'channel.enterCredentialsAsJson',\n 'You can still enter credentials as JSON in the raw format below.'\n )}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n const handleFieldChange = (key: string, value: unknown) => {\n onChange({ ...credentials, [key]: value });\n };\n\n const handleFieldBlur = (key: string) => {\n setTouched((prev) => ({ ...prev, [key]: true }));\n };\n\n const togglePasswordVisibility = (key: string) => {\n setShowPasswords((prev) => ({ ...prev, [key]: !prev[key] }));\n };\n\n const renderField = (field: CredentialField) => {\n const value = credentials[field.key];\n const fieldError = touched[field.key] && field.required && !value;\n\n const commonInputClasses = `w-full px-3 py-2 text-sm bg-surface border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-primary disabled:opacity-50 disabled:cursor-not-allowed ${\n fieldError ? 'border-status-error-border' : 'border-border-subtle'\n }`;\n\n const fieldId = `adapter-cred-${field.key}`;\n return (\n <div key={field.key}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium text-text-primary mb-1.5\">\n {field.displayName}\n {field.required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n\n {field.type === 'text' && (\n <input\n id={fieldId}\n aria-label={field.displayName}\n type=\"text\"\n value={(value as string) || ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n className={commonInputClasses}\n />\n )}\n\n {field.type === 'password' && (\n <div className=\"relative\">\n <input\n id={fieldId}\n aria-label={field.displayName}\n type={showPasswords[field.key] ? 'text' : 'password'}\n value={(value as string) || ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n className={`${commonInputClasses} pr-10`}\n />\n <button\n type=\"button\"\n onClick={() => togglePasswordVisibility(field.key)}\n aria-label={\n showPasswords[field.key] ? `Hide ${field.displayName}` : `Show ${field.displayName}`\n }\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-text-secondary hover:text-text-primary\"\n tabIndex={-1}\n >\n {showPasswords[field.key] ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n )}\n\n {field.type === 'textarea' && (\n <textarea\n id={fieldId}\n aria-label={field.displayName}\n value={(value as string) || ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n rows={4}\n className={`${commonInputClasses} resize-none font-mono text-xs`}\n />\n )}\n\n {field.type === 'number' && (\n <input\n id={fieldId}\n aria-label={field.displayName}\n type=\"number\"\n value={(value as number) ?? field.defaultValue ?? ''}\n onChange={(e) =>\n handleFieldChange(field.key, e.target.value ? Number(e.target.value) : undefined)\n }\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n className={commonInputClasses}\n />\n )}\n\n {field.type === 'boolean' && (\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={(value as boolean) ?? field.defaultValue ?? false}\n onChange={(e) => handleFieldChange(field.key, e.target.checked)}\n disabled={disabled}\n className=\"size-4 rounded border-border-subtle text-accent-primary focus:ring-accent-primary\"\n />\n <span className=\"text-sm text-text-secondary\">{field.description}</span>\n </label>\n )}\n\n {field.type === 'select' && field.options && (\n <select\n id={fieldId}\n aria-label={field.displayName}\n value={(value as string) ?? field.defaultValue ?? ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n className={`${commonInputClasses} bg-bg-surface`}\n >\n <option value=\"\">\n {tr('channel.select', 'Select')} {field.displayName.toLowerCase()}\n </option>\n {field.options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n )}\n\n {field.type !== 'boolean' && (\n <p className=\"mt-1 text-xs text-text-secondary\">{field.description}</p>\n )}\n\n {fieldError && (\n <p className=\"mt-1 text-xs text-status-error-text\">\n {tr('channel.fieldRequired', 'This field is required')}\n </p>\n )}\n </div>\n );\n };\n\n return (\n <div className=\"space-y-5\">\n {/* Header with adapter info */}\n <div className=\"flex items-start justify-between\">\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">{schema.displayName}</h3>\n <p className=\"text-xs text-text-secondary mt-0.5\">{schema.description}</p>\n </div>\n {schema.docUrl && (\n <a\n href={schema.docUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 text-xs text-accent-primary hover:text-accent-primary-hover\"\n >\n <span>{tr('channel.docs', 'Docs')}</span>\n <ExternalLink size={12} />\n </a>\n )}\n </div>\n\n {/* Credential fields */}\n <div className=\"space-y-4\">\n {schema.credentials.length > 0 && (\n <div className=\"space-y-4\">{schema.credentials.map(renderField)}</div>\n )}\n\n {/* Platform metadata fields (optional settings) */}\n {showPlatformMetadata && schema.platformMetadata && schema.platformMetadata.length > 0 && (\n <>\n <div className=\"border-t border-border-subtle pt-4 mt-4\">\n <p className=\"text-xs font-medium text-text-secondary mb-3\">\n {tr('channel.optionalSettings', 'Optional Settings')}\n </p>\n <div className=\"space-y-4\">{schema.platformMetadata.map(renderField)}</div>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Compact validation status indicator\n */\nexport function CredentialValidationStatus({\n adapterType,\n credentials,\n}: {\n adapterType: AdapterType | undefined;\n credentials: Record<string, unknown>;\n}) {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n if (!adapterType) return null;\n\n const { valid, errors } = validateCredentials(adapterType, credentials);\n\n if (valid) {\n return (\n <div className=\"flex items-center gap-1.5 text-status-success-text\">\n <CheckCircle2 size={14} />\n <span className=\"text-xs\">\n {tr('channel.allRequiredFieldsFilled', 'All required fields filled')}\n </span>\n </div>\n );\n }\n\n return (\n <div className=\"flex items-center gap-1.5 text-status-warning-text\">\n <AlertCircle size={14} />\n <span className=\"text-xs\">\n {errors.length} {tr('channel.fieldsNeedAttention', 'field(s) need attention')}\n </span>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdapterCredentialsForm.js","names":[],"sources":["../../../src/channel/components/AdapterCredentialsForm.tsx"],"sourcesContent":["/**\n * Adapter Credentials Form\n *\n * Dynamic form that renders credential fields based on the selected adapter type.\n * Field names match exactly what the backend adapters expect.\n */\n\nimport { useState, useEffect } from 'react';\nimport { ExternalLink, Eye, EyeOff, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { useTr } from '../hooks/useTr';\nimport type { AdapterType } from '../hooks/useChannels';\nimport {\n getAdapterCredentialSchema,\n getDefaultCredentials,\n validateCredentials,\n type CredentialField,\n} from '../config/adapterCredentials';\n\ninterface AdapterCredentialsFormProps {\n adapterType: AdapterType | undefined;\n credentials: Record<string, unknown>;\n onChange: (credentials: Record<string, unknown>) => void;\n onValidationChange?: (isValid: boolean, errors: string[]) => void;\n disabled?: boolean;\n showPlatformMetadata?: boolean;\n}\n\nexport function AdapterCredentialsForm({\n adapterType,\n credentials,\n onChange,\n onValidationChange,\n disabled = false,\n showPlatformMetadata = true,\n}: AdapterCredentialsFormProps) {\n const tr = useTr();\n const [showPasswords, setShowPasswords] = useState<Record<string, boolean>>({});\n const [touched, setTouched] = useState<Record<string, boolean>>({});\n\n const schema = getAdapterCredentialSchema(adapterType);\n\n // Initialize with default values when adapter type changes\n useEffect(() => {\n if (adapterType) {\n const defaults = getDefaultCredentials(adapterType);\n const merged = { ...defaults, ...credentials };\n if (JSON.stringify(merged) !== JSON.stringify(credentials)) {\n onChange(merged);\n }\n }\n }, [adapterType]);\n\n // Validate on change\n useEffect(() => {\n if (onValidationChange && adapterType) {\n const { valid, errors } = validateCredentials(adapterType, credentials);\n onValidationChange(valid, errors);\n }\n }, [credentials, adapterType, onValidationChange]);\n\n if (!adapterType) {\n return (\n <div className=\"text-center py-6 text-text-secondary\">\n <p className=\"text-sm\">\n {tr('channel.selectAdapterType', 'Select an adapter type to configure credentials')}\n </p>\n </div>\n );\n }\n\n if (!schema) {\n return (\n <div className=\"p-4 bg-status-warning-bg-subtle border border-warning-300 rounded-lg\">\n <div className=\"flex items-start gap-2\">\n <AlertCircle size={16} className=\"text-status-warning-text mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-warning-700\">\n {tr('channel.noCredentialSchema', 'No credential schema defined for')} {adapterType}\n </p>\n <p className=\"text-xs text-warning-600 mt-1\">\n {tr(\n 'channel.enterCredentialsAsJson',\n 'You can still enter credentials as JSON in the raw format below.'\n )}\n </p>\n </div>\n </div>\n </div>\n );\n }\n\n const handleFieldChange = (key: string, value: unknown) => {\n onChange({ ...credentials, [key]: value });\n };\n\n const handleFieldBlur = (key: string) => {\n setTouched((prev) => ({ ...prev, [key]: true }));\n };\n\n const togglePasswordVisibility = (key: string) => {\n setShowPasswords((prev) => ({ ...prev, [key]: !prev[key] }));\n };\n\n const renderField = (field: CredentialField) => {\n const value = credentials[field.key];\n const fieldError = touched[field.key] && field.required && !value;\n\n const commonInputClasses = `w-full px-3 py-2 text-sm bg-surface border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-primary disabled:opacity-50 disabled:cursor-not-allowed ${\n fieldError ? 'border-status-error-border' : 'border-border-subtle'\n }`;\n\n const fieldId = `adapter-cred-${field.key}`;\n return (\n <div key={field.key}>\n <label htmlFor={fieldId} className=\"block text-sm font-medium text-text-primary mb-1.5\">\n {field.displayName}\n {field.required && <span className=\"text-status-error-text ml-1\">*</span>}\n </label>\n\n {field.type === 'text' && (\n <input\n id={fieldId}\n aria-label={field.displayName}\n type=\"text\"\n value={(value as string) || ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n className={commonInputClasses}\n />\n )}\n\n {field.type === 'password' && (\n <div className=\"relative\">\n <input\n id={fieldId}\n aria-label={field.displayName}\n type={showPasswords[field.key] ? 'text' : 'password'}\n value={(value as string) || ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n className={`${commonInputClasses} pr-10`}\n />\n <button\n type=\"button\"\n onClick={() => togglePasswordVisibility(field.key)}\n aria-label={\n showPasswords[field.key]\n ? tr('channel.hideField', 'Hide {{field}}', { field: field.displayName })\n : tr('channel.showField', 'Show {{field}}', { field: field.displayName })\n }\n className=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-text-secondary hover:text-text-primary\"\n tabIndex={-1}\n >\n {showPasswords[field.key] ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n )}\n\n {field.type === 'textarea' && (\n <textarea\n id={fieldId}\n aria-label={field.displayName}\n value={(value as string) || ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n rows={4}\n className={`${commonInputClasses} resize-none font-mono text-xs`}\n />\n )}\n\n {field.type === 'number' && (\n <input\n id={fieldId}\n aria-label={field.displayName}\n type=\"number\"\n value={(value as number) ?? field.defaultValue ?? ''}\n onChange={(e) =>\n handleFieldChange(field.key, e.target.value ? Number(e.target.value) : undefined)\n }\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n placeholder={field.placeholder}\n className={commonInputClasses}\n />\n )}\n\n {field.type === 'boolean' && (\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={(value as boolean) ?? field.defaultValue ?? false}\n onChange={(e) => handleFieldChange(field.key, e.target.checked)}\n disabled={disabled}\n className=\"size-4 rounded border-border-subtle text-accent-primary focus:ring-accent-primary\"\n />\n <span className=\"text-sm text-text-secondary\">{field.description}</span>\n </label>\n )}\n\n {field.type === 'select' && field.options && (\n <select\n id={fieldId}\n aria-label={field.displayName}\n value={(value as string) ?? field.defaultValue ?? ''}\n onChange={(e) => handleFieldChange(field.key, e.target.value)}\n onBlur={() => handleFieldBlur(field.key)}\n disabled={disabled}\n className={`${commonInputClasses} bg-bg-surface`}\n >\n <option value=\"\">\n {tr('channel.select', 'Select')} {field.displayName.toLowerCase()}\n </option>\n {field.options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n )}\n\n {field.type !== 'boolean' && (\n <p className=\"mt-1 text-xs text-text-secondary\">{field.description}</p>\n )}\n\n {fieldError && (\n <p className=\"mt-1 text-xs text-status-error-text\">\n {tr('channel.fieldRequired', 'This field is required')}\n </p>\n )}\n </div>\n );\n };\n\n return (\n <div className=\"space-y-5\">\n {/* Header with adapter info */}\n <div className=\"flex items-start justify-between\">\n <div>\n <h3 className=\"text-sm font-semibold text-text-primary\">{schema.displayName}</h3>\n <p className=\"text-xs text-text-secondary mt-0.5\">{schema.description}</p>\n </div>\n {schema.docUrl && (\n <a\n href={schema.docUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 text-xs text-accent-primary hover:text-accent-primary-hover\"\n >\n <span>{tr('channel.docs', 'Docs')}</span>\n <ExternalLink size={12} />\n </a>\n )}\n </div>\n\n {/* Credential fields */}\n <div className=\"space-y-4\">\n {schema.credentials.length > 0 && (\n <div className=\"space-y-4\">{schema.credentials.map(renderField)}</div>\n )}\n\n {/* Platform metadata fields (optional settings) */}\n {showPlatformMetadata && schema.platformMetadata && schema.platformMetadata.length > 0 && (\n <>\n <div className=\"border-t border-border-subtle pt-4 mt-4\">\n <p className=\"text-xs font-medium text-text-secondary mb-3\">\n {tr('channel.optionalSettings', 'Optional Settings')}\n </p>\n <div className=\"space-y-4\">{schema.platformMetadata.map(renderField)}</div>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Compact validation status indicator\n */\nexport function CredentialValidationStatus({\n adapterType,\n credentials,\n}: {\n adapterType: AdapterType | undefined;\n credentials: Record<string, unknown>;\n}) {\n const tr = useTr();\n\n if (!adapterType) return null;\n\n const { valid, errors } = validateCredentials(adapterType, credentials);\n\n if (valid) {\n return (\n <div className=\"flex items-center gap-1.5 text-status-success-text\">\n <CheckCircle2 size={14} />\n <span className=\"text-xs\">\n {tr('channel.allRequiredFieldsFilled', 'All required fields filled')}\n </span>\n </div>\n );\n }\n\n return (\n <div className=\"flex items-center gap-1.5 text-status-warning-text\">\n <AlertCircle size={14} />\n <span className=\"text-xs\">\n {errors.length} {tr('channel.fieldsNeedAttention', 'field(s) need attention')}\n </span>\n </div>\n );\n}\n"],"mappings":";;;;;;AA2BA,SAAgB,EAAuB,EACrC,gBACA,gBACA,aACA,uBACA,cAAW,IACX,0BAAuB,MACO;CAC9B,IAAM,IAAK,GAAO,EACZ,CAAC,GAAe,KAAoB,EAAkC,EAAE,CAAC,EACzE,CAAC,GAAS,KAAc,EAAkC,EAAE,CAAC,EAE7D,IAAS,EAA2B,EAAY;AAqBtD,KAlBA,QAAgB;AACd,MAAI,GAAa;GAEf,IAAM,IAAS;IAAE,GADA,EAAsB,EAAY;IACrB,GAAG;IAAa;AAC9C,GAAI,KAAK,UAAU,EAAO,KAAK,KAAK,UAAU,EAAY,IACxD,EAAS,EAAO;;IAGnB,CAAC,EAAY,CAAC,EAGjB,QAAgB;AACd,MAAI,KAAsB,GAAa;GACrC,IAAM,EAAE,UAAO,cAAW,EAAoB,GAAa,EAAY;AACvE,KAAmB,GAAO,EAAO;;IAElC;EAAC;EAAa;EAAa;EAAmB,CAAC,EAE9C,CAAC,EACH,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,KAAD;GAAG,WAAU;aACV,EAAG,6BAA6B,kDAAkD;GACjF,CAAA;EACA,CAAA;AAIV,KAAI,CAAC,EACH,QACE,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IAAa,MAAM;IAAI,WAAU;IAAoC,CAAA,EACrE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EAAG,8BAA8B,mCAAmC;KAAC;KAAE;KACtE;OACJ,kBAAC,KAAD;IAAG,WAAU;cACV,EACC,kCACA,mEACD;IACC,CAAA,CACA,EAAA,CAAA,CACF;;EACF,CAAA;CAIV,IAAM,KAAqB,GAAa,MAAmB;AACzD,IAAS;GAAE,GAAG;IAAc,IAAM;GAAO,CAAC;IAGtC,KAAmB,MAAgB;AACvC,KAAY,OAAU;GAAE,GAAG;IAAO,IAAM;GAAM,EAAE;IAG5C,KAA4B,MAAgB;AAChD,KAAkB,OAAU;GAAE,GAAG;IAAO,IAAM,CAAC,EAAK;GAAM,EAAE;IAGxD,KAAe,MAA2B;EAC9C,IAAM,IAAQ,EAAY,EAAM,MAC1B,IAAa,EAAQ,EAAM,QAAQ,EAAM,YAAY,CAAC,GAEtD,IAAqB,mKACzB,IAAa,+BAA+B,0BAGxC,IAAU,gBAAgB,EAAM;AACtC,SACE,kBAAC,OAAD,EAAA,UAAA;GACE,kBAAC,SAAD;IAAO,SAAS;IAAS,WAAU;cAAnC,CACG,EAAM,aACN,EAAM,YAAY,kBAAC,QAAD;KAAM,WAAU;eAA8B;KAAQ,CAAA,CACnE;;GAEP,EAAM,SAAS,UACd,kBAAC,SAAD;IACE,IAAI;IACJ,cAAY,EAAM;IAClB,MAAK;IACL,OAAQ,KAAoB;IAC5B,WAAW,MAAM,EAAkB,EAAM,KAAK,EAAE,OAAO,MAAM;IAC7D,cAAc,EAAgB,EAAM,IAAI;IAC9B;IACV,aAAa,EAAM;IACnB,WAAW;IACX,CAAA;GAGH,EAAM,SAAS,cACd,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,SAAD;KACE,IAAI;KACJ,cAAY,EAAM;KAClB,MAAM,EAAc,EAAM,OAAO,SAAS;KAC1C,OAAQ,KAAoB;KAC5B,WAAW,MAAM,EAAkB,EAAM,KAAK,EAAE,OAAO,MAAM;KAC7D,cAAc,EAAgB,EAAM,IAAI;KAC9B;KACV,aAAa,EAAM;KACnB,WAAW,GAAG,EAAmB;KACjC,CAAA,EACF,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAyB,EAAM,IAAI;KAClD,cACE,EAAc,EAAM,OAChB,EAAG,qBAAqB,kBAAkB,EAAE,OAAO,EAAM,aAAa,CAAC,GACvE,EAAG,qBAAqB,kBAAkB,EAAE,OAAO,EAAM,aAAa,CAAC;KAE7E,WAAU;KACV,UAAU;eAET,EAAc,EAAM,OAAO,kBAAC,GAAD,EAAQ,MAAM,IAAM,CAAA,GAAG,kBAAC,GAAD,EAAK,MAAM,IAAM,CAAA;KAC7D,CAAA,CACL;;GAGP,EAAM,SAAS,cACd,kBAAC,YAAD;IACE,IAAI;IACJ,cAAY,EAAM;IAClB,OAAQ,KAAoB;IAC5B,WAAW,MAAM,EAAkB,EAAM,KAAK,EAAE,OAAO,MAAM;IAC7D,cAAc,EAAgB,EAAM,IAAI;IAC9B;IACV,aAAa,EAAM;IACnB,MAAM;IACN,WAAW,GAAG,EAAmB;IACjC,CAAA;GAGH,EAAM,SAAS,YACd,kBAAC,SAAD;IACE,IAAI;IACJ,cAAY,EAAM;IAClB,MAAK;IACL,OAAQ,KAAoB,EAAM,gBAAgB;IAClD,WAAW,MACT,EAAkB,EAAM,KAAK,EAAE,OAAO,QAAQ,OAAO,EAAE,OAAO,MAAM,GAAG,KAAA,EAAU;IAEnF,cAAc,EAAgB,EAAM,IAAI;IAC9B;IACV,aAAa,EAAM;IACnB,WAAW;IACX,CAAA;GAGH,EAAM,SAAS,aACd,kBAAC,SAAD;IAAO,WAAU;cAAjB,CACE,kBAAC,SAAD;KACE,MAAK;KACL,SAAU,KAAqB,EAAM,gBAAgB;KACrD,WAAW,MAAM,EAAkB,EAAM,KAAK,EAAE,OAAO,QAAQ;KACrD;KACV,WAAU;KACV,CAAA,EACF,kBAAC,QAAD;KAAM,WAAU;eAA+B,EAAM;KAAmB,CAAA,CAClE;;GAGT,EAAM,SAAS,YAAY,EAAM,WAChC,kBAAC,UAAD;IACE,IAAI;IACJ,cAAY,EAAM;IAClB,OAAQ,KAAoB,EAAM,gBAAgB;IAClD,WAAW,MAAM,EAAkB,EAAM,KAAK,EAAE,OAAO,MAAM;IAC7D,cAAc,EAAgB,EAAM,IAAI;IAC9B;IACV,WAAW,GAAG,EAAmB;cAPnC,CASE,kBAAC,UAAD;KAAQ,OAAM;eAAd;MACG,EAAG,kBAAkB,SAAS;MAAC;MAAE,EAAM,YAAY,aAAa;MAC1D;QACR,EAAM,QAAQ,KAAK,MAClB,kBAAC,UAAD;KAAwB,OAAO,EAAI;eAChC,EAAI;KACE,EAFI,EAAI,MAER,CACT,CACK;;GAGV,EAAM,SAAS,aACd,kBAAC,KAAD;IAAG,WAAU;cAAoC,EAAM;IAAgB,CAAA;GAGxE,KACC,kBAAC,KAAD;IAAG,WAAU;cACV,EAAG,yBAAyB,yBAAyB;IACpD,CAAA;GAEF,EAAA,EA1HI,EAAM,IA0HV;;AAIV,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CAEE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cAA2C,EAAO;IAAiB,CAAA,EACjF,kBAAC,KAAD;IAAG,WAAU;cAAsC,EAAO;IAAgB,CAAA,CACtE,EAAA,CAAA,EACL,EAAO,UACN,kBAAC,KAAD;IACE,MAAM,EAAO;IACb,QAAO;IACP,KAAI;IACJ,WAAU;cAJZ,CAME,kBAAC,QAAD,EAAA,UAAO,EAAG,gBAAgB,OAAO,EAAQ,CAAA,EACzC,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA,CACxB;MAEF;MAGN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,EAAO,YAAY,SAAS,KAC3B,kBAAC,OAAD;IAAK,WAAU;cAAa,EAAO,YAAY,IAAI,EAAY;IAAO,CAAA,EAIvE,KAAwB,EAAO,oBAAoB,EAAO,iBAAiB,SAAS,KACnF,kBAAA,GAAA,EAAA,UACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eACV,EAAG,4BAA4B,oBAAoB;KAClD,CAAA,EACJ,kBAAC,OAAD;KAAK,WAAU;eAAa,EAAO,iBAAiB,IAAI,EAAY;KAAO,CAAA,CACvE;OACL,CAAA,CAED;KACF;;;AAOV,SAAgB,EAA2B,EACzC,gBACA,kBAIC;CACD,IAAM,IAAK,GAAO;AAElB,KAAI,CAAC,EAAa,QAAO;CAEzB,IAAM,EAAE,UAAO,cAAW,EAAoB,GAAa,EAAY;AAavE,QAXI,IAEA,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD,EAAc,MAAM,IAAM,CAAA,EAC1B,kBAAC,QAAD;GAAM,WAAU;aACb,EAAG,mCAAmC,6BAA6B;GAC/D,CAAA,CACH;MAKR,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA,EACzB,kBAAC,QAAD;GAAM,WAAU;aAAhB;IACG,EAAO;IAAO;IAAE,EAAG,+BAA+B,0BAA0B;IACxE;KACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeatureNotEnabled.d.ts","sourceRoot":"","sources":["../../../src/channel/components/FeatureNotEnabled.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FeatureNotEnabled.d.ts","sourceRoot":"","sources":["../../../src/channel/components/FeatureNotEnabled.tsx"],"names":[],"mappings":"AAIA,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE,sBAAsB,+BA+CjE"}
|
|
@@ -1,50 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { useTr as e } from "../hooks/useTr.js";
|
|
2
|
+
import { Lock as t } from "lucide-react";
|
|
3
|
+
import { usePermissions as n } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
4
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
5
|
//#region src/channel/components/FeatureNotEnabled.tsx
|
|
5
|
-
function
|
|
6
|
-
let { hasRole:
|
|
7
|
-
return /* @__PURE__ */
|
|
6
|
+
function a({ flag: a }) {
|
|
7
|
+
let { hasRole: o } = n(), s = o("SUPER_ADMIN"), c = e();
|
|
8
|
+
return /* @__PURE__ */ i("div", {
|
|
8
9
|
className: "flex flex-col items-center justify-center min-h-[400px] gap-4 text-center p-6",
|
|
9
|
-
children: [/* @__PURE__ */
|
|
10
|
+
children: [/* @__PURE__ */ r("div", {
|
|
10
11
|
className: "p-3 rounded-full bg-bg-elevated",
|
|
11
|
-
children: /* @__PURE__ */
|
|
12
|
-
}), /* @__PURE__ */
|
|
12
|
+
children: /* @__PURE__ */ r(t, { className: "size-8 text-fg-muted" })
|
|
13
|
+
}), /* @__PURE__ */ i("div", {
|
|
13
14
|
className: "space-y-2 max-w-md",
|
|
14
15
|
children: [
|
|
15
|
-
/* @__PURE__ */
|
|
16
|
+
/* @__PURE__ */ r("h3", {
|
|
16
17
|
className: "text-lg font-semibold text-fg",
|
|
17
|
-
children: "Feature not enabled"
|
|
18
|
+
children: c("channel.featureNotEnabled.title", "Feature not enabled")
|
|
18
19
|
}),
|
|
19
|
-
/* @__PURE__ */
|
|
20
|
+
/* @__PURE__ */ r("p", {
|
|
20
21
|
className: "text-sm text-fg-muted",
|
|
21
|
-
children: "This feature is currently disabled for your workspace."
|
|
22
|
+
children: c("channel.featureNotEnabled.description", "This feature is currently disabled for your workspace.")
|
|
22
23
|
}),
|
|
23
|
-
|
|
24
|
+
s ? /* @__PURE__ */ i("p", {
|
|
24
25
|
className: "text-sm text-fg-muted",
|
|
25
26
|
children: [
|
|
26
|
-
"You can enable it in",
|
|
27
|
+
c("channel.featureNotEnabled.adminPrefix", "You can enable it in"),
|
|
27
28
|
" ",
|
|
28
|
-
/* @__PURE__ */
|
|
29
|
+
/* @__PURE__ */ r("a", {
|
|
29
30
|
href: "/feature-previews",
|
|
30
31
|
className: "text-action-primary-text underline underline-offset-2 hover:text-action-primary-text-hover",
|
|
31
|
-
children: "Feature Previews"
|
|
32
|
+
children: c("channel.featureNotEnabled.featurePreviews", "Feature Previews")
|
|
32
33
|
}),
|
|
33
34
|
"."
|
|
34
35
|
]
|
|
35
|
-
}) : /* @__PURE__ */
|
|
36
|
+
}) : /* @__PURE__ */ r("p", {
|
|
36
37
|
className: "text-sm text-fg-muted",
|
|
37
|
-
children: "Contact your administrator if you believe this is in error."
|
|
38
|
+
children: c("channel.featureNotEnabled.contactAdmin", "Contact your administrator if you believe this is in error.")
|
|
38
39
|
}),
|
|
39
|
-
|
|
40
|
+
s && /* @__PURE__ */ i("p", {
|
|
40
41
|
className: "text-xs text-fg-subtle font-mono mt-1",
|
|
41
|
-
children: [
|
|
42
|
+
children: [
|
|
43
|
+
c("channel.featureNotEnabled.flagLabel", "flag"),
|
|
44
|
+
": ",
|
|
45
|
+
a
|
|
46
|
+
]
|
|
42
47
|
})
|
|
43
48
|
]
|
|
44
49
|
})]
|
|
45
50
|
});
|
|
46
51
|
}
|
|
47
52
|
//#endregion
|
|
48
|
-
export {
|
|
53
|
+
export { a as FeatureNotEnabled };
|
|
49
54
|
|
|
50
55
|
//# sourceMappingURL=FeatureNotEnabled.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeatureNotEnabled.js","names":[],"sources":["../../../src/channel/components/FeatureNotEnabled.tsx"],"sourcesContent":["import { Lock } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\n\ninterface FeatureNotEnabledProps {\n flag: string;\n}\n\n/**\n * Default fallback rendered when a feature flag is disabled. Behaves as a\n * \"404-style\" panel — never throws, never crashes the route.\n *\n * - The flag key is only shown to super admins (developer-facing detail).\n * - The CTA links to Feature Previews so admins can enable the flag directly.\n */\nexport function FeatureNotEnabled({ flag }: FeatureNotEnabledProps) {\n const { hasRole } = usePermissions();\n const isSuperAdmin = hasRole('SUPER_ADMIN');\n\n return (\n <div className=\"flex flex-col items-center justify-center min-h-[400px] gap-4 text-center p-6\">\n <div className=\"p-3 rounded-full bg-bg-elevated\">\n <Lock className=\"size-8 text-fg-muted\" />\n </div>\n <div className=\"space-y-2 max-w-md\">\n <h3 className=\"text-lg font-semibold text-fg\"
|
|
1
|
+
{"version":3,"file":"FeatureNotEnabled.js","names":[],"sources":["../../../src/channel/components/FeatureNotEnabled.tsx"],"sourcesContent":["import { Lock } from 'lucide-react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useTr } from '../hooks/useTr';\n\ninterface FeatureNotEnabledProps {\n flag: string;\n}\n\n/**\n * Default fallback rendered when a feature flag is disabled. Behaves as a\n * \"404-style\" panel — never throws, never crashes the route.\n *\n * - The flag key is only shown to super admins (developer-facing detail).\n * - The CTA links to Feature Previews so admins can enable the flag directly.\n */\nexport function FeatureNotEnabled({ flag }: FeatureNotEnabledProps) {\n const { hasRole } = usePermissions();\n const isSuperAdmin = hasRole('SUPER_ADMIN');\n const tr = useTr();\n\n return (\n <div className=\"flex flex-col items-center justify-center min-h-[400px] gap-4 text-center p-6\">\n <div className=\"p-3 rounded-full bg-bg-elevated\">\n <Lock className=\"size-8 text-fg-muted\" />\n </div>\n <div className=\"space-y-2 max-w-md\">\n <h3 className=\"text-lg font-semibold text-fg\">\n {tr('channel.featureNotEnabled.title', 'Feature not enabled')}\n </h3>\n <p className=\"text-sm text-fg-muted\">\n {tr(\n 'channel.featureNotEnabled.description',\n 'This feature is currently disabled for your workspace.'\n )}\n </p>\n {isSuperAdmin ? (\n <p className=\"text-sm text-fg-muted\">\n {tr('channel.featureNotEnabled.adminPrefix', 'You can enable it in')}{' '}\n <a\n href=\"/feature-previews\"\n className=\"text-action-primary-text underline underline-offset-2 hover:text-action-primary-text-hover\"\n >\n {tr('channel.featureNotEnabled.featurePreviews', 'Feature Previews')}\n </a>\n .\n </p>\n ) : (\n <p className=\"text-sm text-fg-muted\">\n {tr(\n 'channel.featureNotEnabled.contactAdmin',\n 'Contact your administrator if you believe this is in error.'\n )}\n </p>\n )}\n {isSuperAdmin && (\n <p className=\"text-xs text-fg-subtle font-mono mt-1\">\n {tr('channel.featureNotEnabled.flagLabel', 'flag')}: {flag}\n </p>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAeA,SAAgB,EAAkB,EAAE,WAAgC;CAClE,IAAM,EAAE,eAAY,GAAgB,EAC9B,IAAe,EAAQ,cAAc,EACrC,IAAK,GAAO;AAElB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAM,WAAU,wBAAyB,CAAA;GACrC,CAAA,EACN,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAG,mCAAmC,sBAAsB;KAC1D,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,yCACA,yDACD;KACC,CAAA;IACH,IACC,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAG,yCAAyC,uBAAuB;MAAE;MACtE,kBAAC,KAAD;OACE,MAAK;OACL,WAAU;iBAET,EAAG,6CAA6C,mBAAmB;OAClE,CAAA;;MAEF;SAEJ,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,0CACA,8DACD;KACC,CAAA;IAEL,KACC,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAG,uCAAuC,OAAO;MAAC;MAAG;MACpD;;IAEF;KACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownEditor.d.ts","sourceRoot":"","sources":["../../../src/channel/components/MarkdownEditor.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MarkdownEditor.d.ts","sourceRoot":"","sources":["../../../src/channel/components/MarkdownEditor.tsx"],"names":[],"mappings":"AASA,UAAU,mBAAmB;IAC3B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAkED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,WAAW,EACX,IAAQ,EACR,YAAY,EAAE,SAAS,EACvB,SAAc,EACd,iBAAsB,EACtB,EAAE,GACH,EAAE,mBAAmB,+BAsKrB"}
|