Implement NotifyOnStatusChange feature for nodes and enhance Telegram notifications
- Added `NotifyOnStatusChange` property to the `Node` class and related DTOs to allow individual node configuration for status change notifications. - Updated `NodeHealthCheckService` to send Telegram notifications to admins when a node's status changes, based on the new property. - Enhanced the `ITelegramNotifier` interface with a method for notifying admins about node status changes. - Modified the frontend to include a checkbox for `NotifyOnStatusChange` in the node editing dialog, allowing admins to easily configure this setting. - Updated API documentation to reflect the new `notifyOnStatusChange` parameter in the node update endpoint. - Added tests to ensure the correct behavior of the new feature and its integration with existing functionality.
This commit is contained in:
@@ -17,12 +17,22 @@ export function EditNodeDialog({ node, open, onOpenChange }: { node: NodeDto; op
|
||||
const [baseAddress, setBaseAddress] = useState(node.baseAddress)
|
||||
const [location, setLocation] = useState(node.location ?? '')
|
||||
const [isEnabled, setIsEnabled] = useState(node.isEnabled)
|
||||
const [notifyOnStatusChange, setNotifyOnStatusChange] = useState(node.notifyOnStatusChange)
|
||||
const [username, setUsername] = useState(node.username)
|
||||
const [password, setPassword] = useState('')
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: () =>
|
||||
updateNode(node.id, name.trim(), baseAddress.trim(), location.trim() || undefined, isEnabled, username.trim() || undefined, password || undefined),
|
||||
updateNode(
|
||||
node.id,
|
||||
name.trim(),
|
||||
baseAddress.trim(),
|
||||
location.trim() || undefined,
|
||||
isEnabled,
|
||||
notifyOnStatusChange,
|
||||
username.trim() || undefined,
|
||||
password || undefined,
|
||||
),
|
||||
onSuccess: async () => {
|
||||
toast.success(t('admin.nodes.updated'))
|
||||
await queryClient.invalidateQueries({ queryKey: ['admin-nodes'] })
|
||||
@@ -66,6 +76,14 @@ export function EditNodeDialog({ node, open, onOpenChange }: { node: NodeDto; op
|
||||
<input type="checkbox" checked={isEnabled} onChange={(e) => setIsEnabled(e.target.checked)} />
|
||||
{t('admin.nodes.enabled')}
|
||||
</label>
|
||||
<label className="flex items-center gap-2 text-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={notifyOnStatusChange}
|
||||
onChange={(e) => setNotifyOnStatusChange(e.target.checked)}
|
||||
/>
|
||||
{t('admin.nodes.notifyOnStatusChange')}
|
||||
</label>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<Label htmlFor="editUsername">
|
||||
{t('admin.nodes.username')} ({t('admin.nodes.optional')})
|
||||
|
||||
@@ -15,12 +15,21 @@ export function updateNode(
|
||||
baseAddress: string,
|
||||
location: string | undefined,
|
||||
isEnabled: boolean,
|
||||
notifyOnStatusChange: boolean,
|
||||
username: string | undefined,
|
||||
password: string | undefined,
|
||||
) {
|
||||
return apiRequest<NodeDto>(`/admin/nodes/${id}`, {
|
||||
method: 'PUT',
|
||||
body: { name, baseAddress, location: location ?? null, isEnabled, username: username ?? null, password: password ?? null },
|
||||
body: {
|
||||
name,
|
||||
baseAddress,
|
||||
location: location ?? null,
|
||||
isEnabled,
|
||||
notifyOnStatusChange,
|
||||
username: username ?? null,
|
||||
password: password ?? null,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -262,6 +262,7 @@ export type NodeDto = {
|
||||
location: string | null
|
||||
status: NodeStatus
|
||||
isEnabled: boolean
|
||||
notifyOnStatusChange: boolean
|
||||
lastSyncAt: string | null
|
||||
}
|
||||
|
||||
|
||||
@@ -430,6 +430,7 @@ const resources = {
|
||||
},
|
||||
enabled: 'Включена',
|
||||
disabled: 'Отключена',
|
||||
notifyOnStatusChange: 'Уведомлять в Telegram при смене статуса (онлайн/офлайн)',
|
||||
inbounds: 'Инбаунды',
|
||||
noInbounds: 'Инбаунды не найдены — нажмите «Синхронизировать».',
|
||||
publish: 'Публикация',
|
||||
@@ -999,6 +1000,7 @@ const resources = {
|
||||
},
|
||||
enabled: 'Enabled',
|
||||
disabled: 'Disabled',
|
||||
notifyOnStatusChange: 'Notify in Telegram on status change (online/offline)',
|
||||
inbounds: 'Inbounds',
|
||||
noInbounds: 'No inbounds found — click "Sync".',
|
||||
publish: 'Publishing',
|
||||
|
||||
Reference in New Issue
Block a user