Skip to content

Commit 925dd1b

Browse files
committed
fix(user-modal): enhance user edit form initialization for keep auto refresh updates off during edit
1 parent 8fca358 commit 925dd1b

File tree

6 files changed

+32
-70
lines changed

6 files changed

+32
-70
lines changed

dashboard/public/statics/locales/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1350,7 +1350,7 @@
13501350
"proxySettings.wireguardPublicKey": "WireGuard Public key",
13511351
"proxySettings.wireguardPeerIps": "WireGuard Peer IPs",
13521352
"proxySettings.generateWireGuardKeyPair": "WireGuard keypair",
1353-
"proxySettings.peerIpsHint": "Leave empty to auto-assign from the global WireGuard peer pool. Manual entries must fall within that pool.",
1353+
"proxySettings.peerIpsHint": "Leave empty to auto-assign from the global WireGuard peer pool. For manual entries, enter one CIDR per line, and keep each value within that pool.",
13541354
"proxySettings.wireguardGenerated": "WireGuard keypair generated",
13551355
"proxySettings.desc": "Configure protocol-specific settings for this user.",
13561356
"selectNode": "Select Node",

dashboard/public/statics/locales/fa.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,7 @@
12151215
"userDialog.proxySettings.wireguardPublicKey": "کلید عمومی وایرگارد",
12161216
"userDialog.proxySettings.wireguardPeerIps": "IPهای همتای وایرگارد",
12171217
"userDialog.proxySettings.generateWireGuardKeyPair": "جفت‌کلید وایرگارد",
1218-
"userDialog.proxySettings.peerIpsHint": "برای تخصیص خودکار از استخر سراسری آی‌پی وایرگارد خالی بگذارید. مقادیر دستی باید داخل همان محدوده باشند.",
1218+
"userDialog.proxySettings.peerIpsHint": "برای تخصیص خودکار از استخر سراسری آی‌پی وایرگارد خالی بگذارید. در ورود دستی، هر CIDR را در یک خط جدا وارد کنید و همه مقادیر باید داخل همان محدوده باشند.",
12191219
"userDialog.proxySettings.wireguardGenerated": "جفت‌کلید وایرگارد تولید شد",
12201220
"userDialog.proxySettings.desc": "تنظیمات اختصاصی پروتکل برای این کاربر را پیکربندی کنید.",
12211221
"userDialog.expireDate": "تاریخ انقضا",

dashboard/public/statics/locales/ru.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,7 @@
17181718
"proxySettings.wireguardPublicKey": "Публичный ключ WireGuard",
17191719
"proxySettings.wireguardPeerIps": "Peer IP-адреса WireGuard",
17201720
"proxySettings.generateWireGuardKeyPair": "Пара ключей WireGuard",
1721-
"proxySettings.peerIpsHint": "Оставьте пустым для автоназначения из глобального пула peer-адресов WireGuard. Ручной ввод должен попадать в этот пул.",
1721+
"proxySettings.peerIpsHint": "Оставьте пустым для автоназначения из глобального пула peer-адресов WireGuard. При ручном вводе указывайте по одному CIDR в строке, и каждое значение должно входить в этот пул.",
17221722
"proxySettings.wireguardGenerated": "Пара ключей WireGuard сгенерирована",
17231723
"proxySettings.desc": "Настройте параметры протокола для этого пользователя.",
17241724
"selectNode": "Выберите узел",

dashboard/public/statics/locales/zh.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,7 @@
13211321
"userDialog.proxySettings.wireguardPublicKey": "WireGuard 公钥",
13221322
"userDialog.proxySettings.wireguardPeerIps": "WireGuard 对端 IP",
13231323
"userDialog.proxySettings.generateWireGuardKeyPair": "WireGuard 密钥对",
1324-
"userDialog.proxySettings.peerIpsHint": "留空则从全局 WireGuard 对端地址池自动分配;手动填写须在该池范围内",
1324+
"userDialog.proxySettings.peerIpsHint": "留空则从全局 WireGuard 对端地址池自动分配;手动填写时每行输入一个 CIDR,且每个值都必须在该地址池范围内",
13251325
"userDialog.proxySettings.wireguardGenerated": "WireGuard 密钥对已生成",
13261326
"userDialog.proxySettings.desc": "为此用户配置协议专属设置。",
13271327
"userDialog.expireDate": "过期日期",

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2259,7 +2259,7 @@ function UserModal({ isDialogOpen, onOpenChange, form, editingUser, editingUserI
22592259
/>
22602260
</FormControl>
22612261
<p className="text-xs text-muted-foreground">
2262-
{t('userDialog.proxySettings.peerIpsHint', { defaultValue: 'Leave empty to auto-assign from the global WireGuard peer pool. Manual entries must fall within that pool.' })}
2262+
{t('userDialog.proxySettings.peerIpsHint', { defaultValue: 'Leave empty to auto-assign from the global WireGuard peer pool. For manual entries, enter one CIDR per line, and keep each value within that pool.' })}
22632263
</p>
22642264
<FormMessage />
22652265
</FormItem>

dashboard/src/components/users/action-buttons.tsx

Lines changed: 27 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,27 @@ const updateModalState = (userId: number, updater: (prev: ActionButtonsModalStat
159159
notifyGlobalListeners()
160160
}
161161

162+
const buildUserEditFormValues = (user: UserResponse): UseEditFormValues => ({
163+
username: user.username,
164+
status: user.status === 'active' || user.status === 'on_hold' || user.status === 'disabled' ? (user.status as UseEditFormValues['status']) : 'active',
165+
data_limit: user.data_limit ? bytesToFormGigabytes(Number(user.data_limit)) : 0,
166+
expire: normalizeExpireForEditForm(user.expire),
167+
note: user.note || '',
168+
data_limit_reset_strategy: user.data_limit_reset_strategy || undefined,
169+
group_ids: user.group_ids || [],
170+
on_hold_expire_duration: user.on_hold_expire_duration || undefined,
171+
on_hold_timeout: user.on_hold_timeout || undefined,
172+
proxy_settings: user.proxy_settings || undefined,
173+
next_plan: user.next_plan
174+
? {
175+
user_template_id: user.next_plan.user_template_id ? Number(user.next_plan.user_template_id) : undefined,
176+
data_limit: user.next_plan.data_limit ? Math.round(Number(user.next_plan.data_limit)) : 0,
177+
expire: user.next_plan.expire ? Math.round(Number(user.next_plan.expire)) : 0,
178+
add_remaining_traffic: user.next_plan.add_remaining_traffic || false,
179+
}
180+
: undefined,
181+
})
182+
162183
const ActionButtons: FC<ActionButtonsProps> = ({ user, isModalHost = true, renderActions = true }) => {
163184
const [subscribeLinks, setSubscribeLinks] = useState<SubscribeLink[]>([])
164185
const [isEditModalOpen, setEditModalOpen] = useState(false)
@@ -264,54 +285,16 @@ const ActionButtons: FC<ActionButtonsProps> = ({ user, isModalHost = true, rende
264285

265286
// Create form for user editing
266287
const userForm = useForm<UseEditFormValues>({
267-
defaultValues: {
268-
username: user.username,
269-
status: user.status === 'expired' || user.status === 'limited' ? 'active' : user.status,
270-
data_limit: user.data_limit ? bytesToFormGigabytes(Number(user.data_limit)) : undefined,
271-
expire: normalizeExpireForEditForm(user.expire),
272-
note: user.note || '',
273-
data_limit_reset_strategy: user.data_limit_reset_strategy || undefined,
274-
group_ids: user.group_ids || [], // Add group_ids
275-
on_hold_expire_duration: user.on_hold_expire_duration || undefined,
276-
on_hold_timeout: user.on_hold_timeout || undefined,
277-
proxy_settings: user.proxy_settings || undefined,
278-
next_plan: user.next_plan
279-
? {
280-
user_template_id: user.next_plan.user_template_id ? Number(user.next_plan.user_template_id) : undefined,
281-
data_limit: user.next_plan.data_limit ? Math.round(Number(user.next_plan.data_limit)) : 0,
282-
expire: user.next_plan.expire ? Math.round(Number(user.next_plan.expire)) : 0,
283-
add_remaining_traffic: user.next_plan.add_remaining_traffic || false,
284-
}
285-
: undefined,
286-
},
288+
defaultValues: buildUserEditFormValues(user),
287289
})
288290

289291
// Update form when user data changes
290292
useEffect(() => {
291-
const values: UseEditFormValues = {
292-
username: user.username,
293-
status: user.status === 'active' || user.status === 'on_hold' || user.status === 'disabled' ? (user.status as any) : 'active',
294-
data_limit: user.data_limit ? bytesToFormGigabytes(Number(user.data_limit)) : 0,
295-
expire: normalizeExpireForEditForm(user.expire),
296-
note: user.note || '',
297-
data_limit_reset_strategy: user.data_limit_reset_strategy || undefined,
298-
group_ids: user.group_ids || [],
299-
on_hold_expire_duration: user.on_hold_expire_duration || undefined,
300-
on_hold_timeout: user.on_hold_timeout || undefined,
301-
proxy_settings: user.proxy_settings || undefined,
302-
next_plan: user.next_plan
303-
? {
304-
user_template_id: user.next_plan.user_template_id ? Number(user.next_plan.user_template_id) : undefined,
305-
data_limit: user.next_plan.data_limit ? Math.round(Number(user.next_plan.data_limit)) : 0,
306-
expire: user.next_plan.expire ? Math.round(Number(user.next_plan.expire)) : 0,
307-
add_remaining_traffic: user.next_plan.add_remaining_traffic || false,
308-
}
309-
: undefined,
310-
}
293+
// Keep background refreshes from clobbering an active edit session.
294+
if (isEditModalOpen) return
311295

312-
// Update form with current values
313-
userForm.reset(values)
314-
}, [user, userForm])
296+
userForm.reset(buildUserEditFormValues(user))
297+
}, [user, userForm, isEditModalOpen])
315298

316299
const onOpenSubscriptionModal = useCallback(() => {
317300
setSubscribeUrl(user.subscription_url ? user.subscription_url : '')
@@ -372,28 +355,7 @@ const ActionButtons: FC<ActionButtonsProps> = ({ user, isModalHost = true, rende
372355
}
373356

374357
// Update form with latest user data
375-
const values: UseEditFormValues = {
376-
username: latestUser.username,
377-
status: latestUser.status === 'active' || latestUser.status === 'on_hold' || latestUser.status === 'disabled' ? (latestUser.status as any) : 'active',
378-
data_limit: latestUser.data_limit ? bytesToFormGigabytes(Number(latestUser.data_limit)) : 0,
379-
expire: normalizeExpireForEditForm(latestUser.expire),
380-
note: latestUser.note || '',
381-
data_limit_reset_strategy: latestUser.data_limit_reset_strategy || undefined,
382-
group_ids: latestUser.group_ids || [],
383-
on_hold_expire_duration: latestUser.on_hold_expire_duration || undefined,
384-
on_hold_timeout: latestUser.on_hold_timeout || undefined,
385-
proxy_settings: latestUser.proxy_settings || undefined,
386-
next_plan: latestUser.next_plan
387-
? {
388-
user_template_id: latestUser.next_plan.user_template_id ? Number(latestUser.next_plan.user_template_id) : undefined,
389-
data_limit: latestUser.next_plan.data_limit ? Math.round(Number(latestUser.next_plan.data_limit)) : 0,
390-
expire: latestUser.next_plan.expire ? Math.round(Number(latestUser.next_plan.expire)) : 0,
391-
add_remaining_traffic: latestUser.next_plan.add_remaining_traffic || false,
392-
}
393-
: undefined,
394-
}
395-
396-
userForm.reset(values)
358+
userForm.reset(buildUserEditFormValues(latestUser))
397359
setSelectedUser(latestUser)
398360
setEditModalOpen(true)
399361
}

0 commit comments

Comments
 (0)