tmex-cli 0.1.7 → 0.2.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/runtime/server.js +2924 -514
- package/package.json +2 -3
- package/resources/fe-dist/assets/DevicePage-6GBZ9nXN.css +32 -0
- package/resources/fe-dist/assets/DevicePage-DDl0kHG5.js +267 -0
- package/resources/fe-dist/assets/DevicePage-DDl0kHG5.js.map +1 -0
- package/resources/fe-dist/assets/{DevicesPage-DClS6lhB.js → DevicesPage-B4rMKhEo.js} +3 -3
- package/resources/fe-dist/assets/{DevicesPage-DClS6lhB.js.map → DevicesPage-B4rMKhEo.js.map} +1 -1
- package/resources/fe-dist/assets/SettingsPage-CNlEDOxd.js +17 -0
- package/resources/fe-dist/assets/SettingsPage-CNlEDOxd.js.map +1 -0
- package/resources/fe-dist/assets/index-35UZ83ei.js +200 -0
- package/resources/fe-dist/assets/index-35UZ83ei.js.map +1 -0
- package/resources/fe-dist/assets/index-CxzyWqMn.css +1 -0
- package/resources/fe-dist/assets/select-Eq1zbeJ1.js +17 -0
- package/resources/fe-dist/assets/select-Eq1zbeJ1.js.map +1 -0
- package/resources/fe-dist/assets/{switch-DbiHVHFg.js → switch-MW4hLOq6.js} +3 -3
- package/resources/fe-dist/assets/{switch-DbiHVHFg.js.map → switch-MW4hLOq6.js.map} +1 -1
- package/resources/fe-dist/assets/useValueChanged-ia5UgAxm.js +7 -0
- package/resources/fe-dist/assets/useValueChanged-ia5UgAxm.js.map +1 -0
- package/resources/fe-dist/index.html +2 -2
- package/resources/fe-dist/assets/DevicePage-Beg8tuEN.css +0 -32
- package/resources/fe-dist/assets/DevicePage-DXr7cn5f.js +0 -31
- package/resources/fe-dist/assets/DevicePage-DXr7cn5f.js.map +0 -1
- package/resources/fe-dist/assets/SettingsPage-DZPiSKLS.js +0 -17
- package/resources/fe-dist/assets/SettingsPage-DZPiSKLS.js.map +0 -1
- package/resources/fe-dist/assets/index-DLLCJhRn.css +0 -1
- package/resources/fe-dist/assets/index-uap7lu9-.js +0 -200
- package/resources/fe-dist/assets/index-uap7lu9-.js.map +0 -1
- package/resources/fe-dist/assets/select-DOLHUgAj.js +0 -12
- package/resources/fe-dist/assets/select-DOLHUgAj.js.map +0 -1
- package/resources/fe-dist/assets/useValueChanged-DoNZeDee.js +0 -2
- package/resources/fe-dist/assets/useValueChanged-DoNZeDee.js.map +0 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import{c as G,u as B,a as ge,b as xe,r as i,d as ce,e as z,j as e,B as d,I as de,t as pe,f as o,i as ve}from"./index-35UZ83ei.js";import{u as j,C as M,a as $,b as I,c as D,I as g,S as ke,d as Ce,e as Se,f as Ee,g as Te}from"./select-Eq1zbeJ1.js";import{T as je,A as Fe,a as Be,b as Pe,c as Re,d as qe,e as Ae,f as Me,g as $e}from"./useValueChanged-ia5UgAxm.js";import{S as F,L as me,a as Ie}from"./switch-MW4hLOq6.js";/**
|
|
2
|
+
* @license lucide-react v0.564.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const De=[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"1357e3"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}]],ze=G("rotate-ccw",De);/**
|
|
7
|
+
* @license lucide-react v0.564.0 - ISC
|
|
8
|
+
*
|
|
9
|
+
* This source code is licensed under the ISC license.
|
|
10
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
11
|
+
*/const Le=[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]],L=G("save",Le);/**
|
|
12
|
+
* @license lucide-react v0.564.0 - ISC
|
|
13
|
+
*
|
|
14
|
+
* This source code is licensed under the ISC license.
|
|
15
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
16
|
+
*/const Qe=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]],he=G("shield",Qe);async function h(s,m){try{return(await s.json()).error??m}catch{return m}}function We(){var ie,oe,re,le;const{t:s}=B(),m=ge(),{refreshSettings:u}=xe(),[n,r]=i.useState("site"),x=ce(t=>t.theme),y=ce(t=>t.setTheme),b=x==="dark",[w,k]=i.useState("tmex"),[C,S]=i.useState(window.location.origin),[p,N]=i.useState("en_US"),[f,P]=i.useState(6),[R,q]=i.useState(!0),[E,A]=i.useState(!0),[T,a]=i.useState(2),[l,v]=i.useState(10),[we,be]=i.useState(!1),[Q,X]=i.useState(""),[K,Y]=i.useState(""),[fe,ye]=i.useState(null),[U,Z]=i.useState(""),[O,ee]=i.useState(""),Ne=t=>{const c=t?"dark":"light";y(c),document.documentElement.classList.toggle("dark",c==="dark")},_=z({queryKey:["site-settings"],queryFn:async()=>{const t=await fetch("/api/settings/site");if(!t.ok)throw new Error(await h(t,s("settings.loadFailed")));return await t.json()}}),H=z({queryKey:["telegram-bots"],queryFn:async()=>{const t=await fetch("/api/settings/telegram/bots");if(!t.ok)throw new Error(await h(t,s("telegram.loadBotsFailed")));return await t.json()}});i.useEffect(()=>{var c;const t=(c=_.data)==null?void 0:c.settings;t&&(k(t.siteName),S(t.siteUrl),N(t.language??"en_US"),P(t.bellThrottleSeconds),q(t.enableBrowserBellToast??!0),A(t.enableTelegramBellPush??!0),a(t.sshReconnectMaxRetries),v(t.sshReconnectDelaySeconds))},[(ie=_.data)==null?void 0:ie.settings]);const se=j({mutationFn:async()=>{const c=await fetch("/api/settings/site",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({siteName:w,siteUrl:C,language:p,bellThrottleSeconds:f,enableBrowserBellToast:R,enableTelegramBellPush:E,sshReconnectMaxRetries:T,sshReconnectDelaySeconds:l})});if(!c.ok)throw new Error(await h(c,s("settings.saveFailed")))},onSuccess:async()=>{var t,c;await Promise.all([m.invalidateQueries({queryKey:["site-settings"]}),u()]),o.success(s("settings.settingsSaved")),((c=(t=_.data)==null?void 0:t.settings)==null?void 0:c.language)!==p&&(ve.changeLanguage(p),be(!0))},onError:t=>{o.error(t instanceof Error?t.message:s("common.error"))}}),W=j({mutationFn:async()=>{const t=await fetch("/api/settings/telegram/bots",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:Q,token:K,enabled:!0,allowAuthRequests:!0})});if(!t.ok)throw new Error(await h(t,s("telegram.createFailed")))},onSuccess:async()=>{X(""),Y(""),await m.invalidateQueries({queryKey:["telegram-bots"]}),o.success(s("common.success"))},onError:t=>{o.error(t instanceof Error?t.message:s("common.error"))}}),te=((oe=H.data)==null?void 0:oe.bots)??[],J=z({queryKey:["webhooks"],queryFn:async()=>{const t=await fetch("/api/webhooks");if(!t.ok)throw new Error(await h(t,s("webhook.loadFailed")));return await t.json()}}),V=j({mutationFn:async()=>{const t=await fetch("/api/webhooks",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:U,secret:O})});if(!t.ok)throw new Error(await h(t,s("webhook.createFailed")))},onSuccess:async()=>{Z(""),ee(""),await m.invalidateQueries({queryKey:["webhooks"]}),o.success(s("common.success"))},onError:t=>{o.error(t instanceof Error?t.message:s("common.error"))}}),ae=j({mutationFn:async t=>{const c=await fetch(`/api/webhooks/${t}`,{method:"DELETE"});if(!c.ok)throw new Error(await h(c,s("webhook.deleteFailed")))},onSuccess:async()=>{await m.invalidateQueries({queryKey:["webhooks"]}),o.success(s("common.success"))},onError:t=>{o.error(t instanceof Error?t.message:s("common.error"))}}),ne=((re=J.data)==null?void 0:re.webhooks)??[];return e.jsxs("div",{className:"mx-auto flex w-full max-w-6xl flex-col gap-4 p-3 pb-[calc(2rem+env(safe-area-inset-bottom))] sm:gap-6 sm:p-5","data-testid":"settings-page",children:[e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(d,{type:"button",size:"sm",variant:n==="site"?"default":"outline","data-testid":"settings-tab-site",onClick:()=>r("site"),children:s("settings.siteSettings")}),e.jsx(d,{type:"button",size:"sm",variant:n==="notifications"?"default":"outline","data-testid":"settings-tab-notifications",onClick:()=>r("notifications"),children:s("settings.notificationsTab")}),e.jsx(d,{type:"button",size:"sm",variant:n==="telegram"?"default":"outline","data-testid":"settings-tab-telegram",onClick:()=>r("telegram"),children:s("telegram.title")}),e.jsx(d,{type:"button",size:"sm",variant:n==="webhooks"?"default":"outline","data-testid":"settings-tab-webhooks",onClick:()=>r("webhooks"),children:s("webhook.title")})]}),n==="site"&&e.jsxs(M,{className:"border-0 ring-0",children:[e.jsx($,{children:e.jsx(I,{children:s("settings.siteSettings")})}),e.jsxs(D,{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"site-name-input",children:s("settings.siteName")}),e.jsx(g,{id:"site-name-input",value:w,onChange:t=>k(t.target.value),placeholder:s("settings.siteNamePlaceholder"),className:"min-h-10"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"site-url-input",children:s("settings.siteUrl")}),e.jsx(g,{id:"site-url-input",value:C,onChange:t=>S(t.target.value),placeholder:s("settings.siteUrlPlaceholder"),className:"min-h-10"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"language-select",children:s("settings.language")}),e.jsxs(ke,{value:p,onValueChange:t=>{t&&N(t)},children:[e.jsx(Ce,{id:"language-select","data-testid":"settings-language-select",className:"w-full min-h-10",children:e.jsx(Se,{placeholder:s("settings.language"),children:((le=de.locales.find(t=>t.code===p))==null?void 0:le.nativeName)??p})}),e.jsx(Ee,{className:"max-h-[var(--tmex-viewport-height)]",children:de.locales.map(t=>e.jsx(Te,{value:t.code,children:t.nativeName},t.code))})]}),we&&e.jsx("p",{className:"mt-1 text-xs text-primary","data-testid":"settings-refresh-notice",children:s("settings.refreshToApply")})]}),e.jsx("div",{className:"space-y-3",children:e.jsxs("div",{className:"flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5",children:[e.jsx("div",{className:"min-w-0 pr-2",children:e.jsx("div",{className:"text-sm font-medium",children:s("settings.theme")})}),e.jsx(F,{checked:b,onCheckedChange:t=>Ne(!!t),"data-testid":"settings-theme-toggle"})]})})]})]}),n==="notifications"&&e.jsxs(M,{className:"border-0 ring-0",children:[e.jsx($,{children:e.jsx(I,{children:s("settings.notificationsTab")})}),e.jsxs(D,{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5",children:[e.jsx("div",{className:"min-w-0 pr-2",children:e.jsx("div",{className:"text-sm font-medium",children:s("settings.enableBrowserBellToast")})}),e.jsx(F,{checked:R,onCheckedChange:t=>q(!!t),"data-testid":"settings-enable-browser-bell-toast"})]}),e.jsxs("div",{className:"flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5",children:[e.jsx("div",{className:"min-w-0 pr-2",children:e.jsx("div",{className:"text-sm font-medium",children:s("settings.enableTelegramBellPush")})}),e.jsx(F,{checked:E,onCheckedChange:t=>A(!!t),"data-testid":"settings-enable-telegram-bell-push"})]})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-4 sm:grid-cols-3",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"bell-throttle-input",children:s("settings.bellThrottle")}),e.jsx(g,{id:"bell-throttle-input",type:"number",value:f,min:0,max:300,onChange:t=>P(Number(t.target.value)),className:"min-h-10"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"ssh-reconnect-retries-input",children:s("settings.sshReconnectMaxRetries")}),e.jsx(g,{id:"ssh-reconnect-retries-input",type:"number",value:T,min:0,max:20,onChange:t=>a(Number(t.target.value)),className:"min-h-10"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"ssh-reconnect-delay-input",children:s("settings.sshReconnectDelay")}),e.jsx(g,{id:"ssh-reconnect-delay-input",type:"number",value:l,min:1,max:300,onChange:t=>v(Number(t.target.value)),className:"min-h-10"})]})]})]})]}),n==="telegram"&&e.jsxs(M,{className:"border-0 ring-0",children:[e.jsx($,{children:e.jsx(I,{children:s("telegram.title")})}),e.jsxs(D,{className:"space-y-6",children:[e.jsx("div",{className:"space-y-4",children:e.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end",children:[e.jsxs("div",{className:"md:col-span-4 space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"new-bot-name",children:s("telegram.botName")}),e.jsx(g,{id:"new-bot-name",value:Q,onChange:t=>X(t.target.value),placeholder:s("telegram.botNamePlaceholder"),className:"min-h-10"})]}),e.jsxs("div",{className:"md:col-span-6 space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"new-bot-token",children:s("telegram.botToken")}),e.jsx(g,{id:"new-bot-token",type:"password",value:K,onChange:t=>Y(t.target.value),placeholder:s("telegram.botTokenPlaceholder"),className:"min-h-10"})]}),e.jsx("div",{className:"md:col-span-2",children:e.jsxs(d,{variant:"default",className:"w-full md:w-auto","data-testid":"telegram-add-bot",onClick:()=>W.mutate(),disabled:W.isPending||!Q.trim()||!K.trim(),children:[W.isPending?e.jsx(me,{className:"h-4 w-4 animate-spin"}):e.jsx(L,{className:"h-4 w-4"}),s("telegram.addBot")]})})]})}),e.jsxs("div",{className:"space-y-3",children:[H.isLoading&&e.jsx("div",{className:"text-sm text-muted-foreground",children:s("common.loading")}),!H.isLoading&&te.length===0&&e.jsx("div",{className:"text-sm text-muted-foreground",children:s("telegram.addBot")}),te.map(t=>e.jsx(Ke,{bot:t,expanded:fe===t.id,onToggleExpand:()=>{ye(c=>c===t.id?null:t.id)}},t.id))]})]})]}),n==="webhooks"&&e.jsxs(M,{className:"border-0 ring-0",children:[e.jsx($,{children:e.jsx(I,{children:s("webhook.title")})}),e.jsxs(D,{className:"space-y-6",children:[e.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end",children:[e.jsxs("div",{className:"md:col-span-6 space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"webhook-url-input",children:s("webhook.url")}),e.jsx(g,{id:"webhook-url-input","data-testid":"webhook-url-input",value:U,onChange:t=>Z(t.target.value),placeholder:"https://example.com/webhook",className:"min-h-10"})]}),e.jsxs("div",{className:"md:col-span-4 space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:"webhook-secret-input",children:s("webhook.secret")}),e.jsx(g,{id:"webhook-secret-input","data-testid":"webhook-secret-input",value:O,onChange:t=>ee(t.target.value),placeholder:s("webhook.secretPlaceholder"),className:"min-h-10"})]}),e.jsx("div",{className:"md:col-span-2",children:e.jsxs(d,{variant:"default",className:"w-full md:w-auto","data-testid":"webhook-add",onClick:()=>V.mutate(),disabled:V.isPending||!U.trim()||!O.trim(),children:[V.isPending?e.jsx(me,{className:"h-4 w-4 animate-spin"}):e.jsx(L,{className:"h-4 w-4"}),s("webhook.add")]})})]}),e.jsxs("div",{className:"space-y-2",children:[J.isLoading&&e.jsx("div",{className:"text-sm text-muted-foreground",children:s("common.loading")}),!J.isLoading&&ne.length===0&&e.jsx("div",{className:"text-sm text-muted-foreground",children:s("webhook.empty")}),ne.map(t=>e.jsxs("div",{"data-testid":"webhook-item","data-webhook-url":t.url,className:"flex items-center justify-between gap-3 rounded-lg border border-border bg-card px-4 py-2.5",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium",children:t.url}),e.jsx("div",{className:"text-xs text-muted-foreground",children:new Date(t.createdAt).toLocaleString(pe(p))})]}),e.jsx(d,{variant:"ghost",size:"icon-sm","data-testid":"webhook-delete",onClick:()=>ae.mutate(t.id),disabled:ae.isPending,"aria-label":s("common.delete"),title:s("common.delete"),children:e.jsx(je,{className:"h-4 w-4"})})]},t.id))]})]})]}),(n==="site"||n==="notifications")&&e.jsx("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end",children:e.jsxs(d,{variant:"default","data-testid":"settings-save",onClick:()=>se.mutate(),disabled:se.isPending,className:"w-full sm:w-auto",children:[e.jsx(L,{className:"h-4 w-4"}),s("common.save")]})})]})}function Ke({bot:s,expanded:m,onToggleExpand:u}){var T;const{t:n}=B(),r=ge(),[x,y]=i.useState(s.name),[b,w]=i.useState(""),[k,C]=i.useState(s.enabled),[S,p]=i.useState(s.allowAuthRequests);i.useEffect(()=>{y(s.name),C(s.enabled),p(s.allowAuthRequests)},[s.allowAuthRequests,s.enabled,s.name]);const N=z({queryKey:["telegram-bot-chats",s.id],enabled:m,queryFn:async()=>{const a=await fetch(`/api/settings/telegram/bots/${s.id}/chats`);if(!a.ok)throw new Error(await h(a,n("telegram.loadChatsFailed")));return await a.json()}}),f=i.useMemo(()=>{var l;const a=((l=N.data)==null?void 0:l.chats)??[];return{pending:a.filter(v=>v.status==="pending"),authorized:a.filter(v=>v.status==="authorized")}},[(T=N.data)==null?void 0:T.chats]),P=j({mutationFn:async()=>{const a={name:x,enabled:k,allowAuthRequests:S};b.trim()&&(a.token=b.trim());const l=await fetch(`/api/settings/telegram/bots/${s.id}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)});if(!l.ok)throw new Error(await h(l,n("telegram.updateFailed")))},onSuccess:async()=>{w(""),await r.invalidateQueries({queryKey:["telegram-bots"]}),o.success(n("common.success"))},onError:a=>{o.error(a instanceof Error?a.message:n("common.error"))}}),R=j({mutationFn:async()=>{const a=await fetch(`/api/settings/telegram/bots/${s.id}`,{method:"DELETE"});if(!a.ok)throw new Error(await h(a,n("telegram.deleteFailed")))},onSuccess:async()=>{await r.invalidateQueries({queryKey:["telegram-bots"]}),o.success(n("common.success"))},onError:a=>{o.error(a instanceof Error?a.message:n("common.error"))}}),q=j({mutationFn:async a=>{const l=await fetch(`/api/settings/telegram/bots/${s.id}/chats/${encodeURIComponent(a)}/approve`,{method:"POST"});if(!l.ok)throw new Error(await h(l,n("telegram.approveFailed")))},onSuccess:async()=>{await Promise.all([r.invalidateQueries({queryKey:["telegram-bots"]}),r.invalidateQueries({queryKey:["telegram-bot-chats",s.id]})]),o.success(n("common.success"))},onError:a=>{o.error(a instanceof Error?a.message:n("common.error"))}}),E=j({mutationFn:async a=>{const l=await fetch(`/api/settings/telegram/bots/${s.id}/chats/${encodeURIComponent(a)}`,{method:"DELETE"});if(!l.ok)throw new Error(await h(l,n("telegram.removeFailed")))},onSuccess:async()=>{await Promise.all([r.invalidateQueries({queryKey:["telegram-bots"]}),r.invalidateQueries({queryKey:["telegram-bot-chats",s.id]})]),o.success(n("common.success"))},onError:a=>{o.error(a instanceof Error?a.message:n("common.error"))}}),A=j({mutationFn:async a=>{const l=await fetch(`/api/settings/telegram/bots/${s.id}/chats/${encodeURIComponent(a)}/test`,{method:"POST"});if(!l.ok)throw new Error(await h(l,n("telegram.testMessageFailed")))},onSuccess:()=>{o.success(n("common.success"))},onError:a=>{o.error(a instanceof Error?a.message:n("common.error"))}});return e.jsxs("div",{className:"space-y-4 rounded-md border-0 bg-card p-4","data-testid":`telegram-bot-card-${s.id}`,"data-bot-name":s.name,children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:s.name}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[s.authorizedCount," / ",s.pendingCount]})]}),e.jsx(d,{variant:"ghost","data-testid":`telegram-bot-toggle-${s.id}`,onClick:u,children:n(m?"common.collapse":"common.expand")})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end",children:[e.jsxs("div",{className:"md:col-span-3 space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:`bot-name-${s.id}`,children:n("telegram.botName")}),e.jsx(g,{id:`bot-name-${s.id}`,value:x,onChange:a=>y(a.target.value),className:"min-h-10"})]}),e.jsxs("div",{className:"md:col-span-4 space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium",htmlFor:`bot-token-${s.id}`,children:n("telegram.botToken")}),e.jsx(g,{id:`bot-token-${s.id}`,type:"password",value:b,onChange:a=>w(a.target.value),placeholder:n("telegram.tokenPlaceholder"),className:"min-h-10"})]}),e.jsx("div",{className:"md:col-span-2",children:e.jsxs("div",{className:"flex min-h-10 items-center justify-between gap-3 rounded-lg border border-border bg-background px-3 py-2.5",children:[e.jsx("span",{className:"text-sm font-medium",children:n("common.enabled")}),e.jsx(F,{checked:k,onCheckedChange:a=>C(!!a)})]})}),e.jsx("div",{className:"md:col-span-3",children:e.jsxs("div",{className:"flex min-h-10 items-center justify-between gap-3 rounded-lg border border-border bg-background px-3 py-2.5",children:[e.jsx("span",{className:"text-sm font-medium",children:n("telegram.allowAuthRequests")}),e.jsx(F,{checked:S,onCheckedChange:a=>p(!!a)})]})})]}),e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end",children:[e.jsxs(d,{variant:"destructive","data-testid":`telegram-bot-delete-${s.id}`,onClick:()=>R.mutate(),className:"w-full sm:w-auto",children:[e.jsx(je,{className:"h-4 w-4"}),n("telegram.deleteBot")]}),e.jsxs(d,{variant:"default","data-testid":`telegram-bot-save-${s.id}`,onClick:()=>P.mutate(),className:"w-full sm:w-auto",children:[e.jsx(L,{className:"h-4 w-4"}),n("common.save")]})]}),m&&e.jsxs("div",{className:"grid grid-cols-1 gap-4 border-t border-border pt-4 lg:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("h3",{className:"text-sm font-semibold flex items-center gap-1",children:[e.jsx(he,{className:"h-4 w-4"}),n("telegram.pendingChats")]}),f.pending.length===0&&e.jsx("div",{className:"text-xs text-muted-foreground",children:"-"}),f.pending.map(a=>e.jsx(ue,{chat:a,pending:!0,onApprove:()=>q.mutate(a.chatId),onDelete:()=>E.mutate(a.chatId)},`${a.botId}-${a.chatId}`))]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("h3",{className:"text-sm font-semibold flex items-center gap-1",children:[e.jsx(he,{className:"h-4 w-4"}),n("telegram.chats")]}),f.authorized.length===0&&e.jsx("div",{className:"text-xs text-muted-foreground",children:"-"}),f.authorized.map(a=>e.jsx(ue,{chat:a,pending:!1,onTest:()=>A.mutate(a.chatId),onDelete:()=>E.mutate(a.chatId)},`${a.botId}-${a.chatId}`))]}),N.isLoading&&e.jsx("div",{className:"lg:col-span-2 text-xs text-muted-foreground",children:n("common.loading")})]})]})}function ue({chat:s,pending:m,onApprove:u,onDelete:n,onTest:r}){const{t:x}=B(),y=xe(b=>{var w;return((w=b.settings)==null?void 0:w.language)??"en_US"});return e.jsxs("div",{className:"space-y-2 rounded border-0 bg-background p-3",children:[e.jsx("div",{className:"text-sm font-medium truncate",title:s.displayName,children:s.displayName}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[x("telegram.chatId"),":",s.chatId]}),e.jsx("div",{className:"text-xs text-muted-foreground",children:new Date(s.appliedAt).toLocaleString(pe(y))}),e.jsx("div",{className:"flex items-center justify-end gap-2 pt-1",children:m?e.jsxs(e.Fragment,{children:[e.jsx(d,{variant:"outline",size:"sm",onClick:n,children:x("telegram.reject")}),e.jsx(d,{variant:"default",size:"sm",onClick:u,children:x("telegram.authorize")})]}):e.jsxs(e.Fragment,{children:[e.jsxs(d,{variant:"secondary",size:"sm",onClick:r,children:[e.jsx(Ie,{className:"h-3.5 w-3.5"}),x("telegram.sendTestMessage")]}),e.jsx(d,{variant:"destructive",size:"sm",onClick:n,children:x("common.delete")})]})})]})}function Je(){const{t:s}=B();return e.jsx(e.Fragment,{children:s("sidebar.settings")})}function Ve(){const{t:s}=B(),[m,u]=i.useState(!1),n=j({mutationFn:async()=>{const r=await fetch("/api/settings/restart",{method:"POST"});if(!r.ok)throw new Error(await h(r,s("settings.restartFailed")))},onSuccess:()=>{o.success(s("settings.restartScheduled"))},onError:r=>{o.error(r instanceof Error?r.message:s("common.error"))}});return e.jsxs(e.Fragment,{children:[e.jsx(d,{variant:"ghost",size:"icon-sm",onClick:()=>u(!0),disabled:n.isPending,"aria-label":s("settings.restartGateway"),title:s("settings.restartGateway"),className:"text-destructive hover:text-destructive hover:bg-destructive/10",children:e.jsx(ze,{className:"h-4 w-4"})}),e.jsx(Fe,{open:m,onOpenChange:u,children:e.jsxs(Be,{children:[e.jsxs(Pe,{children:[e.jsx(Re,{children:s("settings.restartGateway")}),e.jsx(qe,{children:s("settings.restartConfirm")})]}),e.jsxs(Ae,{children:[e.jsx(Me,{onClick:()=>u(!1),children:s("common.cancel")}),e.jsx($e,{variant:"destructive",onClick:()=>{n.mutate(),u(!1)},children:s("common.confirm")})]})]})})]})}export{Ve as PageActions,Je as PageTitle,We as default};
|
|
17
|
+
//# sourceMappingURL=SettingsPage-CNlEDOxd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsPage-CNlEDOxd.js","sources":["../../../../node_modules/.bun/lucide-react@0.564.0+b1ab299f0a400331/node_modules/lucide-react/dist/esm/icons/rotate-ccw.js","../../../../node_modules/.bun/lucide-react@0.564.0+b1ab299f0a400331/node_modules/lucide-react/dist/esm/icons/save.js","../../../../node_modules/.bun/lucide-react@0.564.0+b1ab299f0a400331/node_modules/lucide-react/dist/esm/icons/shield.js","../../src/pages/SettingsPage.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.564.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"1357e3\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }]\n];\nconst RotateCcw = createLucideIcon(\"rotate-ccw\", __iconNode);\n\nexport { __iconNode, RotateCcw as default };\n//# sourceMappingURL=rotate-ccw.js.map\n","/**\n * @license lucide-react v0.564.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n];\nconst Save = createLucideIcon(\"save\", __iconNode);\n\nexport { __iconNode, Save as default };\n//# sourceMappingURL=save.js.map\n","/**\n * @license lucide-react v0.564.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n];\nconst Shield = createLucideIcon(\"shield\", __iconNode);\n\nexport { __iconNode, Shield as default };\n//# sourceMappingURL=shield.js.map\n","import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport type {\n LocaleCode,\n SiteSettings,\n TelegramBotChat,\n TelegramBotWithStats,\n UpdateSiteSettingsRequest,\n WebhookEndpoint,\n} from '@tmex/shared';\nimport { I18N_MANIFEST, toBCP47 as toBCP47Locale } from '@tmex/shared';\nimport { Loader2, RotateCcw, Save, Send, Shield, Trash2 } from 'lucide-react';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport i18n from '../i18n';\nimport { toast } from 'sonner';\n\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n} from '@/components/ui/alert-dialog';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';\nimport { Input } from '@/components/ui/input';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select';\nimport { Switch } from '@/components/ui/switch';\nimport { useSiteStore } from '../stores/site';\nimport { useUIStore } from '../stores/ui';\n\ninterface TelegramBotsResponse {\n bots: TelegramBotWithStats[];\n}\n\ninterface TelegramChatsResponse {\n chats: TelegramBotChat[];\n}\n\ninterface SiteSettingsResponse {\n settings: SiteSettings;\n}\n\ninterface WebhooksResponse {\n webhooks: WebhookEndpoint[];\n}\n\nasync function parseApiError(res: Response, fallback: string): Promise<string> {\n try {\n const payload = (await res.json()) as { error?: string };\n return payload.error ?? fallback;\n } catch {\n return fallback;\n }\n}\n\nexport default function SettingsPage() {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const { refreshSettings } = useSiteStore();\n\n const [activeTab, setActiveTab] = useState<'site' | 'notifications' | 'telegram' | 'webhooks'>(\n 'site'\n );\n\n const theme = useUIStore((state) => state.theme);\n const setTheme = useUIStore((state) => state.setTheme);\n const isDark = theme === 'dark';\n\n // Site settings state\n const [siteName, setSiteName] = useState('tmex');\n const [siteUrl, setSiteUrl] = useState(window.location.origin);\n const [language, setLanguage] = useState<LocaleCode>('en_US');\n\n // Notifications state\n const [bellThrottleSeconds, setBellThrottleSeconds] = useState(6);\n const [enableBrowserBellToast, setEnableBrowserBellToast] = useState(true);\n const [enableTelegramBellPush, setEnableTelegramBellPush] = useState(true);\n const [sshReconnectMaxRetries, setSshReconnectMaxRetries] = useState(2);\n const [sshReconnectDelaySeconds, setSshReconnectDelaySeconds] = useState(10);\n const [showRefreshNotice, setShowRefreshNotice] = useState(false);\n\n // Telegram state\n const [newBotName, setNewBotName] = useState('');\n const [newBotToken, setNewBotToken] = useState('');\n const [expandedBotId, setExpandedBotId] = useState<string | null>(null);\n\n // Webhook state\n const [newWebhookUrl, setNewWebhookUrl] = useState('');\n const [newWebhookSecret, setNewWebhookSecret] = useState('');\n\n const handleThemeChange = (checked: boolean) => {\n const nextTheme = checked ? 'dark' : 'light';\n setTheme(nextTheme);\n document.documentElement.classList.toggle('dark', nextTheme === 'dark');\n };\n\n const settingsQuery = useQuery({\n queryKey: ['site-settings'],\n queryFn: async () => {\n const res = await fetch('/api/settings/site');\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('settings.loadFailed')));\n }\n return (await res.json()) as SiteSettingsResponse;\n },\n });\n\n const botsQuery = useQuery({\n queryKey: ['telegram-bots'],\n queryFn: async () => {\n const res = await fetch('/api/settings/telegram/bots');\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.loadBotsFailed')));\n }\n return (await res.json()) as TelegramBotsResponse;\n },\n });\n\n useEffect(() => {\n const settings = settingsQuery.data?.settings;\n if (!settings) {\n return;\n }\n\n setSiteName(settings.siteName);\n setSiteUrl(settings.siteUrl);\n setLanguage(settings.language ?? 'en_US');\n setBellThrottleSeconds(settings.bellThrottleSeconds);\n setEnableBrowserBellToast(settings.enableBrowserBellToast ?? true);\n setEnableTelegramBellPush(settings.enableTelegramBellPush ?? true);\n setSshReconnectMaxRetries(settings.sshReconnectMaxRetries);\n setSshReconnectDelaySeconds(settings.sshReconnectDelaySeconds);\n }, [settingsQuery.data?.settings]);\n\n const saveSiteMutation = useMutation({\n mutationFn: async () => {\n const payload: UpdateSiteSettingsRequest = {\n siteName,\n siteUrl,\n language,\n bellThrottleSeconds,\n enableBrowserBellToast,\n enableTelegramBellPush,\n sshReconnectMaxRetries,\n sshReconnectDelaySeconds,\n };\n\n const res = await fetch('/api/settings/site', {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('settings.saveFailed')));\n }\n },\n onSuccess: async () => {\n await Promise.all([\n queryClient.invalidateQueries({ queryKey: ['site-settings'] }),\n refreshSettings(),\n ]);\n toast.success(t('settings.settingsSaved'));\n if (settingsQuery.data?.settings?.language !== language) {\n void i18n.changeLanguage(language);\n setShowRefreshNotice(true);\n }\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const createBotMutation = useMutation({\n mutationFn: async () => {\n const res = await fetch('/api/settings/telegram/bots', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n name: newBotName,\n token: newBotToken,\n enabled: true,\n allowAuthRequests: true,\n }),\n });\n\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.createFailed')));\n }\n },\n onSuccess: async () => {\n setNewBotName('');\n setNewBotToken('');\n await queryClient.invalidateQueries({ queryKey: ['telegram-bots'] });\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const bots = botsQuery.data?.bots ?? [];\n\n const webhooksQuery = useQuery({\n queryKey: ['webhooks'],\n queryFn: async () => {\n const res = await fetch('/api/webhooks');\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('webhook.loadFailed')));\n }\n return (await res.json()) as WebhooksResponse;\n },\n });\n\n const createWebhookMutation = useMutation({\n mutationFn: async () => {\n const res = await fetch('/api/webhooks', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n url: newWebhookUrl,\n secret: newWebhookSecret,\n }),\n });\n\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('webhook.createFailed')));\n }\n },\n onSuccess: async () => {\n setNewWebhookUrl('');\n setNewWebhookSecret('');\n await queryClient.invalidateQueries({ queryKey: ['webhooks'] });\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const deleteWebhookMutation = useMutation({\n mutationFn: async (id: string) => {\n const res = await fetch(`/api/webhooks/${id}`, { method: 'DELETE' });\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('webhook.deleteFailed')));\n }\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: ['webhooks'] });\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const webhooks = webhooksQuery.data?.webhooks ?? [];\n\n return (\n <div\n className=\"mx-auto flex w-full max-w-6xl flex-col gap-4 p-3 pb-[calc(2rem+env(safe-area-inset-bottom))] sm:gap-6 sm:p-5\"\n data-testid=\"settings-page\"\n >\n <div className=\"flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant={activeTab === 'site' ? 'default' : 'outline'}\n data-testid=\"settings-tab-site\"\n onClick={() => setActiveTab('site')}\n >\n {t('settings.siteSettings')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant={activeTab === 'notifications' ? 'default' : 'outline'}\n data-testid=\"settings-tab-notifications\"\n onClick={() => setActiveTab('notifications')}\n >\n {t('settings.notificationsTab')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant={activeTab === 'telegram' ? 'default' : 'outline'}\n data-testid=\"settings-tab-telegram\"\n onClick={() => setActiveTab('telegram')}\n >\n {t('telegram.title')}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant={activeTab === 'webhooks' ? 'default' : 'outline'}\n data-testid=\"settings-tab-webhooks\"\n onClick={() => setActiveTab('webhooks')}\n >\n {t('webhook.title')}\n </Button>\n </div>\n\n {activeTab === 'site' && (\n <Card className=\"border-0 ring-0\">\n <CardHeader>\n <CardTitle>{t('settings.siteSettings')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"site-name-input\">\n {t('settings.siteName')}\n </label>\n <Input\n id=\"site-name-input\"\n value={siteName}\n onChange={(event) => setSiteName(event.target.value)}\n placeholder={t('settings.siteNamePlaceholder')}\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"site-url-input\">\n {t('settings.siteUrl')}\n </label>\n <Input\n id=\"site-url-input\"\n value={siteUrl}\n onChange={(event) => setSiteUrl(event.target.value)}\n placeholder={t('settings.siteUrlPlaceholder')}\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"language-select\">\n {t('settings.language')}\n </label>\n <Select\n value={language}\n onValueChange={(nextValue) => {\n if (!nextValue) return;\n setLanguage(nextValue as LocaleCode);\n }}\n >\n <SelectTrigger\n id=\"language-select\"\n data-testid=\"settings-language-select\"\n className=\"w-full min-h-10\"\n >\n <SelectValue placeholder={t('settings.language')}>\n {I18N_MANIFEST.locales.find((l) => l.code === language)?.nativeName ?? language}\n </SelectValue>\n </SelectTrigger>\n <SelectContent className=\"max-h-[var(--tmex-viewport-height)]\">\n {I18N_MANIFEST.locales.map((locale) => (\n <SelectItem key={locale.code} value={locale.code}>\n {locale.nativeName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {showRefreshNotice && (\n <p className=\"mt-1 text-xs text-primary\" data-testid=\"settings-refresh-notice\">\n {t('settings.refreshToApply')}\n </p>\n )}\n </div>\n\n <div className=\"space-y-3\">\n <div className=\"flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5\">\n <div className=\"min-w-0 pr-2\">\n <div className=\"text-sm font-medium\">{t('settings.theme')}</div>\n </div>\n <Switch\n checked={isDark}\n onCheckedChange={(checked) => handleThemeChange(Boolean(checked))}\n data-testid=\"settings-theme-toggle\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n )}\n\n {activeTab === 'notifications' && (\n <Card className=\"border-0 ring-0\">\n <CardHeader>\n <CardTitle>{t('settings.notificationsTab')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n <div className=\"space-y-3\">\n <div className=\"flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5\">\n <div className=\"min-w-0 pr-2\">\n <div className=\"text-sm font-medium\">{t('settings.enableBrowserBellToast')}</div>\n </div>\n <Switch\n checked={enableBrowserBellToast}\n onCheckedChange={(checked) => setEnableBrowserBellToast(Boolean(checked))}\n data-testid=\"settings-enable-browser-bell-toast\"\n />\n </div>\n\n <div className=\"flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5\">\n <div className=\"min-w-0 pr-2\">\n <div className=\"text-sm font-medium\">{t('settings.enableTelegramBellPush')}</div>\n </div>\n <Switch\n checked={enableTelegramBellPush}\n onCheckedChange={(checked) => setEnableTelegramBellPush(Boolean(checked))}\n data-testid=\"settings-enable-telegram-bell-push\"\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"bell-throttle-input\">\n {t('settings.bellThrottle')}\n </label>\n <Input\n id=\"bell-throttle-input\"\n type=\"number\"\n value={bellThrottleSeconds}\n min={0}\n max={300}\n onChange={(event) => setBellThrottleSeconds(Number(event.target.value))}\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"ssh-reconnect-retries-input\">\n {t('settings.sshReconnectMaxRetries')}\n </label>\n <Input\n id=\"ssh-reconnect-retries-input\"\n type=\"number\"\n value={sshReconnectMaxRetries}\n min={0}\n max={20}\n onChange={(event) => setSshReconnectMaxRetries(Number(event.target.value))}\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"ssh-reconnect-delay-input\">\n {t('settings.sshReconnectDelay')}\n </label>\n <Input\n id=\"ssh-reconnect-delay-input\"\n type=\"number\"\n value={sshReconnectDelaySeconds}\n min={1}\n max={300}\n onChange={(event) => setSshReconnectDelaySeconds(Number(event.target.value))}\n className=\"min-h-10\"\n />\n </div>\n </div>\n </CardContent>\n </Card>\n )}\n\n {activeTab === 'telegram' && (\n <Card className=\"border-0 ring-0\">\n <CardHeader>\n <CardTitle>{t('telegram.title')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n <div className=\"space-y-4\">\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end\">\n <div className=\"md:col-span-4 space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"new-bot-name\">\n {t('telegram.botName')}\n </label>\n <Input\n id=\"new-bot-name\"\n value={newBotName}\n onChange={(event) => setNewBotName(event.target.value)}\n placeholder={t('telegram.botNamePlaceholder')}\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"md:col-span-6 space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"new-bot-token\">\n {t('telegram.botToken')}\n </label>\n <Input\n id=\"new-bot-token\"\n type=\"password\"\n value={newBotToken}\n onChange={(event) => setNewBotToken(event.target.value)}\n placeholder={t('telegram.botTokenPlaceholder')}\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"md:col-span-2\">\n <Button\n variant=\"default\"\n className=\"w-full md:w-auto\"\n data-testid=\"telegram-add-bot\"\n onClick={() => createBotMutation.mutate()}\n disabled={\n createBotMutation.isPending || !newBotName.trim() || !newBotToken.trim()\n }\n >\n {createBotMutation.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n {t('telegram.addBot')}\n </Button>\n </div>\n </div>\n </div>\n\n <div className=\"space-y-3\">\n {botsQuery.isLoading && (\n <div className=\"text-sm text-muted-foreground\">{t('common.loading')}</div>\n )}\n\n {!botsQuery.isLoading && bots.length === 0 && (\n <div className=\"text-sm text-muted-foreground\">{t('telegram.addBot')}</div>\n )}\n\n {bots.map((bot) => (\n <BotCard\n key={bot.id}\n bot={bot}\n expanded={expandedBotId === bot.id}\n onToggleExpand={() => {\n setExpandedBotId((prev) => (prev === bot.id ? null : bot.id));\n }}\n />\n ))}\n </div>\n </CardContent>\n </Card>\n )}\n\n {activeTab === 'webhooks' && (\n <Card className=\"border-0 ring-0\">\n <CardHeader>\n <CardTitle>{t('webhook.title')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-6\">\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end\">\n <div className=\"md:col-span-6 space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"webhook-url-input\">\n {t('webhook.url')}\n </label>\n <Input\n id=\"webhook-url-input\"\n data-testid=\"webhook-url-input\"\n value={newWebhookUrl}\n onChange={(event) => setNewWebhookUrl(event.target.value)}\n placeholder=\"https://example.com/webhook\"\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"md:col-span-4 space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor=\"webhook-secret-input\">\n {t('webhook.secret')}\n </label>\n <Input\n id=\"webhook-secret-input\"\n data-testid=\"webhook-secret-input\"\n value={newWebhookSecret}\n onChange={(event) => setNewWebhookSecret(event.target.value)}\n placeholder={t('webhook.secretPlaceholder')}\n className=\"min-h-10\"\n />\n </div>\n\n <div className=\"md:col-span-2\">\n <Button\n variant=\"default\"\n className=\"w-full md:w-auto\"\n data-testid=\"webhook-add\"\n onClick={() => createWebhookMutation.mutate()}\n disabled={\n createWebhookMutation.isPending ||\n !newWebhookUrl.trim() ||\n !newWebhookSecret.trim()\n }\n >\n {createWebhookMutation.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n {t('webhook.add')}\n </Button>\n </div>\n </div>\n\n <div className=\"space-y-2\">\n {webhooksQuery.isLoading && (\n <div className=\"text-sm text-muted-foreground\">{t('common.loading')}</div>\n )}\n\n {!webhooksQuery.isLoading && webhooks.length === 0 && (\n <div className=\"text-sm text-muted-foreground\">{t('webhook.empty')}</div>\n )}\n\n {webhooks.map((webhook) => (\n <div\n key={webhook.id}\n data-testid=\"webhook-item\"\n data-webhook-url={webhook.url}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-border bg-card px-4 py-2.5\"\n >\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-medium\">{webhook.url}</div>\n <div className=\"text-xs text-muted-foreground\">\n {new Date(webhook.createdAt).toLocaleString(toBCP47Locale(language))}\n </div>\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n data-testid=\"webhook-delete\"\n onClick={() => deleteWebhookMutation.mutate(webhook.id)}\n disabled={deleteWebhookMutation.isPending}\n aria-label={t('common.delete')}\n title={t('common.delete')}\n >\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n </div>\n </CardContent>\n </Card>\n )}\n\n {(activeTab === 'site' || activeTab === 'notifications') && (\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end\">\n <Button\n variant=\"default\"\n data-testid=\"settings-save\"\n onClick={() => saveSiteMutation.mutate()}\n disabled={saveSiteMutation.isPending}\n className=\"w-full sm:w-auto\"\n >\n <Save className=\"h-4 w-4\" />\n {t('common.save')}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\ninterface BotCardProps {\n bot: TelegramBotWithStats;\n expanded: boolean;\n onToggleExpand: () => void;\n}\n\nfunction BotCard({ bot, expanded, onToggleExpand }: BotCardProps) {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n\n const [name, setName] = useState(bot.name);\n const [token, setToken] = useState('');\n const [enabled, setEnabled] = useState(bot.enabled);\n const [allowAuthRequests, setAllowAuthRequests] = useState(bot.allowAuthRequests);\n\n useEffect(() => {\n setName(bot.name);\n setEnabled(bot.enabled);\n setAllowAuthRequests(bot.allowAuthRequests);\n }, [bot.allowAuthRequests, bot.enabled, bot.name]);\n\n const chatsQuery = useQuery({\n queryKey: ['telegram-bot-chats', bot.id],\n enabled: expanded,\n queryFn: async () => {\n const res = await fetch(`/api/settings/telegram/bots/${bot.id}/chats`);\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.loadChatsFailed')));\n }\n return (await res.json()) as TelegramChatsResponse;\n },\n });\n\n const groupedChats = useMemo(() => {\n const chats = chatsQuery.data?.chats ?? [];\n return {\n pending: chats.filter((chat) => chat.status === 'pending'),\n authorized: chats.filter((chat) => chat.status === 'authorized'),\n };\n }, [chatsQuery.data?.chats]);\n\n const patchBotMutation = useMutation({\n mutationFn: async () => {\n const payload: Record<string, unknown> = {\n name,\n enabled,\n allowAuthRequests,\n };\n if (token.trim()) {\n payload.token = token.trim();\n }\n\n const res = await fetch(`/api/settings/telegram/bots/${bot.id}`, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.updateFailed')));\n }\n },\n onSuccess: async () => {\n setToken('');\n await queryClient.invalidateQueries({ queryKey: ['telegram-bots'] });\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const deleteBotMutation = useMutation({\n mutationFn: async () => {\n const res = await fetch(`/api/settings/telegram/bots/${bot.id}`, {\n method: 'DELETE',\n });\n\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.deleteFailed')));\n }\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: ['telegram-bots'] });\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const approveMutation = useMutation({\n mutationFn: async (chatId: string) => {\n const res = await fetch(\n `/api/settings/telegram/bots/${bot.id}/chats/${encodeURIComponent(chatId)}/approve`,\n {\n method: 'POST',\n }\n );\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.approveFailed')));\n }\n },\n onSuccess: async () => {\n await Promise.all([\n queryClient.invalidateQueries({ queryKey: ['telegram-bots'] }),\n queryClient.invalidateQueries({ queryKey: ['telegram-bot-chats', bot.id] }),\n ]);\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const removeChatMutation = useMutation({\n mutationFn: async (chatId: string) => {\n const res = await fetch(\n `/api/settings/telegram/bots/${bot.id}/chats/${encodeURIComponent(chatId)}`,\n {\n method: 'DELETE',\n }\n );\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.removeFailed')));\n }\n },\n onSuccess: async () => {\n await Promise.all([\n queryClient.invalidateQueries({ queryKey: ['telegram-bots'] }),\n queryClient.invalidateQueries({ queryKey: ['telegram-bot-chats', bot.id] }),\n ]);\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n const testChatMutation = useMutation({\n mutationFn: async (chatId: string) => {\n const res = await fetch(\n `/api/settings/telegram/bots/${bot.id}/chats/${encodeURIComponent(chatId)}/test`,\n {\n method: 'POST',\n }\n );\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('telegram.testMessageFailed')));\n }\n },\n onSuccess: () => {\n toast.success(t('common.success'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n return (\n <div\n className=\"space-y-4 rounded-md border-0 bg-card p-4\"\n data-testid={`telegram-bot-card-${bot.id}`}\n data-bot-name={bot.name}\n >\n <div className=\"flex items-center justify-between gap-3\">\n <div>\n <div className=\"font-medium\">{bot.name}</div>\n <div className=\"text-xs text-muted-foreground\">\n {bot.authorizedCount} / {bot.pendingCount}\n </div>\n </div>\n <Button\n variant=\"ghost\"\n data-testid={`telegram-bot-toggle-${bot.id}`}\n onClick={onToggleExpand}\n >\n {expanded ? t('common.collapse') : t('common.expand')}\n </Button>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end\">\n <div className=\"md:col-span-3 space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor={`bot-name-${bot.id}`}>\n {t('telegram.botName')}\n </label>\n <Input\n id={`bot-name-${bot.id}`}\n value={name}\n onChange={(event) => setName(event.target.value)}\n className=\"min-h-10\"\n />\n </div>\n <div className=\"md:col-span-4 space-y-2\">\n <label className=\"block text-sm font-medium\" htmlFor={`bot-token-${bot.id}`}>\n {t('telegram.botToken')}\n </label>\n <Input\n id={`bot-token-${bot.id}`}\n type=\"password\"\n value={token}\n onChange={(event) => setToken(event.target.value)}\n placeholder={t('telegram.tokenPlaceholder')}\n className=\"min-h-10\"\n />\n </div>\n <div className=\"md:col-span-2\">\n <div className=\"flex min-h-10 items-center justify-between gap-3 rounded-lg border border-border bg-background px-3 py-2.5\">\n <span className=\"text-sm font-medium\">{t('common.enabled')}</span>\n <Switch checked={enabled} onCheckedChange={(checked) => setEnabled(Boolean(checked))} />\n </div>\n </div>\n <div className=\"md:col-span-3\">\n <div className=\"flex min-h-10 items-center justify-between gap-3 rounded-lg border border-border bg-background px-3 py-2.5\">\n <span className=\"text-sm font-medium\">{t('telegram.allowAuthRequests')}</span>\n <Switch\n checked={allowAuthRequests}\n onCheckedChange={(checked) => setAllowAuthRequests(Boolean(checked))}\n />\n </div>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end\">\n <Button\n variant=\"destructive\"\n data-testid={`telegram-bot-delete-${bot.id}`}\n onClick={() => deleteBotMutation.mutate()}\n className=\"w-full sm:w-auto\"\n >\n <Trash2 className=\"h-4 w-4\" />\n {t('telegram.deleteBot')}\n </Button>\n <Button\n variant=\"default\"\n data-testid={`telegram-bot-save-${bot.id}`}\n onClick={() => patchBotMutation.mutate()}\n className=\"w-full sm:w-auto\"\n >\n <Save className=\"h-4 w-4\" />\n {t('common.save')}\n </Button>\n </div>\n\n {expanded && (\n <div className=\"grid grid-cols-1 gap-4 border-t border-border pt-4 lg:grid-cols-2\">\n <div className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold flex items-center gap-1\">\n <Shield className=\"h-4 w-4\" />\n {t('telegram.pendingChats')}\n </h3>\n {groupedChats.pending.length === 0 && <div className=\"text-xs text-muted-foreground\">-</div>}\n {groupedChats.pending.map((chat) => (\n <ChatRow\n key={`${chat.botId}-${chat.chatId}`}\n chat={chat}\n pending\n onApprove={() => approveMutation.mutate(chat.chatId)}\n onDelete={() => removeChatMutation.mutate(chat.chatId)}\n />\n ))}\n </div>\n\n <div className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold flex items-center gap-1\">\n <Shield className=\"h-4 w-4\" />\n {t('telegram.chats')}\n </h3>\n {groupedChats.authorized.length === 0 && <div className=\"text-xs text-muted-foreground\">-</div>}\n {groupedChats.authorized.map((chat) => (\n <ChatRow\n key={`${chat.botId}-${chat.chatId}`}\n chat={chat}\n pending={false}\n onTest={() => testChatMutation.mutate(chat.chatId)}\n onDelete={() => removeChatMutation.mutate(chat.chatId)}\n />\n ))}\n </div>\n\n {chatsQuery.isLoading && (\n <div className=\"lg:col-span-2 text-xs text-muted-foreground\">\n {t('common.loading')}\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n\ninterface ChatRowProps {\n chat: TelegramBotChat;\n pending: boolean;\n onApprove?: () => void;\n onDelete: () => void;\n onTest?: () => void;\n}\n\nfunction ChatRow({ chat, pending, onApprove, onDelete, onTest }: ChatRowProps) {\n const { t } = useTranslation();\n const language = useSiteStore((state) => state.settings?.language ?? 'en_US');\n return (\n <div className=\"space-y-2 rounded border-0 bg-background p-3\">\n <div className=\"text-sm font-medium truncate\" title={chat.displayName}>\n {chat.displayName}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {t('telegram.chatId')}:{chat.chatId}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {new Date(chat.appliedAt).toLocaleString(toBCP47Locale(language))}\n </div>\n\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n {pending ? (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={onDelete}>\n {t('telegram.reject')}\n </Button>\n <Button variant=\"default\" size=\"sm\" onClick={onApprove}>\n {t('telegram.authorize')}\n </Button>\n </>\n ) : (\n <>\n <Button variant=\"secondary\" size=\"sm\" onClick={onTest}>\n <Send className=\"h-3.5 w-3.5\" />\n {t('telegram.sendTestMessage')}\n </Button>\n <Button variant=\"destructive\" size=\"sm\" onClick={onDelete}>\n {t('common.delete')}\n </Button>\n </>\n )}\n </div>\n </div>\n );\n}\n\n// Page title component\nexport function PageTitle() {\n const { t } = useTranslation();\n return <>{t('sidebar.settings')}</>;\n}\n\n// Page actions component\nexport function PageActions() {\n const { t } = useTranslation();\n const [showRestartConfirm, setShowRestartConfirm] = useState(false);\n\n const restartMutation = useMutation({\n mutationFn: async () => {\n const res = await fetch('/api/settings/restart', { method: 'POST' });\n if (!res.ok) {\n throw new Error(await parseApiError(res, t('settings.restartFailed')));\n }\n },\n onSuccess: () => {\n toast.success(t('settings.restartScheduled'));\n },\n onError: (err) => {\n toast.error(err instanceof Error ? err.message : t('common.error'));\n },\n });\n\n return (\n <>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setShowRestartConfirm(true)}\n disabled={restartMutation.isPending}\n aria-label={t('settings.restartGateway')}\n title={t('settings.restartGateway')}\n className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n >\n <RotateCcw className=\"h-4 w-4\" />\n </Button>\n\n <AlertDialog open={showRestartConfirm} onOpenChange={setShowRestartConfirm}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>{t('settings.restartGateway')}</AlertDialogTitle>\n <AlertDialogDescription>{t('settings.restartConfirm')}</AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel onClick={() => setShowRestartConfirm(false)}>\n {t('common.cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n variant=\"destructive\"\n onClick={() => {\n restartMutation.mutate();\n setShowRestartConfirm(false);\n }}\n >\n {t('common.confirm')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </>\n );\n}\n"],"names":["__iconNode","RotateCcw","createLucideIcon","Save","Shield","parseApiError","res","fallback","SettingsPage","t","useTranslation","queryClient","useQueryClient","refreshSettings","useSiteStore","activeTab","setActiveTab","useState","theme","useUIStore","state","setTheme","isDark","siteName","setSiteName","siteUrl","setSiteUrl","language","setLanguage","bellThrottleSeconds","setBellThrottleSeconds","enableBrowserBellToast","setEnableBrowserBellToast","enableTelegramBellPush","setEnableTelegramBellPush","sshReconnectMaxRetries","setSshReconnectMaxRetries","sshReconnectDelaySeconds","setSshReconnectDelaySeconds","showRefreshNotice","setShowRefreshNotice","newBotName","setNewBotName","newBotToken","setNewBotToken","expandedBotId","setExpandedBotId","newWebhookUrl","setNewWebhookUrl","newWebhookSecret","setNewWebhookSecret","handleThemeChange","checked","nextTheme","settingsQuery","useQuery","botsQuery","useEffect","settings","_a","saveSiteMutation","useMutation","toast","_b","i18n","err","createBotMutation","bots","webhooksQuery","createWebhookMutation","deleteWebhookMutation","id","webhooks","_c","jsxs","jsx","Button","Card","CardHeader","CardTitle","CardContent","Input","event","Select","nextValue","SelectTrigger","SelectValue","_d","I18N_MANIFEST","l","SelectContent","locale","SelectItem","Switch","Loader2","bot","BotCard","prev","webhook","toBCP47Locale","Trash2","expanded","onToggleExpand","name","setName","token","setToken","enabled","setEnabled","allowAuthRequests","setAllowAuthRequests","chatsQuery","groupedChats","useMemo","chats","chat","patchBotMutation","payload","deleteBotMutation","approveMutation","chatId","removeChatMutation","testChatMutation","ChatRow","pending","onApprove","onDelete","onTest","Fragment","Send","PageTitle","PageActions","showRestartConfirm","setShowRestartConfirm","restartMutation","AlertDialog","AlertDialogContent","AlertDialogHeader","AlertDialogTitle","AlertDialogDescription","AlertDialogFooter","AlertDialogCancel","AlertDialogAction"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|