Skip to content

Commit 558f7bc

Browse files
committed
feat(nodes): add loading state, no-nodes guidance, and fix search functionality of logs
1 parent eeb9231 commit 558f7bc

File tree

6 files changed

+52
-6
lines changed

6 files changed

+52
-6
lines changed

dashboard/public/statics/locales/en.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
"certificateDownloaded": "Certificate downloaded successfully",
5858
"certificateDescription": "To set up the node, you need to configure this certificate to establish a secure connection between the main server and the node",
5959
"selectNode": "Select a node",
60+
"noNodes": "No nodes configured",
61+
"noNodesDescription": "Master Panel doesn't have any cores configured. You need to add and configure a node from",
62+
"noNodesDescription2": "and connect it to the panel.",
6063
"logs": {
6164
"title": "Logs",
6265
"description": "View and monitor node logs",
@@ -516,8 +519,8 @@
516519
"admin.disable": "Disabled Admin",
517520
"admin.enable": "Enabled Admin",
518521
"deleteAdmin.prompt": "Are you sure you want to remove the <b>{{name}}</b> admin?",
519-
"activeUsers.prompt": "Do you want to activate all users under this {{name}}?",
520-
"disableUsers.prompt": "Do you want to disable all users under this {{name}}?",
522+
"activeUsers.prompt": "Do you want to activate all users under {{name}}?",
523+
"disableUsers.prompt": "Do you want to disable all users under {{name}}?",
521524
"manageAccounts": "Control, Update, and Arrange User Accounts",
522525
"manageGroups": "Control, Update, and Arrange User Groups",
523526
"manageNodes": "Monitor, control, create, modify, remove nodes",

dashboard/public/statics/locales/fa.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,9 @@
10911091
"certificateDownloaded": "گواهینامه با موفقیت دانلود شد",
10921092
"certificateDescription": "برای تنظیم گره، باید این گواهینامه را برای برقراری ارتباط امن بین سرور اصلی و گره پیکربندی کنید",
10931093
"selectNode": "یک گره انتخاب کنید",
1094+
"noNodes": "هیچ گره ای پیکربندی نشده",
1095+
"noNodesDescription": "پنل اصلی هیچ هسته‌ای ندارد. شما باید یک گره از",
1096+
"noNodesDescription2": "اضافه و پیکربندی کنید و آن را به پنل متصل کنید.",
10941097
"logs": {
10951098
"title": "لاگ‌ها",
10961099
"description": "مشاهده و نظارت بر لاگ‌های گره‌ها",

dashboard/public/statics/locales/ru.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@
7070
"certificateDownloaded": "Сертификат успешно загружен",
7171
"certificateDescription": "Для настройки узла необходимо настроить этот сертификат для установки безопасного соединения между основным сервером и узлом",
7272
"selectNode": "Выберите узел",
73+
"noNodes": "Узлы не настроены",
74+
"noNodesDescription": "Главная панель не имеет настроенных ядер. Вам нужно добавить и настроить узел из",
75+
"noNodesDescription2": "и подключить его к панели.",
7376
"logs": {
7477
"title": "Журналы",
7578
"description": "Просмотр и мониторинг журналов узла",

dashboard/public/statics/locales/zh.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
"certificate": "证书",
5353
"createdAt": "创建时间",
5454
"selectNode": "选择节点",
55+
"noNodes": "未配置节点",
56+
"noNodesDescription": "主面板没有配置任何核心。您需要从",
57+
"noNodesDescription2": "添加和配置节点,并将其连接到面板。",
5558
"logs": {
5659
"title": "日志",
5760
"description": "查看和监控节点日志",

dashboard/src/components/nodes/Nodes.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import NodeModal from '@/components/dialogs/NodeModal'
88
import { useForm } from 'react-hook-form'
99
import { zodResolver } from '@hookform/resolvers/zod'
1010
import { nodeFormSchema, NodeFormValues } from '@/components/dialogs/NodeModal'
11+
import { Card, CardContent } from '@/components/ui/card'
12+
import { LoadingSpinner } from '@/components/LoadingSpinner'
1113

1214
const initialDefaultValues: Partial<NodeFormValues> = {
1315
name: '',
@@ -26,7 +28,7 @@ export default function Nodes() {
2628
const [editingNode, setEditingNode] = useState<NodeResponse | null>(null)
2729
const modifyNodeMutation = useModifyNode()
2830

29-
const { data: nodesData } = useGetNodes(undefined, {
31+
const { data: nodesData, isLoading } = useGetNodes(undefined, {
3032
query: {
3133
refetchInterval: 5000,
3234
refetchIntervalInBackground: true,
@@ -101,6 +103,10 @@ export default function Nodes() {
101103
}
102104
}
103105

106+
if (isLoading) {
107+
return <LoadingSpinner />
108+
}
109+
104110
return (
105111
<div className="flex flex-col gap-2 w-full items-start">
106112
<div className="flex-1 space-y-4 pt-6 w-full">
@@ -111,6 +117,28 @@ export default function Nodes() {
111117
{nodesData?.map(node => <Node key={node.id} node={node} onEdit={handleEdit} onToggleStatus={handleToggleStatus} />)}
112118
</div>
113119

120+
{(!nodesData || nodesData.length === 0) && (
121+
<Card className="mb-12">
122+
<CardContent className="p-8 text-center">
123+
<div className="space-y-4">
124+
<h3 className="text-lg font-semibold">{t('nodes.noNodes')}</h3>
125+
<p className="text-muted-foreground max-w-2xl mx-auto">
126+
{t('nodes.noNodesDescription')}{' '}
127+
<a
128+
href="https://github.com/PasarGuard/node"
129+
target="_blank"
130+
rel="noopener noreferrer"
131+
className="text-primary underline-offset-4 hover:underline font-medium"
132+
>
133+
PasarGuard/node
134+
</a>{' '}
135+
{t('nodes.noNodesDescription2', { defaultValue: 'and connect it to the panel.' })}
136+
</p>
137+
</div>
138+
</CardContent>
139+
</Card>
140+
)}
141+
114142
<NodeModal
115143
isDialogOpen={isDialogOpen}
116144
onOpenChange={open => {

dashboard/src/pages/_dashboard.nodes.logs.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,17 @@ export default function NodeLogs() {
219219
return logs.filter((log) => {
220220
const logType = getLogType(log.message).type;
221221

222-
if (typeFilter.length === 0) {
223-
return true;
222+
// Filter by type
223+
if (typeFilter.length > 0 && !typeFilter.includes(logType)) {
224+
return false;
224225
}
225226

226-
return typeFilter.includes(logType);
227+
// Filter by search term
228+
if (search && !log.message.toLowerCase().includes(search.toLowerCase())) {
229+
return false;
230+
}
231+
232+
return true;
227233
});
228234
};
229235

0 commit comments

Comments
 (0)