diff --git a/app/dashboard/index.html b/app/dashboard/index.html index 4fc5208..c21c605 100644 --- a/app/dashboard/index.html +++ b/app/dashboard/index.html @@ -1,41 +1,26 @@ - - - - - Marzban - - - - - - - - - - - - - -
- - + + + + + + Marzneshin + + + + + + + + + + + + + + +
+ + + diff --git a/app/dashboard/public/locales/en.json b/app/dashboard/public/locales/en.json index 75ce0b0..db20623 100644 --- a/app/dashboard/public/locales/en.json +++ b/app/dashboard/public/locales/en.json @@ -86,6 +86,10 @@ "port": "Port", "total": "Total" }, + "noInboundsCallout": { + "header": "Configure Nodes!", + "body": "Please configure nodes to access inbounds hosts" + }, "userDialog": { "dataLimit": "Data Limit", "periodicUsageReset": "Periodic Usage Reset", @@ -204,12 +208,16 @@ "host.wildcard": "Use * to generate a random string (works for wildcard domain names)" }, "revoke": "Revoke", - "deleteNode.title": "Delete Node", - "deleteNode.prompt": "Are you sure you want to delete the {{name}} node?", - "deleteNode.deleteSuccess": "Node {{name}} removed successfully", - "deleteService.title": "Delete Service", - "deleteService.prompt": "Are you sure you want to delete the {{name}} node?", - "deleteService.deleteSuccess": "Service {{name}} removed successfully", + "deleteNode": { + "title": "Delete Node", + "prompt": "Are you sure you want to delete the {{name}} node?", + "deleteSuccess": "Node {{name}} removed successfully" + }, + "deleteService": { + "title": "Delete Service", + "prompt": "Are you sure you want to delete the {{name}} node?", + "deleteSuccess": "Service {{name}} removed successfully" + }, "users": "Users", "active": "active", "disabled": "disabled", diff --git a/app/dashboard/src/components/callout/index.tsx b/app/dashboard/src/components/callout/index.tsx new file mode 100644 index 0000000..5cdae9e --- /dev/null +++ b/app/dashboard/src/components/callout/index.tsx @@ -0,0 +1,20 @@ + + +import { Box, ChakraProps, Text } from '@chakra-ui/react' +import { FC } from 'react' + +type CalloutProps = { + header: string, + body: string, +}; + +export const Callout: FC = ({ header, body, ...props }) => { + return ( + + + {header} + + {body} + + ) +} diff --git a/app/dashboard/src/pages/hosts/container.tsx b/app/dashboard/src/pages/hosts/container.tsx index cf67977..aafaf0f 100644 --- a/app/dashboard/src/pages/hosts/container.tsx +++ b/app/dashboard/src/pages/hosts/container.tsx @@ -5,6 +5,8 @@ import { queryIds } from 'constants/query-ids'; import { useQuery } from '@tanstack/react-query'; import { fetchInbounds, fetchInboundHosts, useInbounds } from 'stores'; import { Grid, GridItem, } from '@chakra-ui/react'; +import { useTranslation } from 'react-i18next'; +import { Callout } from 'components/callout'; export const InboundsHostsManager = () => { const { selectedInbound } = useInbounds(); @@ -25,21 +27,26 @@ export const InboundsHostsManager = () => { } }); - return ( - <> - - - - - - - - - - - ) + const { t } = useTranslation('noInboundsCallout'); + + return inbounds.length === 0 ? + + : ( + <> + + + + + + + + + + + + ) } diff --git a/app/dashboard/src/pages/hosts/dialog/default-values.ts b/app/dashboard/src/pages/hosts/dialog/default-values.ts index e9df7b1..f6627cc 100644 --- a/app/dashboard/src/pages/hosts/dialog/default-values.ts +++ b/app/dashboard/src/pages/hosts/dialog/default-values.ts @@ -3,7 +3,7 @@ export const getDefaultValues = (): HostSchema => { return { host: '', sni: '', - port: 1, + port: null, path: '', address: '', remark: '', diff --git a/app/dashboard/src/pages/hosts/dialog/index.tsx b/app/dashboard/src/pages/hosts/dialog/index.tsx index fefaffe..4ff37ab 100644 --- a/app/dashboard/src/pages/hosts/dialog/index.tsx +++ b/app/dashboard/src/pages/hosts/dialog/index.tsx @@ -104,7 +104,7 @@ export const HostsDialog: FC = () => { .then(() => { toast({ title: t( - isEditingHost ? 'hostsDialog.editHost' : 'hostsDialog.createNewHost', + isEditingHost ? 'hostsDialog.editHost' : 'hostsDialog.createHost', { hoshtName: values.host } ), status: 'success', diff --git a/app/dashboard/src/pages/hosts/inbounds-sidebar/index.tsx b/app/dashboard/src/pages/hosts/inbounds-sidebar/index.tsx index 41cb365..1f9736d 100644 --- a/app/dashboard/src/pages/hosts/inbounds-sidebar/index.tsx +++ b/app/dashboard/src/pages/hosts/inbounds-sidebar/index.tsx @@ -4,6 +4,7 @@ import { InboundCard } from 'components/inbounds-card'; import { handleSort } from 'components/table'; import { FC } from 'react'; import { useTranslation } from 'react-i18next'; +import { useEffect } from 'react'; import { useInbounds } from 'stores'; import { InboundType } from 'types'; @@ -22,6 +23,9 @@ export const InboundsSidebar: FC = ({ refetchHosts, } = useInbounds(); + useEffect(() => { + selectedInbound === undefined && selectInbound(inbounds[0]); + }, [selectedInbound, inbounds]); const { t } = useTranslation(); diff --git a/app/dashboard/src/pages/nodes/dialog.tsx b/app/dashboard/src/pages/nodes/dialog.tsx index c435760..738da0a 100644 --- a/app/dashboard/src/pages/nodes/dialog.tsx +++ b/app/dashboard/src/pages/nodes/dialog.tsx @@ -210,7 +210,6 @@ export const NodesDialog: FC = () => { aria-label="delete node" onClick={() => { if (editingNode !== null) { - console.log('deleting') onDeletingNode(editingNode); onClose(); } diff --git a/app/dashboard/src/stores/inbounds.store.ts b/app/dashboard/src/stores/inbounds.store.ts index ef112f7..7b6974b 100644 --- a/app/dashboard/src/stores/inbounds.store.ts +++ b/app/dashboard/src/stores/inbounds.store.ts @@ -14,7 +14,8 @@ export const hostSchema = z.object({ address: z.string().min(1, 'Address is required'), port: z.coerce.number() .gte(1, 'Port must be more than 1') - .lte(65535, 'Port can not be more than 65535'), + .lte(65535, 'Port can not be more than 65535') + .or(z.string().nullable()), path: z.string(), sni: z.string(), host: z.string(), @@ -136,6 +137,7 @@ export const useInbounds = create( .catch(() => false) .finally(() => { useDashboard.setState({ loading: false }); + get().refetchHosts(); }); } }, @@ -150,6 +152,7 @@ export const useInbounds = create( .catch(() => false) .finally(() => { useDashboard.setState({ loading: false }); + get().refetchHosts(); }); } }, @@ -159,7 +162,10 @@ export const useInbounds = create( deleteHost: async (hostId: number): Promise => { useDashboard.setState({ loading: true }); return fetch(`/inbounds/hosts/${hostId}`, { method: 'DELETE' }) - .then(() => true) + .then(() => { + get().refetchHosts(); + return true; + }) .catch(() => false) .finally(() => { useDashboard.setState({ loading: false }); diff --git a/makefile b/makefile index 053e7a4..7e31509 100644 --- a/makefile +++ b/makefile @@ -14,16 +14,15 @@ dashboard-dev: VITE_BASE_API=http://0.0.0.0:8000/api/ npm run dev \ --prefix './app/dashboard/' \ -- --host 0.0.0.0 \ - --base ./app/dashboard/ \ + --base /dashboard/ \ --clearScreen false dashboard-preview: VITE_BASE_API=http://0.0.0.0:8000/api/ npm run preview \ --prefix './app/dashboard/' \ -- --host 0.0.0.0 \ - --base ./app/dashboard/ \ + --base /dashboard/ \ --clearScreen false - dashboard-cleanup: rm -rf app/dashboard/node_modules/