gitscope
https://dev.kronoz.win/r/marzneshin.git
app/dashboard/src/stores/nodes.store.ts · v0.1.4
Source
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 }));