tmex-cli 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/runtime/server.js +736 -186
  2. package/package.json +1 -1
  3. package/resources/fe-dist/assets/DevicePage-CKaPUo7L.js +26 -0
  4. package/resources/fe-dist/assets/DevicePage-CKaPUo7L.js.map +1 -0
  5. package/resources/fe-dist/assets/DevicesPage-FqU-Dxhu.js +17 -0
  6. package/resources/fe-dist/assets/{DevicesPage-CtNzaW_c.js.map → DevicesPage-FqU-Dxhu.js.map} +1 -1
  7. package/resources/fe-dist/assets/SettingsPage-BfkOW0fc.js +17 -0
  8. package/resources/fe-dist/assets/SettingsPage-BfkOW0fc.js.map +1 -0
  9. package/resources/fe-dist/assets/index-EgHfq93I.js +449 -0
  10. package/resources/fe-dist/assets/index-EgHfq93I.js.map +1 -0
  11. package/resources/fe-dist/assets/index-Ytlj3p_q.css +1 -0
  12. package/resources/fe-dist/assets/select-CNlE6MiW.js +17 -0
  13. package/resources/fe-dist/assets/{select-BNsiC9zT.js.map → select-CNlE6MiW.js.map} +1 -1
  14. package/resources/fe-dist/assets/switch-CxkzOIL6.js +12 -0
  15. package/resources/fe-dist/assets/{switch-CIU4AisU.js.map → switch-CxkzOIL6.js.map} +1 -1
  16. package/resources/fe-dist/assets/useValueChanged-CO2U5MoL.js +7 -0
  17. package/resources/fe-dist/assets/{useValueChanged-V23H0VpC.js.map → useValueChanged-CO2U5MoL.js.map} +1 -1
  18. package/resources/fe-dist/index.html +2 -2
  19. package/resources/gateway-drizzle/0002_broad_vengeance.sql +3 -0
  20. package/resources/gateway-drizzle/meta/0000_snapshot.json +17 -6
  21. package/resources/gateway-drizzle/meta/0001_snapshot.json +17 -6
  22. package/resources/gateway-drizzle/meta/0002_snapshot.json +535 -0
  23. package/resources/gateway-drizzle/meta/_journal.json +8 -1
  24. package/resources/fe-dist/assets/DevicePage-iSkEDEpS.js +0 -4570
  25. package/resources/fe-dist/assets/DevicePage-iSkEDEpS.js.map +0 -1
  26. package/resources/fe-dist/assets/DevicesPage-CtNzaW_c.js +0 -2143
  27. package/resources/fe-dist/assets/SettingsPage-D25_d6j9.js +0 -1144
  28. package/resources/fe-dist/assets/SettingsPage-D25_d6j9.js.map +0 -1
  29. package/resources/fe-dist/assets/index-CJaX5rlK.css +0 -4527
  30. package/resources/fe-dist/assets/index-dsVN7rgz.js +0 -200
  31. package/resources/fe-dist/assets/index-dsVN7rgz.js.map +0 -1
  32. package/resources/fe-dist/assets/select-BNsiC9zT.js +0 -2805
  33. package/resources/fe-dist/assets/switch-CIU4AisU.js +0 -234
  34. package/resources/fe-dist/assets/useValueChanged-V23H0VpC.js +0 -351
@@ -1,1144 +0,0 @@
1
- import {
2
- u as B,
3
- c as G,
4
- d as ce,
5
- B as d,
6
- I as de,
7
- j as e,
8
- a as ge,
9
- r as i,
10
- f as o,
11
- t as pe,
12
- i as ve,
13
- b as xe,
14
- e as z,
15
- } from './index-dsVN7rgz.js';
16
- import {
17
- a as $,
18
- d as Ce,
19
- c as D,
20
- f as Ee,
21
- b as I,
22
- C as M,
23
- e as Se,
24
- g as Te,
25
- I as g,
26
- u as j,
27
- S as ke,
28
- } from './select-BNsiC9zT.js';
29
- import { S as F, a as Ie, L as me } from './switch-CIU4AisU.js'; /**
30
- * @license lucide-react v0.564.0 - ISC
31
- *
32
- * This source code is licensed under the ISC license.
33
- * See the LICENSE file in the root directory of this source tree.
34
- */
35
- import {
36
- g as $e,
37
- e as Ae,
38
- a as Be,
39
- A as Fe,
40
- f as Me,
41
- b as Pe,
42
- c as Re,
43
- T as je,
44
- d as qe,
45
- } from './useValueChanged-V23H0VpC.js';
46
- const De = [
47
- ['path', { d: 'M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8', key: '1357e3' }],
48
- ['path', { d: 'M3 3v5h5', key: '1xhq8a' }],
49
- ],
50
- ze = G('rotate-ccw', De); /**
51
- * @license lucide-react v0.564.0 - ISC
52
- *
53
- * This source code is licensed under the ISC license.
54
- * See the LICENSE file in the root directory of this source tree.
55
- */
56
- const Le = [
57
- [
58
- 'path',
59
- {
60
- 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',
61
- key: '1c8476',
62
- },
63
- ],
64
- ['path', { d: 'M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7', key: '1ydtos' }],
65
- ['path', { d: 'M7 3v4a1 1 0 0 0 1 1h7', key: 't51u73' }],
66
- ],
67
- L = G('save', Le); /**
68
- * @license lucide-react v0.564.0 - ISC
69
- *
70
- * This source code is licensed under the ISC license.
71
- * See the LICENSE file in the root directory of this source tree.
72
- */
73
- const Qe = [
74
- [
75
- 'path',
76
- {
77
- 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',
78
- key: 'oel41y',
79
- },
80
- ],
81
- ],
82
- he = G('shield', Qe);
83
- async function h(s, m) {
84
- try {
85
- return (await s.json()).error ?? m;
86
- } catch {
87
- return m;
88
- }
89
- }
90
- function We() {
91
- var ie, oe, re, le;
92
- const { t: s } = B(),
93
- m = ge(),
94
- { refreshSettings: u } = xe(),
95
- [n, r] = i.useState('site'),
96
- x = ce((t) => t.theme),
97
- y = ce((t) => t.setTheme),
98
- b = x === 'dark',
99
- [w, k] = i.useState('tmex'),
100
- [C, S] = i.useState(window.location.origin),
101
- [p, N] = i.useState('en_US'),
102
- [f, P] = i.useState(6),
103
- [R, q] = i.useState(!0),
104
- [E, A] = i.useState(!0),
105
- [T, a] = i.useState(2),
106
- [l, v] = i.useState(10),
107
- [we, be] = i.useState(!1),
108
- [Q, X] = i.useState(''),
109
- [K, Y] = i.useState(''),
110
- [fe, ye] = i.useState(null),
111
- [U, Z] = i.useState(''),
112
- [O, ee] = i.useState(''),
113
- Ne = (t) => {
114
- const c = t ? 'dark' : 'light';
115
- y(c), document.documentElement.classList.toggle('dark', c === 'dark');
116
- },
117
- _ = z({
118
- queryKey: ['site-settings'],
119
- queryFn: async () => {
120
- const t = await fetch('/api/settings/site');
121
- if (!t.ok) throw new Error(await h(t, s('settings.loadFailed')));
122
- return await t.json();
123
- },
124
- }),
125
- H = z({
126
- queryKey: ['telegram-bots'],
127
- queryFn: async () => {
128
- const t = await fetch('/api/settings/telegram/bots');
129
- if (!t.ok) throw new Error(await h(t, s('telegram.loadBotsFailed')));
130
- return await t.json();
131
- },
132
- });
133
- i.useEffect(() => {
134
- var c;
135
- const t = (c = _.data) == null ? void 0 : c.settings;
136
- t &&
137
- (k(t.siteName),
138
- S(t.siteUrl),
139
- N(t.language ?? 'en_US'),
140
- P(t.bellThrottleSeconds),
141
- q(t.enableBrowserBellToast ?? !0),
142
- A(t.enableTelegramBellPush ?? !0),
143
- a(t.sshReconnectMaxRetries),
144
- v(t.sshReconnectDelaySeconds));
145
- }, [(ie = _.data) == null ? void 0 : ie.settings]);
146
- const se = j({
147
- mutationFn: async () => {
148
- const c = await fetch('/api/settings/site', {
149
- method: 'PATCH',
150
- headers: { 'Content-Type': 'application/json' },
151
- body: JSON.stringify({
152
- siteName: w,
153
- siteUrl: C,
154
- language: p,
155
- bellThrottleSeconds: f,
156
- enableBrowserBellToast: R,
157
- enableTelegramBellPush: E,
158
- sshReconnectMaxRetries: T,
159
- sshReconnectDelaySeconds: l,
160
- }),
161
- });
162
- if (!c.ok) throw new Error(await h(c, s('settings.saveFailed')));
163
- },
164
- onSuccess: async () => {
165
- var t, c;
166
- await Promise.all([m.invalidateQueries({ queryKey: ['site-settings'] }), u()]),
167
- o.success(s('settings.settingsSaved')),
168
- ((c = (t = _.data) == null ? void 0 : t.settings) == null ? void 0 : c.language) !== p &&
169
- (ve.changeLanguage(p), be(!0));
170
- },
171
- onError: (t) => {
172
- o.error(t instanceof Error ? t.message : s('common.error'));
173
- },
174
- }),
175
- W = j({
176
- mutationFn: async () => {
177
- const t = await fetch('/api/settings/telegram/bots', {
178
- method: 'POST',
179
- headers: { 'Content-Type': 'application/json' },
180
- body: JSON.stringify({ name: Q, token: K, enabled: !0, allowAuthRequests: !0 }),
181
- });
182
- if (!t.ok) throw new Error(await h(t, s('telegram.createFailed')));
183
- },
184
- onSuccess: async () => {
185
- X(''),
186
- Y(''),
187
- await m.invalidateQueries({ queryKey: ['telegram-bots'] }),
188
- o.success(s('common.success'));
189
- },
190
- onError: (t) => {
191
- o.error(t instanceof Error ? t.message : s('common.error'));
192
- },
193
- }),
194
- te = ((oe = H.data) == null ? void 0 : oe.bots) ?? [],
195
- J = z({
196
- queryKey: ['webhooks'],
197
- queryFn: async () => {
198
- const t = await fetch('/api/webhooks');
199
- if (!t.ok) throw new Error(await h(t, s('webhook.loadFailed')));
200
- return await t.json();
201
- },
202
- }),
203
- V = j({
204
- mutationFn: async () => {
205
- const t = await fetch('/api/webhooks', {
206
- method: 'POST',
207
- headers: { 'Content-Type': 'application/json' },
208
- body: JSON.stringify({ url: U, secret: O }),
209
- });
210
- if (!t.ok) throw new Error(await h(t, s('webhook.createFailed')));
211
- },
212
- onSuccess: async () => {
213
- Z(''),
214
- ee(''),
215
- await m.invalidateQueries({ queryKey: ['webhooks'] }),
216
- o.success(s('common.success'));
217
- },
218
- onError: (t) => {
219
- o.error(t instanceof Error ? t.message : s('common.error'));
220
- },
221
- }),
222
- ae = j({
223
- mutationFn: async (t) => {
224
- const c = await fetch(`/api/webhooks/${t}`, { method: 'DELETE' });
225
- if (!c.ok) throw new Error(await h(c, s('webhook.deleteFailed')));
226
- },
227
- onSuccess: async () => {
228
- await m.invalidateQueries({ queryKey: ['webhooks'] }), o.success(s('common.success'));
229
- },
230
- onError: (t) => {
231
- o.error(t instanceof Error ? t.message : s('common.error'));
232
- },
233
- }),
234
- ne = ((re = J.data) == null ? void 0 : re.webhooks) ?? [];
235
- return e.jsxs('div', {
236
- className:
237
- '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',
238
- 'data-testid': 'settings-page',
239
- children: [
240
- e.jsxs('div', {
241
- className: 'flex flex-wrap gap-2',
242
- children: [
243
- e.jsx(d, {
244
- type: 'button',
245
- size: 'sm',
246
- variant: n === 'site' ? 'default' : 'outline',
247
- 'data-testid': 'settings-tab-site',
248
- onClick: () => r('site'),
249
- children: s('settings.siteSettings'),
250
- }),
251
- e.jsx(d, {
252
- type: 'button',
253
- size: 'sm',
254
- variant: n === 'notifications' ? 'default' : 'outline',
255
- 'data-testid': 'settings-tab-notifications',
256
- onClick: () => r('notifications'),
257
- children: s('settings.notificationsTab'),
258
- }),
259
- e.jsx(d, {
260
- type: 'button',
261
- size: 'sm',
262
- variant: n === 'telegram' ? 'default' : 'outline',
263
- 'data-testid': 'settings-tab-telegram',
264
- onClick: () => r('telegram'),
265
- children: s('telegram.title'),
266
- }),
267
- e.jsx(d, {
268
- type: 'button',
269
- size: 'sm',
270
- variant: n === 'webhooks' ? 'default' : 'outline',
271
- 'data-testid': 'settings-tab-webhooks',
272
- onClick: () => r('webhooks'),
273
- children: s('webhook.title'),
274
- }),
275
- ],
276
- }),
277
- n === 'site' &&
278
- e.jsxs(M, {
279
- className: 'border-0 ring-0',
280
- children: [
281
- e.jsx($, { children: e.jsx(I, { children: s('settings.siteSettings') }) }),
282
- e.jsxs(D, {
283
- className: 'space-y-6',
284
- children: [
285
- e.jsxs('div', {
286
- className: 'space-y-2',
287
- children: [
288
- e.jsx('label', {
289
- className: 'block text-sm font-medium',
290
- htmlFor: 'site-name-input',
291
- children: s('settings.siteName'),
292
- }),
293
- e.jsx(g, {
294
- id: 'site-name-input',
295
- value: w,
296
- onChange: (t) => k(t.target.value),
297
- placeholder: s('settings.siteNamePlaceholder'),
298
- className: 'min-h-10',
299
- }),
300
- ],
301
- }),
302
- e.jsxs('div', {
303
- className: 'space-y-2',
304
- children: [
305
- e.jsx('label', {
306
- className: 'block text-sm font-medium',
307
- htmlFor: 'site-url-input',
308
- children: s('settings.siteUrl'),
309
- }),
310
- e.jsx(g, {
311
- id: 'site-url-input',
312
- value: C,
313
- onChange: (t) => S(t.target.value),
314
- placeholder: s('settings.siteUrlPlaceholder'),
315
- className: 'min-h-10',
316
- }),
317
- ],
318
- }),
319
- e.jsxs('div', {
320
- className: 'space-y-2',
321
- children: [
322
- e.jsx('label', {
323
- className: 'block text-sm font-medium',
324
- htmlFor: 'language-select',
325
- children: s('settings.language'),
326
- }),
327
- e.jsxs(ke, {
328
- value: p,
329
- onValueChange: (t) => {
330
- t && N(t);
331
- },
332
- children: [
333
- e.jsx(Ce, {
334
- id: 'language-select',
335
- 'data-testid': 'settings-language-select',
336
- className: 'w-full min-h-10',
337
- children: e.jsx(Se, {
338
- placeholder: s('settings.language'),
339
- children:
340
- ((le = de.locales.find((t) => t.code === p)) == null
341
- ? void 0
342
- : le.nativeName) ?? p,
343
- }),
344
- }),
345
- e.jsx(Ee, {
346
- className: 'max-h-[var(--tmex-viewport-height)]',
347
- children: de.locales.map((t) =>
348
- e.jsx(Te, { value: t.code, children: t.nativeName }, t.code)
349
- ),
350
- }),
351
- ],
352
- }),
353
- we &&
354
- e.jsx('p', {
355
- className: 'mt-1 text-xs text-primary',
356
- 'data-testid': 'settings-refresh-notice',
357
- children: s('settings.refreshToApply'),
358
- }),
359
- ],
360
- }),
361
- e.jsx('div', {
362
- className: 'space-y-3',
363
- children: e.jsxs('div', {
364
- className:
365
- 'flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5',
366
- children: [
367
- e.jsx('div', {
368
- className: 'min-w-0 pr-2',
369
- children: e.jsx('div', {
370
- className: 'text-sm font-medium',
371
- children: s('settings.theme'),
372
- }),
373
- }),
374
- e.jsx(F, {
375
- checked: b,
376
- onCheckedChange: (t) => Ne(!!t),
377
- 'data-testid': 'settings-theme-toggle',
378
- }),
379
- ],
380
- }),
381
- }),
382
- ],
383
- }),
384
- ],
385
- }),
386
- n === 'notifications' &&
387
- e.jsxs(M, {
388
- className: 'border-0 ring-0',
389
- children: [
390
- e.jsx($, { children: e.jsx(I, { children: s('settings.notificationsTab') }) }),
391
- e.jsxs(D, {
392
- className: 'space-y-6',
393
- children: [
394
- e.jsxs('div', {
395
- className: 'space-y-3',
396
- children: [
397
- e.jsxs('div', {
398
- className:
399
- 'flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5',
400
- children: [
401
- e.jsx('div', {
402
- className: 'min-w-0 pr-2',
403
- children: e.jsx('div', {
404
- className: 'text-sm font-medium',
405
- children: s('settings.enableBrowserBellToast'),
406
- }),
407
- }),
408
- e.jsx(F, {
409
- checked: R,
410
- onCheckedChange: (t) => q(!!t),
411
- 'data-testid': 'settings-enable-browser-bell-toast',
412
- }),
413
- ],
414
- }),
415
- e.jsxs('div', {
416
- className:
417
- 'flex min-h-10 items-center justify-between gap-4 rounded-lg border border-border bg-card px-4 py-2.5',
418
- children: [
419
- e.jsx('div', {
420
- className: 'min-w-0 pr-2',
421
- children: e.jsx('div', {
422
- className: 'text-sm font-medium',
423
- children: s('settings.enableTelegramBellPush'),
424
- }),
425
- }),
426
- e.jsx(F, {
427
- checked: E,
428
- onCheckedChange: (t) => A(!!t),
429
- 'data-testid': 'settings-enable-telegram-bell-push',
430
- }),
431
- ],
432
- }),
433
- ],
434
- }),
435
- e.jsxs('div', {
436
- className: 'grid grid-cols-1 gap-4 sm:grid-cols-3',
437
- children: [
438
- e.jsxs('div', {
439
- className: 'space-y-2',
440
- children: [
441
- e.jsx('label', {
442
- className: 'block text-sm font-medium',
443
- htmlFor: 'bell-throttle-input',
444
- children: s('settings.bellThrottle'),
445
- }),
446
- e.jsx(g, {
447
- id: 'bell-throttle-input',
448
- type: 'number',
449
- value: f,
450
- min: 0,
451
- max: 300,
452
- onChange: (t) => P(Number(t.target.value)),
453
- className: 'min-h-10',
454
- }),
455
- ],
456
- }),
457
- e.jsxs('div', {
458
- className: 'space-y-2',
459
- children: [
460
- e.jsx('label', {
461
- className: 'block text-sm font-medium',
462
- htmlFor: 'ssh-reconnect-retries-input',
463
- children: s('settings.sshReconnectMaxRetries'),
464
- }),
465
- e.jsx(g, {
466
- id: 'ssh-reconnect-retries-input',
467
- type: 'number',
468
- value: T,
469
- min: 0,
470
- max: 20,
471
- onChange: (t) => a(Number(t.target.value)),
472
- className: 'min-h-10',
473
- }),
474
- ],
475
- }),
476
- e.jsxs('div', {
477
- className: 'space-y-2',
478
- children: [
479
- e.jsx('label', {
480
- className: 'block text-sm font-medium',
481
- htmlFor: 'ssh-reconnect-delay-input',
482
- children: s('settings.sshReconnectDelay'),
483
- }),
484
- e.jsx(g, {
485
- id: 'ssh-reconnect-delay-input',
486
- type: 'number',
487
- value: l,
488
- min: 1,
489
- max: 300,
490
- onChange: (t) => v(Number(t.target.value)),
491
- className: 'min-h-10',
492
- }),
493
- ],
494
- }),
495
- ],
496
- }),
497
- ],
498
- }),
499
- ],
500
- }),
501
- n === 'telegram' &&
502
- e.jsxs(M, {
503
- className: 'border-0 ring-0',
504
- children: [
505
- e.jsx($, { children: e.jsx(I, { children: s('telegram.title') }) }),
506
- e.jsxs(D, {
507
- className: 'space-y-6',
508
- children: [
509
- e.jsx('div', {
510
- className: 'space-y-4',
511
- children: e.jsxs('div', {
512
- className: 'grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end',
513
- children: [
514
- e.jsxs('div', {
515
- className: 'md:col-span-4 space-y-2',
516
- children: [
517
- e.jsx('label', {
518
- className: 'block text-sm font-medium',
519
- htmlFor: 'new-bot-name',
520
- children: s('telegram.botName'),
521
- }),
522
- e.jsx(g, {
523
- id: 'new-bot-name',
524
- value: Q,
525
- onChange: (t) => X(t.target.value),
526
- placeholder: s('telegram.botNamePlaceholder'),
527
- className: 'min-h-10',
528
- }),
529
- ],
530
- }),
531
- e.jsxs('div', {
532
- className: 'md:col-span-6 space-y-2',
533
- children: [
534
- e.jsx('label', {
535
- className: 'block text-sm font-medium',
536
- htmlFor: 'new-bot-token',
537
- children: s('telegram.botToken'),
538
- }),
539
- e.jsx(g, {
540
- id: 'new-bot-token',
541
- type: 'password',
542
- value: K,
543
- onChange: (t) => Y(t.target.value),
544
- placeholder: s('telegram.botTokenPlaceholder'),
545
- className: 'min-h-10',
546
- }),
547
- ],
548
- }),
549
- e.jsx('div', {
550
- className: 'md:col-span-2',
551
- children: e.jsxs(d, {
552
- variant: 'default',
553
- className: 'w-full md:w-auto',
554
- 'data-testid': 'telegram-add-bot',
555
- onClick: () => W.mutate(),
556
- disabled: W.isPending || !Q.trim() || !K.trim(),
557
- children: [
558
- W.isPending
559
- ? e.jsx(me, { className: 'h-4 w-4 animate-spin' })
560
- : e.jsx(L, { className: 'h-4 w-4' }),
561
- s('telegram.addBot'),
562
- ],
563
- }),
564
- }),
565
- ],
566
- }),
567
- }),
568
- e.jsxs('div', {
569
- className: 'space-y-3',
570
- children: [
571
- H.isLoading &&
572
- e.jsx('div', {
573
- className: 'text-sm text-muted-foreground',
574
- children: s('common.loading'),
575
- }),
576
- !H.isLoading &&
577
- te.length === 0 &&
578
- e.jsx('div', {
579
- className: 'text-sm text-muted-foreground',
580
- children: s('telegram.addBot'),
581
- }),
582
- te.map((t) =>
583
- e.jsx(
584
- Ke,
585
- {
586
- bot: t,
587
- expanded: fe === t.id,
588
- onToggleExpand: () => {
589
- ye((c) => (c === t.id ? null : t.id));
590
- },
591
- },
592
- t.id
593
- )
594
- ),
595
- ],
596
- }),
597
- ],
598
- }),
599
- ],
600
- }),
601
- n === 'webhooks' &&
602
- e.jsxs(M, {
603
- className: 'border-0 ring-0',
604
- children: [
605
- e.jsx($, { children: e.jsx(I, { children: s('webhook.title') }) }),
606
- e.jsxs(D, {
607
- className: 'space-y-6',
608
- children: [
609
- e.jsxs('div', {
610
- className: 'grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end',
611
- children: [
612
- e.jsxs('div', {
613
- className: 'md:col-span-6 space-y-2',
614
- children: [
615
- e.jsx('label', {
616
- className: 'block text-sm font-medium',
617
- htmlFor: 'webhook-url-input',
618
- children: s('webhook.url'),
619
- }),
620
- e.jsx(g, {
621
- id: 'webhook-url-input',
622
- 'data-testid': 'webhook-url-input',
623
- value: U,
624
- onChange: (t) => Z(t.target.value),
625
- placeholder: 'https://example.com/webhook',
626
- className: 'min-h-10',
627
- }),
628
- ],
629
- }),
630
- e.jsxs('div', {
631
- className: 'md:col-span-4 space-y-2',
632
- children: [
633
- e.jsx('label', {
634
- className: 'block text-sm font-medium',
635
- htmlFor: 'webhook-secret-input',
636
- children: s('webhook.secret'),
637
- }),
638
- e.jsx(g, {
639
- id: 'webhook-secret-input',
640
- 'data-testid': 'webhook-secret-input',
641
- value: O,
642
- onChange: (t) => ee(t.target.value),
643
- placeholder: s('webhook.secretPlaceholder'),
644
- className: 'min-h-10',
645
- }),
646
- ],
647
- }),
648
- e.jsx('div', {
649
- className: 'md:col-span-2',
650
- children: e.jsxs(d, {
651
- variant: 'default',
652
- className: 'w-full md:w-auto',
653
- 'data-testid': 'webhook-add',
654
- onClick: () => V.mutate(),
655
- disabled: V.isPending || !U.trim() || !O.trim(),
656
- children: [
657
- V.isPending
658
- ? e.jsx(me, { className: 'h-4 w-4 animate-spin' })
659
- : e.jsx(L, { className: 'h-4 w-4' }),
660
- s('webhook.add'),
661
- ],
662
- }),
663
- }),
664
- ],
665
- }),
666
- e.jsxs('div', {
667
- className: 'space-y-2',
668
- children: [
669
- J.isLoading &&
670
- e.jsx('div', {
671
- className: 'text-sm text-muted-foreground',
672
- children: s('common.loading'),
673
- }),
674
- !J.isLoading &&
675
- ne.length === 0 &&
676
- e.jsx('div', {
677
- className: 'text-sm text-muted-foreground',
678
- children: s('webhook.empty'),
679
- }),
680
- ne.map((t) =>
681
- e.jsxs(
682
- 'div',
683
- {
684
- 'data-testid': 'webhook-item',
685
- 'data-webhook-url': t.url,
686
- className:
687
- 'flex items-center justify-between gap-3 rounded-lg border border-border bg-card px-4 py-2.5',
688
- children: [
689
- e.jsxs('div', {
690
- className: 'min-w-0',
691
- children: [
692
- e.jsx('div', {
693
- className: 'truncate text-sm font-medium',
694
- children: t.url,
695
- }),
696
- e.jsx('div', {
697
- className: 'text-xs text-muted-foreground',
698
- children: new Date(t.createdAt).toLocaleString(pe(p)),
699
- }),
700
- ],
701
- }),
702
- e.jsx(d, {
703
- variant: 'ghost',
704
- size: 'icon-sm',
705
- 'data-testid': 'webhook-delete',
706
- onClick: () => ae.mutate(t.id),
707
- disabled: ae.isPending,
708
- 'aria-label': s('common.delete'),
709
- title: s('common.delete'),
710
- children: e.jsx(je, { className: 'h-4 w-4' }),
711
- }),
712
- ],
713
- },
714
- t.id
715
- )
716
- ),
717
- ],
718
- }),
719
- ],
720
- }),
721
- ],
722
- }),
723
- (n === 'site' || n === 'notifications') &&
724
- e.jsx('div', {
725
- className: 'flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end',
726
- children: e.jsxs(d, {
727
- variant: 'default',
728
- 'data-testid': 'settings-save',
729
- onClick: () => se.mutate(),
730
- disabled: se.isPending,
731
- className: 'w-full sm:w-auto',
732
- children: [e.jsx(L, { className: 'h-4 w-4' }), s('common.save')],
733
- }),
734
- }),
735
- ],
736
- });
737
- }
738
- function Ke({ bot: s, expanded: m, onToggleExpand: u }) {
739
- var T;
740
- const { t: n } = B(),
741
- r = ge(),
742
- [x, y] = i.useState(s.name),
743
- [b, w] = i.useState(''),
744
- [k, C] = i.useState(s.enabled),
745
- [S, p] = i.useState(s.allowAuthRequests);
746
- i.useEffect(() => {
747
- y(s.name), C(s.enabled), p(s.allowAuthRequests);
748
- }, [s.allowAuthRequests, s.enabled, s.name]);
749
- const N = z({
750
- queryKey: ['telegram-bot-chats', s.id],
751
- enabled: m,
752
- queryFn: async () => {
753
- const a = await fetch(`/api/settings/telegram/bots/${s.id}/chats`);
754
- if (!a.ok) throw new Error(await h(a, n('telegram.loadChatsFailed')));
755
- return await a.json();
756
- },
757
- }),
758
- f = i.useMemo(() => {
759
- var l;
760
- const a = ((l = N.data) == null ? void 0 : l.chats) ?? [];
761
- return {
762
- pending: a.filter((v) => v.status === 'pending'),
763
- authorized: a.filter((v) => v.status === 'authorized'),
764
- };
765
- }, [(T = N.data) == null ? void 0 : T.chats]),
766
- P = j({
767
- mutationFn: async () => {
768
- const a = { name: x, enabled: k, allowAuthRequests: S };
769
- b.trim() && (a.token = b.trim());
770
- const l = await fetch(`/api/settings/telegram/bots/${s.id}`, {
771
- method: 'PATCH',
772
- headers: { 'Content-Type': 'application/json' },
773
- body: JSON.stringify(a),
774
- });
775
- if (!l.ok) throw new Error(await h(l, n('telegram.updateFailed')));
776
- },
777
- onSuccess: async () => {
778
- w(''),
779
- await r.invalidateQueries({ queryKey: ['telegram-bots'] }),
780
- o.success(n('common.success'));
781
- },
782
- onError: (a) => {
783
- o.error(a instanceof Error ? a.message : n('common.error'));
784
- },
785
- }),
786
- R = j({
787
- mutationFn: async () => {
788
- const a = await fetch(`/api/settings/telegram/bots/${s.id}`, { method: 'DELETE' });
789
- if (!a.ok) throw new Error(await h(a, n('telegram.deleteFailed')));
790
- },
791
- onSuccess: async () => {
792
- await r.invalidateQueries({ queryKey: ['telegram-bots'] }), o.success(n('common.success'));
793
- },
794
- onError: (a) => {
795
- o.error(a instanceof Error ? a.message : n('common.error'));
796
- },
797
- }),
798
- q = j({
799
- mutationFn: async (a) => {
800
- const l = await fetch(
801
- `/api/settings/telegram/bots/${s.id}/chats/${encodeURIComponent(a)}/approve`,
802
- { method: 'POST' }
803
- );
804
- if (!l.ok) throw new Error(await h(l, n('telegram.approveFailed')));
805
- },
806
- onSuccess: async () => {
807
- await Promise.all([
808
- r.invalidateQueries({ queryKey: ['telegram-bots'] }),
809
- r.invalidateQueries({ queryKey: ['telegram-bot-chats', s.id] }),
810
- ]),
811
- o.success(n('common.success'));
812
- },
813
- onError: (a) => {
814
- o.error(a instanceof Error ? a.message : n('common.error'));
815
- },
816
- }),
817
- E = j({
818
- mutationFn: async (a) => {
819
- const l = await fetch(
820
- `/api/settings/telegram/bots/${s.id}/chats/${encodeURIComponent(a)}`,
821
- { method: 'DELETE' }
822
- );
823
- if (!l.ok) throw new Error(await h(l, n('telegram.removeFailed')));
824
- },
825
- onSuccess: async () => {
826
- await Promise.all([
827
- r.invalidateQueries({ queryKey: ['telegram-bots'] }),
828
- r.invalidateQueries({ queryKey: ['telegram-bot-chats', s.id] }),
829
- ]),
830
- o.success(n('common.success'));
831
- },
832
- onError: (a) => {
833
- o.error(a instanceof Error ? a.message : n('common.error'));
834
- },
835
- }),
836
- A = j({
837
- mutationFn: async (a) => {
838
- const l = await fetch(
839
- `/api/settings/telegram/bots/${s.id}/chats/${encodeURIComponent(a)}/test`,
840
- { method: 'POST' }
841
- );
842
- if (!l.ok) throw new Error(await h(l, n('telegram.testMessageFailed')));
843
- },
844
- onSuccess: () => {
845
- o.success(n('common.success'));
846
- },
847
- onError: (a) => {
848
- o.error(a instanceof Error ? a.message : n('common.error'));
849
- },
850
- });
851
- return e.jsxs('div', {
852
- className: 'space-y-4 rounded-md border-0 bg-card p-4',
853
- 'data-testid': `telegram-bot-card-${s.id}`,
854
- 'data-bot-name': s.name,
855
- children: [
856
- e.jsxs('div', {
857
- className: 'flex items-center justify-between gap-3',
858
- children: [
859
- e.jsxs('div', {
860
- children: [
861
- e.jsx('div', { className: 'font-medium', children: s.name }),
862
- e.jsxs('div', {
863
- className: 'text-xs text-muted-foreground',
864
- children: [s.authorizedCount, ' / ', s.pendingCount],
865
- }),
866
- ],
867
- }),
868
- e.jsx(d, {
869
- variant: 'ghost',
870
- 'data-testid': `telegram-bot-toggle-${s.id}`,
871
- onClick: u,
872
- children: n(m ? 'common.collapse' : 'common.expand'),
873
- }),
874
- ],
875
- }),
876
- e.jsxs('div', {
877
- className: 'grid grid-cols-1 gap-4 md:grid-cols-12 md:items-end',
878
- children: [
879
- e.jsxs('div', {
880
- className: 'md:col-span-3 space-y-2',
881
- children: [
882
- e.jsx('label', {
883
- className: 'block text-sm font-medium',
884
- htmlFor: `bot-name-${s.id}`,
885
- children: n('telegram.botName'),
886
- }),
887
- e.jsx(g, {
888
- id: `bot-name-${s.id}`,
889
- value: x,
890
- onChange: (a) => y(a.target.value),
891
- className: 'min-h-10',
892
- }),
893
- ],
894
- }),
895
- e.jsxs('div', {
896
- className: 'md:col-span-4 space-y-2',
897
- children: [
898
- e.jsx('label', {
899
- className: 'block text-sm font-medium',
900
- htmlFor: `bot-token-${s.id}`,
901
- children: n('telegram.botToken'),
902
- }),
903
- e.jsx(g, {
904
- id: `bot-token-${s.id}`,
905
- type: 'password',
906
- value: b,
907
- onChange: (a) => w(a.target.value),
908
- placeholder: n('telegram.tokenPlaceholder'),
909
- className: 'min-h-10',
910
- }),
911
- ],
912
- }),
913
- e.jsx('div', {
914
- className: 'md:col-span-2',
915
- children: e.jsxs('div', {
916
- className:
917
- 'flex min-h-10 items-center justify-between gap-3 rounded-lg border border-border bg-background px-3 py-2.5',
918
- children: [
919
- e.jsx('span', { className: 'text-sm font-medium', children: n('common.enabled') }),
920
- e.jsx(F, { checked: k, onCheckedChange: (a) => C(!!a) }),
921
- ],
922
- }),
923
- }),
924
- e.jsx('div', {
925
- className: 'md:col-span-3',
926
- children: e.jsxs('div', {
927
- className:
928
- 'flex min-h-10 items-center justify-between gap-3 rounded-lg border border-border bg-background px-3 py-2.5',
929
- children: [
930
- e.jsx('span', {
931
- className: 'text-sm font-medium',
932
- children: n('telegram.allowAuthRequests'),
933
- }),
934
- e.jsx(F, { checked: S, onCheckedChange: (a) => p(!!a) }),
935
- ],
936
- }),
937
- }),
938
- ],
939
- }),
940
- e.jsxs('div', {
941
- className: 'flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-end',
942
- children: [
943
- e.jsxs(d, {
944
- variant: 'destructive',
945
- 'data-testid': `telegram-bot-delete-${s.id}`,
946
- onClick: () => R.mutate(),
947
- className: 'w-full sm:w-auto',
948
- children: [e.jsx(je, { className: 'h-4 w-4' }), n('telegram.deleteBot')],
949
- }),
950
- e.jsxs(d, {
951
- variant: 'default',
952
- 'data-testid': `telegram-bot-save-${s.id}`,
953
- onClick: () => P.mutate(),
954
- className: 'w-full sm:w-auto',
955
- children: [e.jsx(L, { className: 'h-4 w-4' }), n('common.save')],
956
- }),
957
- ],
958
- }),
959
- m &&
960
- e.jsxs('div', {
961
- className: 'grid grid-cols-1 gap-4 border-t border-border pt-4 lg:grid-cols-2',
962
- children: [
963
- e.jsxs('div', {
964
- className: 'space-y-2',
965
- children: [
966
- e.jsxs('h3', {
967
- className: 'text-sm font-semibold flex items-center gap-1',
968
- children: [e.jsx(he, { className: 'h-4 w-4' }), n('telegram.pendingChats')],
969
- }),
970
- f.pending.length === 0 &&
971
- e.jsx('div', { className: 'text-xs text-muted-foreground', children: '-' }),
972
- f.pending.map((a) =>
973
- e.jsx(
974
- ue,
975
- {
976
- chat: a,
977
- pending: !0,
978
- onApprove: () => q.mutate(a.chatId),
979
- onDelete: () => E.mutate(a.chatId),
980
- },
981
- `${a.botId}-${a.chatId}`
982
- )
983
- ),
984
- ],
985
- }),
986
- e.jsxs('div', {
987
- className: 'space-y-2',
988
- children: [
989
- e.jsxs('h3', {
990
- className: 'text-sm font-semibold flex items-center gap-1',
991
- children: [e.jsx(he, { className: 'h-4 w-4' }), n('telegram.chats')],
992
- }),
993
- f.authorized.length === 0 &&
994
- e.jsx('div', { className: 'text-xs text-muted-foreground', children: '-' }),
995
- f.authorized.map((a) =>
996
- e.jsx(
997
- ue,
998
- {
999
- chat: a,
1000
- pending: !1,
1001
- onTest: () => A.mutate(a.chatId),
1002
- onDelete: () => E.mutate(a.chatId),
1003
- },
1004
- `${a.botId}-${a.chatId}`
1005
- )
1006
- ),
1007
- ],
1008
- }),
1009
- N.isLoading &&
1010
- e.jsx('div', {
1011
- className: 'lg:col-span-2 text-xs text-muted-foreground',
1012
- children: n('common.loading'),
1013
- }),
1014
- ],
1015
- }),
1016
- ],
1017
- });
1018
- }
1019
- function ue({ chat: s, pending: m, onApprove: u, onDelete: n, onTest: r }) {
1020
- const { t: x } = B(),
1021
- y = xe((b) => {
1022
- var w;
1023
- return ((w = b.settings) == null ? void 0 : w.language) ?? 'en_US';
1024
- });
1025
- return e.jsxs('div', {
1026
- className: 'space-y-2 rounded border-0 bg-background p-3',
1027
- children: [
1028
- e.jsx('div', {
1029
- className: 'text-sm font-medium truncate',
1030
- title: s.displayName,
1031
- children: s.displayName,
1032
- }),
1033
- e.jsxs('div', {
1034
- className: 'text-xs text-muted-foreground',
1035
- children: [x('telegram.chatId'), ':', s.chatId],
1036
- }),
1037
- e.jsx('div', {
1038
- className: 'text-xs text-muted-foreground',
1039
- children: new Date(s.appliedAt).toLocaleString(pe(y)),
1040
- }),
1041
- e.jsx('div', {
1042
- className: 'flex items-center justify-end gap-2 pt-1',
1043
- children: m
1044
- ? e.jsxs(e.Fragment, {
1045
- children: [
1046
- e.jsx(d, {
1047
- variant: 'outline',
1048
- size: 'sm',
1049
- onClick: n,
1050
- children: x('telegram.reject'),
1051
- }),
1052
- e.jsx(d, {
1053
- variant: 'default',
1054
- size: 'sm',
1055
- onClick: u,
1056
- children: x('telegram.authorize'),
1057
- }),
1058
- ],
1059
- })
1060
- : e.jsxs(e.Fragment, {
1061
- children: [
1062
- e.jsxs(d, {
1063
- variant: 'secondary',
1064
- size: 'sm',
1065
- onClick: r,
1066
- children: [
1067
- e.jsx(Ie, { className: 'h-3.5 w-3.5' }),
1068
- x('telegram.sendTestMessage'),
1069
- ],
1070
- }),
1071
- e.jsx(d, {
1072
- variant: 'destructive',
1073
- size: 'sm',
1074
- onClick: n,
1075
- children: x('common.delete'),
1076
- }),
1077
- ],
1078
- }),
1079
- }),
1080
- ],
1081
- });
1082
- }
1083
- function Je() {
1084
- const { t: s } = B();
1085
- return e.jsx(e.Fragment, { children: s('sidebar.settings') });
1086
- }
1087
- function Ve() {
1088
- const { t: s } = B(),
1089
- [m, u] = i.useState(!1),
1090
- n = j({
1091
- mutationFn: async () => {
1092
- const r = await fetch('/api/settings/restart', { method: 'POST' });
1093
- if (!r.ok) throw new Error(await h(r, s('settings.restartFailed')));
1094
- },
1095
- onSuccess: () => {
1096
- o.success(s('settings.restartScheduled'));
1097
- },
1098
- onError: (r) => {
1099
- o.error(r instanceof Error ? r.message : s('common.error'));
1100
- },
1101
- });
1102
- return e.jsxs(e.Fragment, {
1103
- children: [
1104
- e.jsx(d, {
1105
- variant: 'ghost',
1106
- size: 'icon-sm',
1107
- onClick: () => u(!0),
1108
- disabled: n.isPending,
1109
- 'aria-label': s('settings.restartGateway'),
1110
- title: s('settings.restartGateway'),
1111
- className: 'text-destructive hover:text-destructive hover:bg-destructive/10',
1112
- children: e.jsx(ze, { className: 'h-4 w-4' }),
1113
- }),
1114
- e.jsx(Fe, {
1115
- open: m,
1116
- onOpenChange: u,
1117
- children: e.jsxs(Be, {
1118
- children: [
1119
- e.jsxs(Pe, {
1120
- children: [
1121
- e.jsx(Re, { children: s('settings.restartGateway') }),
1122
- e.jsx(qe, { children: s('settings.restartConfirm') }),
1123
- ],
1124
- }),
1125
- e.jsxs(Ae, {
1126
- children: [
1127
- e.jsx(Me, { onClick: () => u(!1), children: s('common.cancel') }),
1128
- e.jsx($e, {
1129
- variant: 'destructive',
1130
- onClick: () => {
1131
- n.mutate(), u(!1);
1132
- },
1133
- children: s('common.confirm'),
1134
- }),
1135
- ],
1136
- }),
1137
- ],
1138
- }),
1139
- }),
1140
- ],
1141
- });
1142
- }
1143
- export { Ve as PageActions, Je as PageTitle, We as default };
1144
- //# sourceMappingURL=SettingsPage-D25_d6j9.js.map