| 1 |
16e5ea1 |
Mrdn |
2y ago |
import { useQuery } from '@tanstack/react-query'; |
| 2 |
bf7c131 |
Mardin |
2y ago |
import { fetch } from 'service/http'; |
| 3 |
bf7c131 |
Mardin |
2y ago |
import { create } from 'zustand'; |
| 4 |
5bb2712 |
Mardin |
2y ago |
import { z } from 'zod'; |
| 5 |
89f8f93 |
Mardin |
2y ago |
import { FilterUsageType, NodesFilterType } from 'types/filter'; |
| 6 |
6aab6f0 |
Mrdn |
2y ago |
import { pageSizeManagers } from 'utils/userPreferenceStorage'; |
| 7 |
89f8f93 |
Mardin |
2y ago |
import { useDashboard } from './dashboard.store'; |
| 8 |
a61ba53 |
Mrdn |
2y ago |
import { queryClient } from 'service/react-query'; |
| 9 |
a61ba53 |
Mrdn |
2y ago |
import { queryIds } from 'constants/query-ids'; |
| 10 |
a47eb4c |
Dawsh |
2y ago |
|
| 11 |
a47eb4c |
Dawsh |
2y ago |
export const NodeSchema = z.object({ |
| 12 |
a47eb4c |
Dawsh |
2y ago |
name: z.string().min(1), |
| 13 |
a47eb4c |
Dawsh |
2y ago |
address: z.string().min(1), |
| 14 |
a47eb4c |
Dawsh |
2y ago |
port: z |
| 15 |
a47eb4c |
Dawsh |
2y ago |
.number() |
| 16 |
a47eb4c |
Dawsh |
2y ago |
.min(1) |
| 17 |
a47eb4c |
Dawsh |
2y ago |
.or(z.string().transform((v) => parseFloat(v))), |
| 18 |
a47eb4c |
Dawsh |
2y ago |
xray_version: z.string().nullable().optional(), |
| 19 |
a47eb4c |
Dawsh |
2y ago |
id: z.number().nullable().optional(), |
| 20 |
a47eb4c |
Dawsh |
2y ago |
status: z |
| 21 |
5bb2712 |
Mardin |
2y ago |
.enum(['healthy', 'unhealthy', 'disabled']), |
| 22 |
a47eb4c |
Dawsh |
2y ago |
message: z.string().nullable().optional(), |
| 23 |
5bb2712 |
Mardin |
2y ago |
usage_coefficient: z.number().default(1), |
| 24 |
5bb2712 |
Mardin |
2y ago |
add_as_new_host: z.boolean(), |
| 25 |
5bb2712 |
Mardin |
2y ago |
}); |
| 26 |
5bb2712 |
Mardin |
2y ago |
|
| 27 |
5bb2712 |
Mardin |
2y ago |
export const NodeCreateSchema = z.object({ |
| 28 |
5bb2712 |
Mardin |
2y ago |
name: z.string().min(1), |
| 29 |
5bb2712 |
Mardin |
2y ago |
address: z.string().min(1), |
| 30 |
5bb2712 |
Mardin |
2y ago |
port: z |
| 31 |
5bb2712 |
Mardin |
2y ago |
.number() |
| 32 |
5bb2712 |
Mardin |
2y ago |
.min(1) |
| 33 |
5bb2712 |
Mardin |
2y ago |
.or(z.string().transform((v) => parseFloat(v))), |
| 34 |
5bb2712 |
Mardin |
2y ago |
id: z.number().nullable().optional(), |
| 35 |
5bb2712 |
Mardin |
2y ago |
status: z |
| 36 |
5bb2712 |
Mardin |
2y ago |
.enum(['none', 'disabled']), |
| 37 |
5bb2712 |
Mardin |
2y ago |
usage_coefficient: z.number().default(1), |
| 38 |
a47eb4c |
Dawsh |
2y ago |
add_as_new_host: z.boolean().optional(), |
| 39 |
a47eb4c |
Dawsh |
2y ago |
}); |
| 40 |
a47eb4c |
Dawsh |
2y ago |
|
| 41 |
a47eb4c |
Dawsh |
2y ago |
export type NodeType = z.infer<typeof NodeSchema>; |
| 42 |
5bb2712 |
Mardin |
2y ago |
export type NodeCreate = z.infer<typeof NodeCreateSchema>; |
| 43 |
a47eb4c |
Dawsh |
2y ago |
|
| 44 |
a47eb4c |
Dawsh |
2y ago |
export const getNodeDefaultValues = (): NodeType => ({ |
| 45 |
bf7c131 |
Mardin |
2y ago |
name: '', |
| 46 |
bf7c131 |
Mardin |
2y ago |
address: '', |
| 47 |
5bb2712 |
Mardin |
2y ago |
status: 'unhealthy', |
| 48 |
a47eb4c |
Dawsh |
2y ago |
port: 62050, |
| 49 |
bf7c131 |
Mardin |
2y ago |
xray_version: '', |
| 50 |
5bb2712 |
Mardin |
2y ago |
add_as_new_host: false, |
| 51 |
5bb2712 |
Mardin |
2y ago |
usage_coefficient: 1, |
| 52 |
5bb2712 |
Mardin |
2y ago |
}); |
| 53 |
5bb2712 |
Mardin |
2y ago |
|
| 54 |
5bb2712 |
Mardin |
2y ago |
export const getNodeCreateDefaultValues = (): NodeCreate => ({ |
| 55 |
5bb2712 |
Mardin |
2y ago |
name: '', |
| 56 |
5bb2712 |
Mardin |
2y ago |
address: '', |
| 57 |
5bb2712 |
Mardin |
2y ago |
status: 'none', |
| 58 |
5bb2712 |
Mardin |
2y ago |
port: 62050, |
| 59 |
5bb2712 |
Mardin |
2y ago |
add_as_new_host: false, |
| 60 |
5bb2712 |
Mardin |
2y ago |
usage_coefficient: 1, |
| 61 |
5bb2712 |
Mardin |
2y ago |
id: 0, |
| 62 |
a47eb4c |
Dawsh |
2y ago |
}); |
| 63 |
a47eb4c |
Dawsh |
2y ago |
|
| 64 |
bf7c131 |
Mardin |
2y ago |
export const FetchNodesQueryKey = 'fetch-nodes-query-key'; |
| 65 |
a47eb4c |
Dawsh |
2y ago |
|
| 66 |
a61ba53 |
Mrdn |
2y ago |
export function fetchNodes(): Promise<NodeType[]> { |
| 67 |
a61ba53 |
Mrdn |
2y ago |
useDashboard.setState({ loading: true }) |
| 68 |
a61ba53 |
Mrdn |
2y ago |
return fetch('/nodes').then((nodes) => { |
| 69 |
a61ba53 |
Mrdn |
2y ago |
return nodes; |
| 70 |
a61ba53 |
Mrdn |
2y ago |
}).finally(() => { |
| 71 |
a61ba53 |
Mrdn |
2y ago |
useDashboard.setState({ loading: false }) |
| 72 |
a61ba53 |
Mrdn |
2y ago |
}); |
| 73 |
5bb2712 |
Mardin |
2y ago |
} |
| 74 |
5bb2712 |
Mardin |
2y ago |
|
| 75 |
a47eb4c |
Dawsh |
2y ago |
export type NodeStore = { |
| 76 |
5bb2712 |
Mardin |
2y ago |
certificate: string, |
| 77 |
5bb2712 |
Mardin |
2y ago |
deletingNode?: NodeCreate | null; |
| 78 |
5bb2712 |
Mardin |
2y ago |
editingNode: NodeCreate | null; |
| 79 |
5bb2712 |
Mardin |
2y ago |
isAddingNode: boolean; |
| 80 |
4205669 |
Mardin |
2y ago |
isShowingNodesUsage: boolean; |
| 81 |
5bb2712 |
Mardin |
2y ago |
isEditingNode: boolean; |
| 82 |
4205669 |
Mardin |
2y ago |
isEditingCore: boolean; |
| 83 |
5bb2712 |
Mardin |
2y ago |
nodesFilters: NodesFilterType; |
| 84 |
5bb2712 |
Mardin |
2y ago |
refetchNodes: () => void; |
| 85 |
5bb2712 |
Mardin |
2y ago |
refetchCertificate: () => void; |
| 86 |
a47eb4c |
Dawsh |
2y ago |
fetchNodesUsage: (query: FilterUsageType) => Promise<void>; |
| 87 |
5bb2712 |
Mardin |
2y ago |
addNode: (node: NodeCreate) => Promise<unknown>; |
| 88 |
5bb2712 |
Mardin |
2y ago |
deleteNode: (node: NodeCreate) => Promise<unknown>; |
| 89 |
5bb2712 |
Mardin |
2y ago |
updateNode: (node: NodeCreate) => Promise<unknown>; |
| 90 |
a47eb4c |
Dawsh |
2y ago |
reconnectNode: (node: NodeType) => Promise<unknown>; |
| 91 |
5bb2712 |
Mardin |
2y ago |
onDeletingNode: (node: NodeCreate | undefined) => void; |
| 92 |
5bb2712 |
Mardin |
2y ago |
onEditingNode: (node: NodeType | undefined) => void; |
| 93 |
5bb2712 |
Mardin |
2y ago |
onAddingNode: (isAddingNode: boolean) => void; |
| 94 |
5bb2712 |
Mardin |
2y ago |
onFilterChange: (filters: Partial<NodesFilterType>) => void; |
| 95 |
4205669 |
Mardin |
2y ago |
onShowingNodesUsage: (isShowingNodesUsage: boolean) => void; |
| 96 |
a47eb4c |
Dawsh |
2y ago |
}; |
| 97 |
a47eb4c |
Dawsh |
2y ago |
|
| 98 |
16e5ea1 |
Mrdn |
2y ago |
// TODO: Refactor all useQuery for inbounds, hosts, |
| 99 |
16e5ea1 |
Mrdn |
2y ago |
// services and uses to be a custom hook like this. |
| 100 |
a47eb4c |
Dawsh |
2y ago |
export const useNodesQuery = () => { |
| 101 |
a47eb4c |
Dawsh |
2y ago |
return useQuery({ |
| 102 |
16e5ea1 |
Mrdn |
2y ago |
queryKey: [FetchNodesQueryKey], |
| 103 |
5bb2712 |
Mardin |
2y ago |
queryFn: fetchNodes, |
| 104 |
5bb2712 |
Mardin |
2y ago |
refetchInterval: useNodes.getState().editingNode ? 3000 : undefined, |
| 105 |
a47eb4c |
Dawsh |
2y ago |
refetchOnWindowFocus: false, |
| 106 |
a47eb4c |
Dawsh |
2y ago |
}); |
| 107 |
a47eb4c |
Dawsh |
2y ago |
}; |
| 108 |
a47eb4c |
Dawsh |
2y ago |
|
| 109 |
a47eb4c |
Dawsh |
2y ago |
export const useNodes = create<NodeStore>((set, get) => ({ |
| 110 |
5bb2712 |
Mardin |
2y ago |
certificate: '', |
| 111 |
5bb2712 |
Mardin |
2y ago |
editingNode: null, |
| 112 |
5bb2712 |
Mardin |
2y ago |
deletingNode: null, |
| 113 |
5bb2712 |
Mardin |
2y ago |
isAddingNode: false, |
| 114 |
5bb2712 |
Mardin |
2y ago |
isEditingNode: false, |
| 115 |
4205669 |
Mardin |
2y ago |
isShowingNodesUsage: false, |
| 116 |
4205669 |
Mardin |
2y ago |
isEditingCore: false, |
| 117 |
5bb2712 |
Mardin |
2y ago |
nodesFilters: { |
| 118 |
5bb2712 |
Mardin |
2y ago |
name: '', |
| 119 |
6aab6f0 |
Mrdn |
2y ago |
limit: pageSizeManagers.nodes.getPageSize(), |
| 120 |
5bb2712 |
Mardin |
2y ago |
sort: '-created_at', |
| 121 |
a47eb4c |
Dawsh |
2y ago |
}, |
| 122 |
5bb2712 |
Mardin |
2y ago |
onFilterChange: (filters) => { |
| 123 |
5bb2712 |
Mardin |
2y ago |
set({ |
| 124 |
5bb2712 |
Mardin |
2y ago |
nodesFilters: { |
| 125 |
5bb2712 |
Mardin |
2y ago |
...get().nodesFilters, |
| 126 |
5bb2712 |
Mardin |
2y ago |
...filters, |
| 127 |
5bb2712 |
Mardin |
2y ago |
}, |
| 128 |
5bb2712 |
Mardin |
2y ago |
}); |
| 129 |
5bb2712 |
Mardin |
2y ago |
get().refetchNodes(); |
| 130 |
5bb2712 |
Mardin |
2y ago |
}, |
| 131 |
5bb2712 |
Mardin |
2y ago |
addNode: async (body) => { |
| 132 |
5bb2712 |
Mardin |
2y ago |
return fetch('/nodes', { method: 'POST', body }).then(() => { get().refetchCertificate() }); |
| 133 |
5bb2712 |
Mardin |
2y ago |
}, |
| 134 |
5bb2712 |
Mardin |
2y ago |
refetchNodes: () => { |
| 135 |
16e5ea1 |
Mrdn |
2y ago |
queryClient.invalidateQueries({ queryKey: [queryIds.nodes] }); |
| 136 |
a47eb4c |
Dawsh |
2y ago |
}, |
| 137 |
5bb2712 |
Mardin |
2y ago |
refetchCertificate: () => { |
| 138 |
5bb2712 |
Mardin |
2y ago |
fetch('/nodes/settings').then((res) => { |
| 139 |
5bb2712 |
Mardin |
2y ago |
set({ certificate: res.certificate }); |
| 140 |
5bb2712 |
Mardin |
2y ago |
}) |
| 141 |
5bb2712 |
Mardin |
2y ago |
}, |
| 142 |
5bb2712 |
Mardin |
2y ago |
fetchNodesUsage: (query: FilterUsageType) => { |
| 143 |
bf7c131 |
Mardin |
2y ago |
return fetch('/nodes/usage', { query }); |
| 144 |
a47eb4c |
Dawsh |
2y ago |
}, |
| 145 |
5bb2712 |
Mardin |
2y ago |
updateNode: (body) => { |
| 146 |
5bb2712 |
Mardin |
2y ago |
console.log('update: ' + body.id) |
| 147 |
5bb2712 |
Mardin |
2y ago |
return fetch(`/nodes/${body.id}`, { |
| 148 |
bf7c131 |
Mardin |
2y ago |
method: 'PUT', |
| 149 |
a47eb4c |
Dawsh |
2y ago |
body, |
| 150 |
a47eb4c |
Dawsh |
2y ago |
}); |
| 151 |
a47eb4c |
Dawsh |
2y ago |
}, |
| 152 |
5bb2712 |
Mardin |
2y ago |
onDeletingNode: (node: NodeCreate | undefined) => { |
| 153 |
5bb2712 |
Mardin |
2y ago |
if (node !== undefined) { |
| 154 |
5bb2712 |
Mardin |
2y ago |
set({ deletingNode: node }); |
| 155 |
5bb2712 |
Mardin |
2y ago |
} |
| 156 |
5bb2712 |
Mardin |
2y ago |
else { |
| 157 |
5bb2712 |
Mardin |
2y ago |
set({ deletingNode: undefined }); |
| 158 |
5bb2712 |
Mardin |
2y ago |
} |
| 159 |
a47eb4c |
Dawsh |
2y ago |
}, |
| 160 |
5bb2712 |
Mardin |
2y ago |
reconnectNode: (body) => { |
| 161 |
5bb2712 |
Mardin |
2y ago |
return fetch(`/nodes/${body.id}/reconnect`, { |
| 162 |
bf7c131 |
Mardin |
2y ago |
method: 'POST', |
| 163 |
a47eb4c |
Dawsh |
2y ago |
}); |
| 164 |
a47eb4c |
Dawsh |
2y ago |
}, |
| 165 |
a47eb4c |
Dawsh |
2y ago |
deleteNode: () => { |
| 166 |
5bb2712 |
Mardin |
2y ago |
return fetch(`/nodes/${get().deletingNode?.id}`, { |
| 167 |
bf7c131 |
Mardin |
2y ago |
method: 'DELETE', |
| 168 |
a47eb4c |
Dawsh |
2y ago |
}); |
| 169 |
a47eb4c |
Dawsh |
2y ago |
}, |
| 170 |
5bb2712 |
Mardin |
2y ago |
onEditingNode: (editingNode: NodeType | undefined) => { |
| 171 |
5bb2712 |
Mardin |
2y ago |
if (editingNode !== undefined) { |
| 172 |
5bb2712 |
Mardin |
2y ago |
const { status, ...rest } = editingNode; |
| 173 |
5bb2712 |
Mardin |
2y ago |
set({ editingNode: { ...rest, status: (status === 'healthy' || status === 'unhealthy') ? 'none' : 'disabled' }, isEditingNode: true }); |
| 174 |
5bb2712 |
Mardin |
2y ago |
} |
| 175 |
5bb2712 |
Mardin |
2y ago |
else { |
| 176 |
5bb2712 |
Mardin |
2y ago |
set({ editingNode: undefined, isEditingNode: false }); |
| 177 |
5bb2712 |
Mardin |
2y ago |
|
| 178 |
5bb2712 |
Mardin |
2y ago |
} |
| 179 |
5bb2712 |
Mardin |
2y ago |
}, |
| 180 |
5bb2712 |
Mardin |
2y ago |
onAddingNode: (isAddingNode: boolean) => { |
| 181 |
5bb2712 |
Mardin |
2y ago |
set({ isAddingNode }); |
| 182 |
4205669 |
Mardin |
2y ago |
}, |
| 183 |
4205669 |
Mardin |
2y ago |
onShowingNodesUsage: (isShowingNodesUsage: boolean) => { |
| 184 |
4205669 |
Mardin |
2y ago |
set({ isShowingNodesUsage }); |
| 185 |
4205669 |
Mardin |
2y ago |
}, |
| 186 |
a47eb4c |
Dawsh |
2y ago |
})); |