Skip to content

Commit e6e1a99

Browse files
committed
feat(node-modal): add default and internal timeout fields with validation
1 parent 216ca4f commit e6e1a99

File tree

6 files changed

+115
-20
lines changed

6 files changed

+115
-20
lines changed

dashboard/public/statics/locales/en.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1403,7 +1403,11 @@
14031403
"viewIPs": "View IPs",
14041404
"userNotFound": "User '{{username}}' not found or not online",
14051405
"errorLoadingIPs": "Error loading user IP addresses"
1406-
}
1406+
},
1407+
"defaultTimeout": "Default Timeout",
1408+
"internalTimeout": "Internal Timeout",
1409+
"defaultTimeoutPlaceholder": "Enter default timeout (seconds)",
1410+
"internalTimeoutPlaceholder": "Enter internal timeout (seconds)"
14071411
},
14081412
"theme": {
14091413
"title": "Theme",

dashboard/public/statics/locales/fa.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,11 @@
12441244
"viewIPs": "مشاهده IP ‌ها",
12451245
"userNotFound": "کاربر '{{username}}' یافت نشد یا آنلاین نیست",
12461246
"errorLoadingIPs": "خطا در بارگذاری آدرس‌های IP کاربر"
1247-
}
1247+
},
1248+
"defaultTimeout": "مهلت پیش‌فرض",
1249+
"internalTimeout": "مهلت اینترنال",
1250+
"defaultTimeoutPlaceholder": "مهلت پیش‌فرض را وارد کنید (ثانیه)",
1251+
"internalTimeoutPlaceholder": "مهلت اینترنال را وارد کنید (ثانیه)"
12481252
},
12491253
"nodes": {
12501254
"title": "گره‌ها",

dashboard/public/statics/locales/ru.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,11 @@
13021302
"viewIPs": "Просмотр IP",
13031303
"userNotFound": "Пользователь '{{username}}' не найден или не в сети",
13041304
"errorLoadingIPs": "Ошибка загрузки IP адресов пользователя"
1305-
}
1305+
},
1306+
"defaultTimeout": "Тайм-аут по умолчанию",
1307+
"internalTimeout": "Внутренний тайм-аут",
1308+
"defaultTimeoutPlaceholder": "Введите тайм-аут по умолчанию (в секундах)",
1309+
"internalTimeoutPlaceholder": "Введите внутренний тайм-аут (в секундах)"
13061310
},
13071311
"theme": {
13081312
"title": "Тема",

dashboard/public/statics/locales/zh.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,11 @@
13641364
"coreConfig": "核心配置",
13651365
"hours": "小时",
13661366
"selectCoreConfig": "选择核心配置",
1367-
"noCoreConfig": "无核心配置"
1367+
"noCoreConfig": "无核心配置",
1368+
"defaultTimeout": "默认超时",
1369+
"internalTimeout": "内部超时",
1370+
"defaultTimeoutPlaceholder": "请输入默认超时(秒)",
1371+
"internalTimeoutPlaceholder": "请输入内部超时(秒)"
13681372
},
13691373
"theme": {
13701374
"title": "主题",

dashboard/src/components/dialogs/node-modal.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export const nodeFormSchema = z.object({
3535
data_limit: z.number().min(0).optional().nullable(),
3636
data_limit_reset_strategy: z.nativeEnum(DataLimitResetStrategy).optional().nullable(),
3737
reset_time: z.union([z.null(), z.undefined(), z.number().min(-1)]),
38+
default_timeout:z.number().min(3 , 'Default timeout must be 3 or greater').max(60, 'Default timeout must be 60 or lower').optional(),
39+
internal_timeout:z.number().min(3 , 'Internal timeout must be 3 or greater').max(60, 'Internal timeout must be 60 or lower').optional()
3840
})
3941

4042
export type NodeFormValues = z.infer<typeof nodeFormSchema>
@@ -142,6 +144,8 @@ export default function NodeModal({ isDialogOpen, onOpenChange, form, editingNod
142144
data_limit: dataLimitGB,
143145
data_limit_reset_strategy: nodeData.data_limit_reset_strategy ?? DataLimitResetStrategy.no_reset,
144146
reset_time: nodeData.reset_time ?? null,
147+
default_timeout: nodeData.default_timeout ?? 10,
148+
internal_timeout: nodeData.internal_timeout ?? 15,
145149
})
146150
setIsFetchingNodeData(false)
147151
} else {
@@ -175,6 +179,8 @@ export default function NodeModal({ isDialogOpen, onOpenChange, form, editingNod
175179
data_limit: dataLimitGB,
176180
data_limit_reset_strategy: nodeData.data_limit_reset_strategy ?? DataLimitResetStrategy.no_reset,
177181
reset_time: nodeData.reset_time ?? null,
182+
default_timeout: nodeData.default_timeout ?? 10,
183+
internal_timeout: nodeData.internal_timeout ?? 15,
178184
})
179185
} catch (error) {
180186
console.error('Error fetching node data:', error)
@@ -201,6 +207,8 @@ export default function NodeModal({ isDialogOpen, onOpenChange, form, editingNod
201207
data_limit: 0,
202208
data_limit_reset_strategy: DataLimitResetStrategy.no_reset,
203209
reset_time: -1,
210+
default_timeout: 10,
211+
internal_timeout: 15,
204212
})
205213
}
206214
}, [editingNode, editingNodeId, isDialogOpen, cores, initialNodeData, form])
@@ -1042,6 +1050,48 @@ export default function NodeModal({ isDialogOpen, onOpenChange, form, editingNod
10421050
)
10431051
}}
10441052
/>
1053+
<div className="flex flex-col sm:flex-row gap-2">
1054+
<FormField
1055+
control={form.control}
1056+
name="default_timeout"
1057+
render={({ field }) => (
1058+
<FormItem className="flex-1">
1059+
<FormLabel>{t('nodeModal.defaultTimeout')}</FormLabel>
1060+
<FormControl>
1061+
<Input
1062+
isError={!!form.formState.errors.default_timeout}
1063+
type="number"
1064+
step="1"
1065+
placeholder={t('nodeModal.defaultTimeoutPlaceholder')}
1066+
{...field}
1067+
onChange={e => field.onChange(parseInt(e.target.value))}
1068+
/>
1069+
</FormControl>
1070+
<FormMessage />
1071+
</FormItem>
1072+
)}
1073+
/>
1074+
<FormField
1075+
control={form.control}
1076+
name="internal_timeout"
1077+
render={({ field }) => (
1078+
<FormItem className="flex-1">
1079+
<FormLabel>{t('nodeModal.internalTimeout')}</FormLabel>
1080+
<FormControl>
1081+
<Input
1082+
isError={!!form.formState.errors.internal_timeout}
1083+
type="number"
1084+
step="1"
1085+
placeholder={t('nodeModal.internalTimeoutPlaceholder')}
1086+
{...field}
1087+
onChange={e => field.onChange(parseInt(e.target.value))}
1088+
/>
1089+
</FormControl>
1090+
<FormMessage />
1091+
</FormItem>
1092+
)}
1093+
/>
1094+
</div>
10451095
</div>
10461096
</div>
10471097
</AccordionContent>

dashboard/src/service/api/index.ts

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,6 @@ export type XrayMuxSettingsOutputXudpConcurrency = number | null
181181

182182
export type XrayMuxSettingsOutputConcurrency = number | null
183183

184-
export interface XrayMuxSettingsOutput {
185-
enabled?: boolean
186-
concurrency?: XrayMuxSettingsOutputConcurrency
187-
xudpConcurrency?: XrayMuxSettingsOutputXudpConcurrency
188-
xudpProxyUDP443?: Xudp
189-
}
190-
191184
export type XrayMuxSettingsInputXudpConcurrency = number | null
192185

193186
export type XrayMuxSettingsInputConcurrency = number | null
@@ -217,6 +210,13 @@ export const Xudp = {
217210
skip: 'skip',
218211
} as const
219212

213+
export interface XrayMuxSettingsOutput {
214+
enabled?: boolean
215+
concurrency?: XrayMuxSettingsOutputConcurrency
216+
xudpConcurrency?: XrayMuxSettingsOutputXudpConcurrency
217+
xudpProxyUDP443?: Xudp
218+
}
219+
220220
export type XTLSFlows = (typeof XTLSFlows)[keyof typeof XTLSFlows]
221221

222222
// eslint-disable-next-line @typescript-eslint/no-redeclare
@@ -759,6 +759,8 @@ export interface TransportSettingsOutput {
759759

760760
export type TransportSettingsInputWebsocketSettings = WebSocketSettings | null
761761

762+
export type TransportSettingsInputTcpSettings = TcpSettings | null
763+
762764
export type TransportSettingsInputKcpSettings = KCPSettings | null
763765

764766
export type TransportSettingsInputGrpcSettings = GRPCSettings | null
@@ -811,8 +813,6 @@ export interface TcpSettings {
811813
response?: TcpSettingsResponse
812814
}
813815

814-
export type TransportSettingsInputTcpSettings = TcpSettings | null
815-
816816
export type SystemStatsCpuUsage = number | null
817817

818818
export type SystemStatsCpuCores = number | null
@@ -1271,6 +1271,16 @@ export interface NodeResponse {
12711271
data_limit?: number
12721272
data_limit_reset_strategy?: DataLimitResetStrategy
12731273
reset_time?: number
1274+
/**
1275+
* @minimum 3
1276+
* @maximum 60
1277+
*/
1278+
default_timeout?: number
1279+
/**
1280+
* @minimum 3
1281+
* @maximum 60
1282+
*/
1283+
internal_timeout?: number
12741284
id: number
12751285
xray_version: NodeResponseXrayVersion
12761286
node_version: NodeResponseNodeVersion
@@ -1303,6 +1313,10 @@ export interface NodeNotificationEnable {
13031313

13041314
export type NodeModifyStatus = NodeStatus | null
13051315

1316+
export type NodeModifyInternalTimeout = number | null
1317+
1318+
export type NodeModifyDefaultTimeout = number | null
1319+
13061320
export type NodeModifyResetTime = number | null
13071321

13081322
export type NodeModifyDataLimitResetStrategy = DataLimitResetStrategy | null
@@ -1340,6 +1354,8 @@ export interface NodeModify {
13401354
data_limit?: NodeModifyDataLimit
13411355
data_limit_reset_strategy?: NodeModifyDataLimitResetStrategy
13421356
reset_time?: NodeModifyResetTime
1357+
default_timeout?: NodeModifyDefaultTimeout
1358+
internal_timeout?: NodeModifyInternalTimeout
13431359
status?: NodeModifyStatus
13441360
}
13451361

@@ -1365,6 +1381,16 @@ export interface NodeCreate {
13651381
data_limit?: number
13661382
data_limit_reset_strategy?: DataLimitResetStrategy
13671383
reset_time?: number
1384+
/**
1385+
* @minimum 3
1386+
* @maximum 60
1387+
*/
1388+
default_timeout?: number
1389+
/**
1390+
* @minimum 3
1391+
* @maximum 60
1392+
*/
1393+
internal_timeout?: number
13681394
}
13691395

13701396
export type NextPlanModelExpire = number | null
@@ -1884,6 +1910,16 @@ export interface ApplicationInput {
18841910
download_links: DownloadLink[]
18851911
}
18861912

1913+
/**
1914+
* Response model for admins list with pagination and statistics.
1915+
*/
1916+
export interface AdminsResponse {
1917+
admins: AdminDetails[]
1918+
total: number
1919+
active: number
1920+
disabled: number
1921+
}
1922+
18871923
export interface AdminNotificationEnable {
18881924
create?: boolean
18891925
modify?: boolean
@@ -1949,13 +1985,6 @@ export type AdminDetailsTelegramId = number | null
19491985
/**
19501986
* Complete admin model with all fields for database representation and API responses.
19511987
*/
1952-
export interface AdminsResponse {
1953-
admins: AdminDetails[]
1954-
total: number
1955-
active: number
1956-
disabled: number
1957-
}
1958-
19591988
export interface AdminDetails {
19601989
username: string
19611990
telegram_id?: AdminDetailsTelegramId

0 commit comments

Comments
 (0)