This is an automated email from the ASF dual-hosted git repository.

baoyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 6fdcbb482 feat: improve empty state UX for service list (#3275)
6fdcbb482 is described below

commit 6fdcbb4820c8242cfe3a301d1866c1b4bfe5c158
Author: Baluduvamsi2006 <[email protected]>
AuthorDate: Fri Feb 27 13:43:14 2026 +0530

    feat: improve empty state UX for service list (#3275)
---
 e2e/tests/services.empty.spec.ts | 60 ++++++++++++++++++++++++++++++++++++++++
 src/locales/en/common.json       |  4 ++-
 src/routes/services/index.tsx    | 11 +++++++-
 3 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/e2e/tests/services.empty.spec.ts b/e2e/tests/services.empty.spec.ts
new file mode 100644
index 000000000..a616b18d6
--- /dev/null
+++ b/e2e/tests/services.empty.spec.ts
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { servicesPom } from '@e2e/pom/services';
+import { e2eReq } from '@e2e/utils/req';
+import { test } from '@e2e/utils/test';
+import { expect } from '@playwright/test';
+
+import { deleteAllServices } from '@/apis/services';
+
+test.describe('Services Empty State', () => {
+    test.describe.configure({ mode: 'serial' });
+
+    test.beforeAll(async () => {
+        await deleteAllServices(e2eReq);
+    });
+
+    test('should display custom empty state when no services exist', async ({ 
page }) => {
+        await test.step('navigate to services page', async () => {
+            await servicesPom.getServiceNavBtn(page).click();
+            await servicesPom.isIndexPage(page);
+        });
+
+        await test.step('verify empty state is displayed', async () => {
+            const table = page.getByRole('table');
+            await expect(table).toBeVisible();
+
+            const emptyDescription = page.getByText('No services found. Click 
Add Service to create your first one.');
+            await expect(emptyDescription).toBeVisible();
+
+            const emptyImage = page.locator('.ant-empty-image');
+            await expect(emptyImage).toBeVisible();
+        });
+
+        await test.step('verify no service rows are displayed', async () => {
+            const serviceRows = page.getByRole('cell', { name: /service_name_/ 
});
+            await expect(serviceRows).toHaveCount(0);
+        });
+
+        await test.step('verify add button is still accessible', async () => {
+            const addButton = servicesPom.getAddServiceBtn(page);
+            await expect(addButton).toBeVisible();
+            await expect(addButton).toBeEnabled();
+        });
+    });
+});
diff --git a/src/locales/en/common.json b/src/locales/en/common.json
index 8195d80c7..600379810 100644
--- a/src/locales/en/common.json
+++ b/src/locales/en/common.json
@@ -329,7 +329,9 @@
     "singular": "Secret"
   },
   "services": {
-    "singular": "Service"
+    "singular": "Service",
+    "empty": "No services found. Click Add Service to create your first one."
+
   },
   "settings": {
     "adminKey": "Admin Key",
diff --git a/src/routes/services/index.tsx b/src/routes/services/index.tsx
index 10fa740b2..ea5c5011f 100644
--- a/src/routes/services/index.tsx
+++ b/src/routes/services/index.tsx
@@ -17,13 +17,14 @@
 import type { ProColumns } from '@ant-design/pro-components';
 import { ProTable } from '@ant-design/pro-components';
 import { createFileRoute } from '@tanstack/react-router';
+import { Empty } from 'antd';
 import { useMemo } from 'react';
 import { useTranslation } from 'react-i18next';
 
 import { getServiceListQueryOptions, useServiceList } from '@/apis/hooks';
 import { DeleteResourceBtn } from '@/components/page/DeleteResourceBtn';
 import PageHeader from '@/components/page/PageHeader';
-import { ToAddPageBtn,ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
+import { ToAddPageBtn, ToDetailPageBtn } from '@/components/page/ToAddPageBtn';
 import { AntdConfigProvider } from '@/config/antdConfigProvider';
 import { API_SERVICES } from '@/config/constant';
 import { queryClient } from '@/config/global';
@@ -91,6 +92,14 @@ const ServiceList = () => {
   return (
     <AntdConfigProvider>
       <ProTable
+        locale={{
+          emptyText: (
+            <Empty
+              description={t('services.empty')}
+              image={Empty.PRESENTED_IMAGE_SIMPLE}
+            />
+          ),
+        }}
         columns={columns}
         dataSource={data.list}
         rowKey="id"

Reply via email to