@nextclaw/ui 0.8.0 → 0.9.0
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/CHANGELOG.md +16 -0
- package/dist/assets/ChannelsList-C7F_As4r.js +1 -0
- package/dist/assets/ChatPage-Oo7-OUsx.js +37 -0
- package/dist/assets/{DocBrowser-DDX2HMXW.js → DocBrowser-Dsd8Dlq8.js} +1 -1
- package/dist/assets/{LogoBadge-J53F_3JA.js → LogoBadge-2ChEc_oz.js} +1 -1
- package/dist/assets/{MarketplacePage-0BZ4bza0.js → MarketplacePage-BXck6-X3.js} +3 -3
- package/dist/assets/{ModelConfig-Wzq9wGHV.js → ModelConfig-CgHRSD0b.js} +1 -1
- package/dist/assets/ProvidersList-PPfZucvS.js +1 -0
- package/dist/assets/{RuntimeConfig-N771_AM6.js → RuntimeConfig-ClLEKNTN.js} +1 -1
- package/dist/assets/{SearchConfig-DVt5QVa_.js → SearchConfig-CuXVCbrf.js} +1 -1
- package/dist/assets/{SecretsConfig-CkwauPa8.js → SecretsConfig-udJz6Ake.js} +1 -1
- package/dist/assets/{SessionsConfig-C3mnHzkZ.js → SessionsConfig-C1XnFfiC.js} +2 -2
- package/dist/assets/{chat-message-pxr79GDs.js → chat-message-BETwXLD4.js} +1 -1
- package/dist/assets/{index-GdpEEKnz.js → index-COJdlL0e.js} +1 -1
- package/dist/assets/index-CsvP4CER.js +8 -0
- package/dist/assets/index-D-bXl7qL.css +1 -0
- package/dist/assets/{label-CmksBHgc.js → label-BGL-ztxh.js} +1 -1
- package/dist/assets/{page-layout-Db0GbnhS.js → page-layout-aw88k7tG.js} +1 -1
- package/dist/assets/popover-DyEvzhmV.js +1 -0
- package/dist/assets/{security-config-CjLFME5Q.js → security-config-BuPAQn82.js} +1 -1
- package/dist/assets/skeleton-drzO_tdU.js +1 -0
- package/dist/assets/{switch-C24d-UJU.js → switch-BK8jIzto.js} +1 -1
- package/dist/assets/tabs-custom-Da3cEOji.js +1 -0
- package/dist/assets/{useConfirmDialog-BeP35LcG.js → useConfirmDialog-z0CE92iS.js} +1 -1
- package/dist/assets/{vendor-psXJBy9u.js → vendor-CkJHmX1g.js} +1 -1
- package/dist/index.html +3 -3
- package/package.json +2 -2
- package/src/api/config.ts +9 -38
- package/src/api/ncp-session.ts +50 -0
- package/src/api/types.ts +1 -0
- package/src/components/chat/ChatConversationPanel.test.tsx +65 -0
- package/src/components/chat/ChatConversationPanel.tsx +21 -12
- package/src/components/chat/ChatSidebar.test.tsx +203 -0
- package/src/components/chat/ChatSidebar.tsx +97 -7
- package/src/components/chat/adapters/chat-message.adapter.test.ts +132 -82
- package/src/components/chat/adapters/chat-message.adapter.ts +27 -9
- package/src/components/chat/chat-page-data.ts +30 -1
- package/src/components/chat/chat-page-runtime.test.ts +181 -0
- package/src/components/chat/chat-page-runtime.ts +101 -15
- package/src/components/chat/chat-session-preference-sync.test.ts +62 -0
- package/src/components/chat/chat-session-preference-sync.ts +75 -0
- package/src/components/chat/containers/chat-input-bar.container.tsx +0 -22
- package/src/components/chat/containers/chat-message-list.container.tsx +31 -27
- package/src/components/chat/legacy/LegacyChatPage.tsx +24 -0
- package/src/components/chat/managers/chat-input.manager.ts +5 -0
- package/src/components/chat/managers/chat-session-list.manager.test.ts +39 -0
- package/src/components/chat/managers/chat-session-list.manager.ts +9 -3
- package/src/components/chat/ncp/NcpChatPage.tsx +42 -10
- package/src/components/chat/ncp/ncp-chat-input.manager.ts +6 -0
- package/src/components/chat/ncp/ncp-chat-page-data.ts +34 -2
- package/src/components/chat/ncp/ncp-chat-thread.manager.ts +1 -1
- package/src/components/chat/ncp/ncp-session-adapter.test.ts +27 -1
- package/src/components/chat/ncp/ncp-session-adapter.ts +20 -0
- package/src/components/chat/stores/chat-thread.store.ts +2 -0
- package/src/components/chat/useChatSessionTypeState.test.tsx +58 -0
- package/src/components/chat/useChatSessionTypeState.ts +25 -8
- package/src/hooks/use-ncp-chat-session-types.ts +11 -0
- package/src/hooks/useConfig.ts +2 -4
- package/src/hooks/useMarketplace.ts +7 -4
- package/src/hooks/useWebSocket.ts +23 -2
- package/dist/assets/ChannelsList-DBcoVJRW.js +0 -1
- package/dist/assets/ChatPage-CD3cxyyM.js +0 -37
- package/dist/assets/ProvidersList-kwzRS8_M.js +0 -1
- package/dist/assets/index-BIvFMkN4.js +0 -1
- package/dist/assets/index-CzkY1reu.js +0 -8
- package/dist/assets/index-RZ0kHHRI.css +0 -1
- package/dist/assets/skeleton-CkpQeVWN.js +0 -1
- package/dist/assets/tabs-custom-D89bh-fc.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo } from 'react';
|
|
1
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import type { Dispatch, SetStateAction } from 'react';
|
|
3
3
|
import type { SessionEntryView } from '@/api/types';
|
|
4
4
|
import { t } from '@/lib/i18n';
|
|
@@ -33,13 +33,16 @@ export function resolveSessionTypeLabel(sessionType: string, fallbackLabel?: str
|
|
|
33
33
|
if (sessionType === 'native') {
|
|
34
34
|
return t('chatSessionTypeNative');
|
|
35
35
|
}
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const normalizedFallback = fallbackLabel?.trim();
|
|
37
|
+
if (normalizedFallback) {
|
|
38
|
+
return normalizedFallback;
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
return sessionType
|
|
41
|
+
.trim()
|
|
42
|
+
.split(/[-_]+/g)
|
|
43
|
+
.filter(Boolean)
|
|
44
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
45
|
+
.join(' ') || sessionType;
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
function buildSessionTypeOptions(
|
|
@@ -113,6 +116,7 @@ export function useChatSessionTypeState(params: UseChatSessionTypeStateParams):
|
|
|
113
116
|
() => normalizeSessionType(sessionTypesData?.defaultType ?? DEFAULT_SESSION_TYPE),
|
|
114
117
|
[sessionTypesData?.defaultType]
|
|
115
118
|
);
|
|
119
|
+
const lastAutoPendingSessionTypeRef = useRef<string | null>(null);
|
|
116
120
|
const selectedSessionType = useMemo(
|
|
117
121
|
() => normalizeSessionType(selectedSession?.sessionType ?? pendingSessionType ?? defaultSessionType),
|
|
118
122
|
[defaultSessionType, pendingSessionType, selectedSession?.sessionType]
|
|
@@ -122,8 +126,21 @@ export function useChatSessionTypeState(params: UseChatSessionTypeStateParams):
|
|
|
122
126
|
if (selectedSessionKey) {
|
|
123
127
|
return;
|
|
124
128
|
}
|
|
129
|
+
const rawPending = typeof pendingSessionType === 'string' ? pendingSessionType.trim() : '';
|
|
130
|
+
const normalizedPending = normalizeSessionType(pendingSessionType);
|
|
131
|
+
const shouldFollowDefault =
|
|
132
|
+
rawPending.length === 0 ||
|
|
133
|
+
lastAutoPendingSessionTypeRef.current === normalizedPending ||
|
|
134
|
+
(lastAutoPendingSessionTypeRef.current === null && normalizedPending === DEFAULT_SESSION_TYPE);
|
|
135
|
+
if (!shouldFollowDefault) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
lastAutoPendingSessionTypeRef.current = defaultSessionType;
|
|
139
|
+
if (normalizedPending === defaultSessionType) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
125
142
|
setPendingSessionType(defaultSessionType);
|
|
126
|
-
}, [defaultSessionType, selectedSessionKey, setPendingSessionType]);
|
|
143
|
+
}, [defaultSessionType, pendingSessionType, selectedSessionKey, setPendingSessionType]);
|
|
127
144
|
|
|
128
145
|
const canEditSessionType = !selectedSessionKey || Boolean(selectedSession?.sessionTypeMutable);
|
|
129
146
|
const availableSessionTypeSet = useMemo(
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
|
+
import { fetchNcpChatSessionTypes } from '@/api/config';
|
|
3
|
+
|
|
4
|
+
export function useNcpChatSessionTypes() {
|
|
5
|
+
return useQuery({
|
|
6
|
+
queryKey: ['ncp-session-types'],
|
|
7
|
+
queryFn: fetchNcpChatSessionTypes,
|
|
8
|
+
staleTime: 10_000,
|
|
9
|
+
retry: false
|
|
10
|
+
});
|
|
11
|
+
}
|
package/src/hooks/useConfig.ts
CHANGED
|
@@ -19,11 +19,8 @@ import {
|
|
|
19
19
|
executeConfigAction,
|
|
20
20
|
fetchSessions,
|
|
21
21
|
fetchSessionHistory,
|
|
22
|
-
fetchNcpSessions,
|
|
23
|
-
fetchNcpSessionMessages,
|
|
24
22
|
updateSession,
|
|
25
23
|
deleteSession,
|
|
26
|
-
deleteNcpSession,
|
|
27
24
|
sendChatTurn,
|
|
28
25
|
fetchChatRun,
|
|
29
26
|
fetchChatRuns,
|
|
@@ -34,6 +31,7 @@ import {
|
|
|
34
31
|
setCronJobEnabled,
|
|
35
32
|
runCronJob
|
|
36
33
|
} from '@/api/config';
|
|
34
|
+
import { deleteNcpSession, fetchNcpSessionMessages, fetchNcpSessions } from '@/api/ncp-session';
|
|
37
35
|
import { toast } from 'sonner';
|
|
38
36
|
import { t } from '@/lib/i18n';
|
|
39
37
|
|
|
@@ -390,7 +388,7 @@ export function useChatRuns(params?: {
|
|
|
390
388
|
if (params?.isLocallyRunning) {
|
|
391
389
|
return 800;
|
|
392
390
|
}
|
|
393
|
-
const data = query.state
|
|
391
|
+
const { data } = query.state;
|
|
394
392
|
const hasActiveRuns = Array.isArray(data?.runs) && data.runs.length > 0;
|
|
395
393
|
return hasActiveRuns ? 800 : false;
|
|
396
394
|
},
|
|
@@ -61,8 +61,10 @@ export function useInstallMarketplaceItem() {
|
|
|
61
61
|
mutationFn: (request: MarketplaceInstallRequest) => installMarketplaceItem(request),
|
|
62
62
|
onSuccess: (result) => {
|
|
63
63
|
queryClient.invalidateQueries({ queryKey: ['marketplace-installed', result.type] });
|
|
64
|
-
queryClient.
|
|
65
|
-
|
|
64
|
+
queryClient.invalidateQueries({ queryKey: ['marketplace-items'] });
|
|
65
|
+
if (result.type === 'plugin') {
|
|
66
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-session-types'] });
|
|
67
|
+
}
|
|
66
68
|
const fallback = result.type === 'plugin'
|
|
67
69
|
? t('marketplaceInstallSuccessPlugin')
|
|
68
70
|
: t('marketplaceInstallSuccessSkill');
|
|
@@ -82,8 +84,9 @@ export function useManageMarketplaceItem() {
|
|
|
82
84
|
onSuccess: (result) => {
|
|
83
85
|
queryClient.invalidateQueries({ queryKey: ['marketplace-installed', result.type] });
|
|
84
86
|
queryClient.invalidateQueries({ queryKey: ['marketplace-items'] });
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
if (result.type === 'plugin') {
|
|
88
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-session-types'] });
|
|
89
|
+
}
|
|
87
90
|
const fallback = result.action === 'enable'
|
|
88
91
|
? t('marketplaceEnableSuccess')
|
|
89
92
|
: result.action === 'disable'
|
|
@@ -73,11 +73,25 @@ export function useWebSocket(queryClient?: QueryClient) {
|
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
75
|
queryClient.invalidateQueries({ queryKey: ['sessions'] });
|
|
76
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-sessions'] });
|
|
76
77
|
if (sessionKey && sessionKey.trim().length > 0) {
|
|
77
78
|
queryClient.invalidateQueries({ queryKey: ['session-history', sessionKey.trim()] });
|
|
79
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-session-messages', sessionKey.trim()] });
|
|
78
80
|
return;
|
|
79
81
|
}
|
|
80
82
|
queryClient.invalidateQueries({ queryKey: ['session-history'] });
|
|
83
|
+
queryClient.invalidateQueries({ queryKey: ['ncp-session-messages'] });
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const shouldInvalidateConfigQuery = (configPath: string) => {
|
|
87
|
+
const normalized = configPath.trim().toLowerCase();
|
|
88
|
+
if (!normalized) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
if (normalized.startsWith('plugins') || normalized.startsWith('skills')) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
81
95
|
};
|
|
82
96
|
|
|
83
97
|
setConnectionStatus('connecting');
|
|
@@ -98,13 +112,20 @@ export function useWebSocket(queryClient?: QueryClient) {
|
|
|
98
112
|
});
|
|
99
113
|
|
|
100
114
|
client.on('config.updated', (event) => {
|
|
115
|
+
const payload = event.payload as { path?: unknown } | undefined;
|
|
116
|
+
const configPath = typeof payload?.path === 'string' ? payload.path : '';
|
|
101
117
|
// Trigger refetch of config
|
|
102
|
-
if (queryClient) {
|
|
118
|
+
if (queryClient && shouldInvalidateConfigQuery(configPath)) {
|
|
103
119
|
queryClient.invalidateQueries({ queryKey: ['config'] });
|
|
104
120
|
}
|
|
105
|
-
if (
|
|
121
|
+
if (configPath.startsWith('session')) {
|
|
106
122
|
invalidateSessionQueries();
|
|
107
123
|
}
|
|
124
|
+
if (configPath.startsWith('plugins')) {
|
|
125
|
+
queryClient?.invalidateQueries({ queryKey: ['ncp-session-types'] });
|
|
126
|
+
queryClient?.invalidateQueries({ queryKey: ['marketplace-installed', 'plugin'] });
|
|
127
|
+
queryClient?.invalidateQueries({ queryKey: ['marketplace-items'] });
|
|
128
|
+
}
|
|
108
129
|
});
|
|
109
130
|
|
|
110
131
|
client.on('run.updated', (event) => {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as v,j as a,a5 as Z,F as ee,e as T,K as ae,ah as te,aR as se,aS as ne,aT as le,z as re,s as oe,a8 as ce,v as ie}from"./vendor-psXJBy9u.js";import{t as e,c as I,Y as me,u as q,a as $,b as H,_ as pe,$ as de,I as D,S as be,e as ue,f as xe,g as ye,h as ge,B as E}from"./index-CzkY1reu.js";import{L as he}from"./label-CmksBHgc.js";import{S as fe}from"./switch-C24d-UJU.js";import{L as K,S as J}from"./LogoBadge-J53F_3JA.js";import{h as _}from"./config-hints-CApS3K_7.js";import{c as we,b as ve,a as je,C as ke}from"./config-layout-BHnOoweL.js";import{T as Se}from"./tabs-custom-D89bh-fc.js";import{P as Ce,a as Ne}from"./page-layout-Db0GbnhS.js";function Pe({value:t,onChange:m,className:i,placeholder:r=""}){const[o,u]=v.useState(""),d=x=>{x.key==="Enter"&&o.trim()?(x.preventDefault(),m([...t,o.trim()]),u("")):x.key==="Backspace"&&!o&&t.length>0&&m(t.slice(0,-1))},g=x=>{m(t.filter((j,h)=>h!==x))};return a.jsxs("div",{className:I("flex flex-wrap gap-2 p-2 border rounded-md min-h-[42px]",i),children:[t.map((x,j)=>a.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 bg-primary text-primary-foreground rounded text-sm",children:[x,a.jsx("button",{type:"button",onClick:()=>g(j),className:"hover:text-red-300 transition-colors",children:a.jsx(Z,{className:"h-3 w-3"})})]},j)),a.jsx("input",{type:"text",value:o,onChange:x=>u(x.target.value),onKeyDown:d,className:"flex-1 outline-none min-w-[100px] bg-transparent text-sm",placeholder:r||e("enterTag")})]})}function z(t){var r,o;const m=me();return((r=t.tutorialUrls)==null?void 0:r[m])||((o=t.tutorialUrls)==null?void 0:o.default)||t.tutorialUrl}const Ie={telegram:"telegram.svg",slack:"slack.svg",discord:"discord.svg",whatsapp:"whatsapp.svg",qq:"qq.svg",feishu:"feishu.svg",dingtalk:"dingtalk.svg",wecom:"wecom.svg",mochat:"mochat.svg",email:"email.svg"};function Fe(t,m){const i=m.toLowerCase(),r=t[i];return r?`/logos/${r}`:null}function Y(t){return Fe(Ie,t)}const R=[{value:"pairing",label:"pairing"},{value:"allowlist",label:"allowlist"},{value:"open",label:"open"},{value:"disabled",label:"disabled"}],B=[{value:"open",label:"open"},{value:"allowlist",label:"allowlist"},{value:"disabled",label:"disabled"}],Te=[{value:"off",label:"off"},{value:"partial",label:"partial"},{value:"block",label:"block"},{value:"progress",label:"progress"}],De=t=>t.includes("token")||t.includes("secret")||t.includes("password")?a.jsx(ae,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("url")||t.includes("host")?a.jsx(te,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("email")||t.includes("mail")?a.jsx(se,{className:"h-3.5 w-3.5 text-gray-500"}):t.includes("id")||t.includes("from")?a.jsx(ne,{className:"h-3.5 w-3.5 text-gray-500"}):t==="enabled"||t==="consentGranted"?a.jsx(le,{className:"h-3.5 w-3.5 text-gray-500"}):a.jsx(re,{className:"h-3.5 w-3.5 text-gray-500"});function G(){return{telegram:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"proxy",type:"text",label:e("proxy")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:R},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:B},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],discord:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"token",type:"password",label:e("botToken")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"allowFrom",type:"tags",label:e("allowFrom")},{name:"gatewayUrl",type:"text",label:e("gatewayUrl")},{name:"intents",type:"number",label:e("intents")},{name:"proxy",type:"text",label:e("proxy")},{name:"mediaMaxMb",type:"number",label:e("attachmentMaxSizeMb")},{name:"streaming",type:"select",label:e("streamingMode"),options:Te},{name:"draftChunk",type:"json",label:e("draftChunkingJson")},{name:"textChunkLimit",type:"number",label:e("textChunkLimit")},{name:"accountId",type:"text",label:e("accountId")},{name:"dmPolicy",type:"select",label:e("dmPolicy"),options:R},{name:"groupPolicy",type:"select",label:e("groupPolicy"),options:B},{name:"groupAllowFrom",type:"tags",label:e("groupAllowFrom")},{name:"requireMention",type:"boolean",label:e("requireMention")},{name:"mentionPatterns",type:"tags",label:e("mentionPatterns")},{name:"groups",type:"json",label:e("groupRulesJson")}],whatsapp:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"bridgeUrl",type:"text",label:e("bridgeUrl")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],feishu:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"appSecret",type:"password",label:e("appSecret")},{name:"encryptKey",type:"password",label:e("encryptKey")},{name:"verificationToken",type:"password",label:e("verificationToken")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],dingtalk:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"clientId",type:"text",label:e("clientId")},{name:"clientSecret",type:"password",label:e("clientSecret")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],wecom:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"corpId",type:"text",label:e("corpId")},{name:"agentId",type:"text",label:e("agentId")},{name:"secret",type:"password",label:e("secret")},{name:"token",type:"password",label:e("token")},{name:"callbackPort",type:"number",label:e("callbackPort")},{name:"callbackPath",type:"text",label:e("callbackPath")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],slack:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"mode",type:"text",label:e("mode")},{name:"webhookPath",type:"text",label:e("webhookPath")},{name:"allowBots",type:"boolean",label:e("allowBotMessages")},{name:"botToken",type:"password",label:e("botToken")},{name:"appToken",type:"password",label:e("appToken")}],email:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"consentGranted",type:"boolean",label:e("consentGranted")},{name:"imapHost",type:"text",label:e("imapHost")},{name:"imapPort",type:"number",label:e("imapPort")},{name:"imapUsername",type:"text",label:e("imapUsername")},{name:"imapPassword",type:"password",label:e("imapPassword")},{name:"fromAddress",type:"email",label:e("fromAddress")}],mochat:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"baseUrl",type:"text",label:e("baseUrl")},{name:"clawToken",type:"password",label:e("clawToken")},{name:"agentUserId",type:"text",label:e("agentUserId")},{name:"allowFrom",type:"tags",label:e("allowFrom")}],qq:[{name:"enabled",type:"boolean",label:e("enabled")},{name:"appId",type:"text",label:e("appId")},{name:"secret",type:"password",label:e("appSecret")},{name:"markdownSupport",type:"boolean",label:e("markdownSupport")},{name:"allowFrom",type:"tags",label:e("allowFrom")}]}}function A(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function V(t,m){const i={...t};for(const[r,o]of Object.entries(m)){const u=i[r];if(A(u)&&A(o)){i[r]=V(u,o);continue}i[r]=o}return i}function Ae(t,m){const i=t.split("."),r={};let o=r;for(let u=0;u<i.length-1;u+=1){const d=i[u];o[d]={},o=o[d]}return o[i[i.length-1]]=m,r}function Le({channelName:t}){var O,U;const{data:m}=q(),{data:i}=$(),{data:r}=H(),o=pe(),u=de(),[d,g]=v.useState({}),[x,j]=v.useState({}),[h,f]=v.useState(null),k=t?m==null?void 0:m.channels[t]:null,w=t?G()[t]??[]:[],c=r==null?void 0:r.uiHints,p=t?`channels.${t}`:null,S=((O=r==null?void 0:r.actions)==null?void 0:O.filter(s=>s.scope===p))??[],C=t&&(((U=_(`channels.${t}`,c))==null?void 0:U.label)??t),P=i==null?void 0:i.channels.find(s=>s.name===t),F=P?z(P):void 0;v.useEffect(()=>{if(k){g({...k});const s={};(t?G()[t]??[]:[]).filter(l=>l.type==="json").forEach(l=>{const y=k[l.name];s[l.name]=JSON.stringify(y??{},null,2)}),j(s)}else g({}),j({})},[k,t]);const N=(s,n)=>{g(l=>({...l,[s]:n}))},L=s=>{if(s.preventDefault(),!t)return;const n={...d};for(const l of w){if(l.type!=="password")continue;const y=n[l.name];(typeof y!="string"||y.length===0)&&delete n[l.name]}for(const l of w){if(l.type!=="json")continue;const y=x[l.name]??"";try{n[l.name]=y.trim()?JSON.parse(y):{}}catch{T.error(`${e("invalidJson")}: ${l.name}`);return}}o.mutate({channel:t,data:n})},Q=s=>{if(!s||!t)return;const n=s.channels;if(!A(n))return;const l=n[t];A(l)&&g(y=>V(y,l))},W=async s=>{if(!(!t||!p)){f(s.id);try{let n={...d};s.saveBeforeRun&&(n={...n,...s.savePatch??{}},g(n),await o.mutateAsync({channel:t,data:n}));const l=await u.mutateAsync({actionId:s.id,data:{scope:p,draftConfig:Ae(p,n)}});Q(l.patch),l.ok?T.success(l.message||e("success")):T.error(l.message||e("error"))}catch(n){const l=n instanceof Error?n.message:String(n);T.error(`${e("error")}: ${l}`)}finally{f(null)}}};if(!t||!P||!k)return a.jsx("div",{className:we,children:a.jsxs("div",{children:[a.jsx("h3",{className:"text-base font-semibold text-gray-900",children:e("channelsSelectTitle")}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsSelectDescription")})]})});const M=!!k.enabled;return a.jsxs("div",{className:ve,children:[a.jsx("div",{className:"border-b border-gray-100 px-6 py-5",children:a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[a.jsxs("div",{className:"min-w-0",children:[a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsx(K,{name:t,src:Y(t),className:I("h-9 w-9 rounded-lg border",M?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:t[0]})}),a.jsx("h3",{className:"truncate text-lg font-semibold text-gray-900 capitalize",children:C})]}),a.jsx("p",{className:"mt-2 text-sm text-gray-500",children:e("channelsFormDescription")}),F&&a.jsxs("a",{href:F,className:"mt-2 inline-flex items-center gap-1.5 text-xs text-primary transition-colors hover:text-primary-hover",children:[a.jsx(ee,{className:"h-3.5 w-3.5"}),e("channelsGuideTitle")]})]}),a.jsx(J,{status:M?"active":"inactive",label:M?e("statusActive"):e("statusInactive")})]})}),a.jsxs("form",{onSubmit:L,className:"flex min-h-0 flex-1 flex-col",children:[a.jsx("div",{className:"min-h-0 flex-1 space-y-6 overflow-y-auto overscroll-contain px-6 py-5",children:w.map(s=>{const n=t?_(`channels.${t}.${s.name}`,c):void 0,l=(n==null?void 0:n.label)??s.label,y=n==null?void 0:n.placeholder;return a.jsxs("div",{className:"space-y-2.5",children:[a.jsxs(he,{htmlFor:s.name,className:"flex items-center gap-2 text-sm font-medium text-gray-900",children:[De(s.name),l]}),s.type==="boolean"&&a.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-3",children:[a.jsx("span",{className:"text-sm text-gray-500",children:d[s.name]?e("enabled"):e("disabled")}),a.jsx(fe,{id:s.name,checked:d[s.name]||!1,onCheckedChange:b=>N(s.name,b),className:"data-[state=checked]:bg-emerald-500"})]}),(s.type==="text"||s.type==="email")&&a.jsx(D,{id:s.name,type:s.type,value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y,className:"rounded-xl"}),s.type==="password"&&a.jsx(D,{id:s.name,type:"password",value:d[s.name]||"",onChange:b=>N(s.name,b.target.value),placeholder:y??e("leaveBlankToKeepUnchanged"),className:"rounded-xl"}),s.type==="number"&&a.jsx(D,{id:s.name,type:"number",value:d[s.name]||0,onChange:b=>N(s.name,parseInt(b.target.value,10)||0),placeholder:y,className:"rounded-xl"}),s.type==="tags"&&a.jsx(Pe,{value:d[s.name]||[],onChange:b=>N(s.name,b)}),s.type==="select"&&a.jsxs(be,{value:d[s.name]||"",onValueChange:b=>N(s.name,b),children:[a.jsx(ue,{className:"rounded-xl",children:a.jsx(xe,{})}),a.jsx(ye,{children:(s.options??[]).map(b=>a.jsx(ge,{value:b.value,children:b.label},b.value))})]}),s.type==="json"&&a.jsx("textarea",{id:s.name,value:x[s.name]??"{}",onChange:b=>j(X=>({...X,[s.name]:b.target.value})),className:"min-h-[120px] w-full resize-none rounded-lg border border-gray-200 bg-white px-3 py-2 text-xs font-mono"})]},s.name)})}),a.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 border-t border-gray-100 px-6 py-4",children:[a.jsx("div",{className:"flex flex-wrap items-center gap-2",children:S.filter(s=>s.trigger==="manual").map(s=>a.jsx(E,{type:"button",onClick:()=>W(s),disabled:o.isPending||!!h,variant:"secondary",children:h===s.id?e("connecting"):s.title},s.id))}),a.jsx(E,{type:"submit",disabled:o.isPending||!!h,children:o.isPending?e("saving"):e("save")})]})]})]})}const Me={telegram:"channelDescTelegram",slack:"channelDescSlack",email:"channelDescEmail",webhook:"channelDescWebhook",discord:"channelDescDiscord",feishu:"channelDescFeishu"};function He(){const{data:t}=q(),{data:m}=$(),{data:i}=H(),[r,o]=v.useState("enabled"),[u,d]=v.useState(),[g,x]=v.useState(""),j=i==null?void 0:i.uiHints,h=m==null?void 0:m.channels,f=t==null?void 0:t.channels,k=[{id:"enabled",label:e("channelsTabEnabled"),count:(h??[]).filter(c=>{var p;return(p=f==null?void 0:f[c.name])==null?void 0:p.enabled}).length},{id:"all",label:e("channelsTabAll"),count:(h??[]).length}],w=v.useMemo(()=>{const c=g.trim().toLowerCase();return(h??[]).filter(p=>{var C;const S=((C=f==null?void 0:f[p.name])==null?void 0:C.enabled)||!1;return r==="enabled"?S:!0}).filter(p=>c?(p.displayName||p.name).toLowerCase().includes(c)||p.name.toLowerCase().includes(c):!0)},[r,f,h,g]);return v.useEffect(()=>{if(w.length===0){d(void 0);return}w.some(p=>p.name===u)||d(w[0].name)},[w,u]),!t||!m?a.jsx("div",{className:"p-8 text-gray-400",children:e("channelsLoading")}):a.jsxs(Ce,{className:"xl:flex xl:h-full xl:min-h-0 xl:flex-col xl:pb-0",children:[a.jsx(Ne,{title:e("channelsPageTitle"),description:e("channelsPageDescription")}),a.jsxs("div",{className:I(ke,"xl:min-h-0 xl:flex-1"),children:[a.jsxs("section",{className:je,children:[a.jsx("div",{className:"border-b border-gray-100 px-4 pt-4",children:a.jsx(Se,{tabs:k,activeTab:r,onChange:o,className:"mb-0"})}),a.jsx("div",{className:"border-b border-gray-100 px-4 py-3",children:a.jsxs("div",{className:"relative",children:[a.jsx(oe,{className:"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400"}),a.jsx(D,{value:g,onChange:c=>x(c.target.value),placeholder:e("channelsFilterPlaceholder"),className:"h-10 rounded-xl pl-9"})]})}),a.jsxs("div",{className:"min-h-0 flex-1 space-y-2 overflow-y-auto overscroll-contain p-3",children:[w.map(c=>{const p=t.channels[c.name],S=(p==null?void 0:p.enabled)||!1,C=_(`channels.${c.name}`,j),P=z(c),F=(C==null?void 0:C.help)||e(Me[c.name]||"channelDescriptionDefault"),N=u===c.name;return a.jsx("button",{type:"button",onClick:()=>d(c.name),className:I("w-full rounded-xl border p-2.5 text-left transition-all",N?"border-primary/30 bg-primary-50/40 shadow-sm":"border-gray-200/70 bg-white hover:border-gray-300 hover:bg-gray-50/70"),children:a.jsxs("div",{className:"flex items-start justify-between gap-3",children:[a.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[a.jsx(K,{name:c.name,src:Y(c.name),className:I("h-10 w-10 rounded-lg border",S?"border-primary/30 bg-white":"border-gray-200/70 bg-white"),imgClassName:"h-5 w-5 object-contain",fallback:a.jsx("span",{className:"text-sm font-semibold uppercase text-gray-500",children:c.name[0]})}),a.jsxs("div",{className:"min-w-0",children:[a.jsx("p",{className:"truncate text-sm font-semibold text-gray-900",children:c.displayName||c.name}),a.jsx("p",{className:"line-clamp-1 text-[11px] text-gray-500",children:F})]})]}),a.jsxs("div",{className:"flex items-center gap-2",children:[P&&a.jsx("a",{href:P,onClick:L=>L.stopPropagation(),className:"inline-flex h-7 w-7 items-center justify-center rounded-md text-gray-300 transition-colors hover:bg-gray-100/70 hover:text-gray-500",title:e("channelsGuideTitle"),children:a.jsx(ce,{className:"h-3.5 w-3.5"})}),a.jsx(J,{status:S?"active":"inactive",label:S?e("statusActive"):e("statusInactive"),className:"min-w-[56px] justify-center"})]})]})},c.name)}),w.length===0&&a.jsxs("div",{className:"flex h-full min-h-[220px] flex-col items-center justify-center rounded-xl border border-dashed border-gray-200 bg-gray-50/70 py-10 text-center",children:[a.jsx("div",{className:"mb-3 flex h-10 w-10 items-center justify-center rounded-lg bg-white",children:a.jsx(ie,{className:"h-5 w-5 text-gray-300"})}),a.jsx("p",{className:"text-sm font-medium text-gray-700",children:e("channelsNoMatch")})]})]})]}),a.jsx(Le,{channelName:u})]})]})}export{He as ChannelsList};
|