This is an automated email from the ASF dual-hosted git repository.
lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
The following commit(s) were added to refs/heads/rocketmq-studio by this push:
new 32607c3f fix: stop rendering mock consumer groups (#691)
32607c3f is described below
commit 32607c3ff624b523e8a4530272625219bd963f4d
Author: aias00 <[email protected]>
AuthorDate: Sun Aug 2 19:38:17 2026 -0700
fix: stop rendering mock consumer groups (#691)
---
web/src/i18n/translations.ts | 4 +
web/src/pages/studio/GroupManagement.tsx | 377 +--------------------
.../studio/__tests__/GroupManagement.test.tsx | 17 +-
3 files changed, 21 insertions(+), 377 deletions(-)
diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts
index 3074959b..321ba2e7 100644
--- a/web/src/i18n/translations.ts
+++ b/web/src/i18n/translations.ts
@@ -956,6 +956,10 @@ const translations: Record<string, Record<Lang, string>> =
{
'groupMgmt.stopped': { zh: '已停止', en: 'Stopped' },
'groupMgmt.createGroup': { zh: '创建消费组', en: 'Create Group' },
'groupMgmt.searchPlaceholder': { zh: '搜索消费组', en: 'Search group' },
+ 'groupMgmt.providerUnavailable': {
+ zh: '当前版本尚未接入真实消费组管理接口,已停止展示模拟消费组数据。',
+ en: 'The real consumer group management API is not connected yet, so mock
consumer group data is no longer displayed.',
+ },
'groupMgmt.manual': { zh: '手动', en: 'Manual' },
'groupMgmt.overview': { zh: '概览', en: 'Overview' },
'groupMgmt.totalDiff': { zh: '总堆积量', en: 'Total Diff' },
diff --git a/web/src/pages/studio/GroupManagement.tsx
b/web/src/pages/studio/GroupManagement.tsx
index 47102e16..0a648b04 100644
--- a/web/src/pages/studio/GroupManagement.tsx
+++ b/web/src/pages/studio/GroupManagement.tsx
@@ -21,16 +21,11 @@ import {
Button,
Input,
Tag,
- Modal,
- Tabs,
Card,
- Row,
- Col,
- Descriptions,
Space,
Switch,
} from 'antd';
-import { MagnifyingGlass, Plus, ArrowClockwise, Users, Eye } from
'@phosphor-icons/react';
+import { MagnifyingGlass, Plus, ArrowClockwise, Users } from
'@phosphor-icons/react';
import { useLang } from '../../i18n/LangContext';
// ─── Types ──────────────────────────────────────────────────────
@@ -46,187 +41,14 @@ interface GroupRecord {
status: 'running' | 'warning' | 'stopped';
}
-interface SubscriptionRecord {
- key: string;
- topic: string;
- consistency: 'consistent' | 'inconsistent';
- subMode: string;
- expression: string;
-}
-
-interface InstanceRecord {
- key: string;
- instanceId: string;
- address: string;
- version: string;
- status: string;
-}
-
-interface ProgressRecord {
- key: string;
- topic: string;
- queueId: string;
- brokerOffset: string;
- consumerOffset: string;
- diff: number;
-}
-
-// ─── Mock Data ──────────────────────────────────────────────────
-const groupData: GroupRecord[] = [
- {
- key: '1',
- group: 'order-consumer-group',
- namespace: 'default',
- cluster: 'cluster-production',
- count: 4,
- consumeType: 'PUSH',
- messageModel: 'CLUSTERING',
- diff: 1280,
- status: 'running',
- },
- {
- key: '2',
- group: 'payment-consumer-group',
- namespace: 'default',
- cluster: 'cluster-production',
- count: 2,
- consumeType: 'PUSH',
- messageModel: 'CLUSTERING',
- diff: 0,
- status: 'running',
- },
- {
- key: '3',
- group: 'inventory-sync-group',
- namespace: 'ns-warehouse',
- cluster: 'cluster-warehouse',
- count: 3,
- consumeType: 'PUSH',
- messageModel: 'CLUSTERING',
- diff: 56800,
- status: 'warning',
- },
- {
- key: '4',
- group: 'log-processor-group',
- namespace: 'default',
- cluster: 'cluster-production',
- count: 1,
- consumeType: 'PUSH',
- messageModel: 'BROADCASTING',
- diff: 0,
- status: 'running',
- },
- {
- key: '5',
- group: 'notification-group',
- namespace: 'ns-notify',
- cluster: 'cluster-production',
- count: 2,
- consumeType: 'PUSH',
- messageModel: 'CLUSTERING',
- diff: 3,
- status: 'running',
- },
-];
-
-const subscriptionData: SubscriptionRecord[] = [
- { key: '1', topic: 'ORDER_TOPIC', consistency: 'consistent', subMode: 'TAG',
expression: '*' },
- {
- key: '2',
- topic: 'PAYMENT_TOPIC',
- consistency: 'consistent',
- subMode: 'TAG',
- expression: 'pay_success || pay_fail',
- },
- {
- key: '3',
- topic: 'INVENTORY_TOPIC',
- consistency: 'inconsistent',
- subMode: 'TAG',
- expression: 'stock_update',
- },
-];
-
-const instanceData: InstanceRecord[] = [
- {
- key: '1',
- instanceId: 'cid-001',
- address: '10.0.1.10:10911',
- version: '5.3.0',
- status: 'online',
- },
- {
- key: '2',
- instanceId: 'cid-002',
- address: '10.0.1.11:10911',
- version: '5.3.0',
- status: 'online',
- },
- {
- key: '3',
- instanceId: 'cid-003',
- address: '10.0.1.12:10911',
- version: '5.3.0',
- status: 'online',
- },
- {
- key: '4',
- instanceId: 'cid-004',
- address: '10.0.1.13:10911',
- version: '5.3.0',
- status: 'online',
- },
-];
-
-const progressData: ProgressRecord[] = [
- {
- key: '1',
- topic: 'ORDER_TOPIC',
- queueId: '0',
- brokerOffset: '125,680',
- consumerOffset: '125,400',
- diff: 280,
- },
- {
- key: '2',
- topic: 'ORDER_TOPIC',
- queueId: '1',
- brokerOffset: '98,200',
- consumerOffset: '98,200',
- diff: 0,
- },
- {
- key: '3',
- topic: 'PAYMENT_TOPIC',
- queueId: '0',
- brokerOffset: '45,300',
- consumerOffset: '45,300',
- diff: 0,
- },
- {
- key: '4',
- topic: 'INVENTORY_TOPIC',
- queueId: '0',
- brokerOffset: '230,100',
- consumerOffset: '173,300',
- diff: 56800,
- },
-];
+const groupData: GroupRecord[] = [];
// ─── Component ──────────────────────────────────────────────────
const GroupManagementPage = () => {
const [searchText, setSearchText] = useState('');
- const [modalVisible, setModalVisible] = useState(false);
- const [selectedGroup, setSelectedGroup] = useState<string | null>(null);
const [autoRefresh, setAutoRefresh] = useState(false);
const { t } = useLang();
- const handleViewDetail = (groupName: string) => {
- setSelectedGroup(groupName);
- setModalVisible(true);
- };
-
const normalizedSearchText = searchText.trim().toLowerCase();
const filteredGroupData = groupData.filter(
(record) => !normalizedSearchText ||
record.group.toLowerCase().includes(normalizedSearchText),
@@ -238,9 +60,9 @@ const GroupManagementPage = () => {
dataIndex: 'group',
key: 'group',
render: (text: string) => (
- <a onClick={() => handleViewDetail(text)} style={{ color: '#1677ff',
fontWeight: 500 }}>
+ <span style={{ color: '#1677ff', fontWeight: 500 }}>
{text}
- </a>
+ </span>
),
},
{ title: t('groupMgmt.namespace'), dataIndex: 'namespace', key:
'namespace' },
@@ -293,12 +115,12 @@ const GroupManagementPage = () => {
{
title: t('common.actions'),
key: 'action',
- render: (_: unknown, record: GroupRecord) => (
+ render: () => (
<Space size="small">
- <Button type="link" size="small" onClick={() =>
handleViewDetail(record.group)}>
+ <Button type="link" size="small" disabled>
{t('common.detail')}
</Button>
- <Button type="link" size="small">
+ <Button type="link" size="small" disabled>
{t('brokerCluster.config')}
</Button>
</Space>
@@ -306,45 +128,6 @@ const GroupManagementPage = () => {
},
];
- const subscriptionColumns = [
- {
- title: t('groupMgmt.topic'),
- dataIndex: 'topic',
- key: 'topic',
- render: (text: string) => <span style={{ fontWeight: 500
}}>{text}</span>,
- },
- {
- title: t('groupMgmt.consistency'),
- dataIndex: 'consistency',
- key: 'consistency',
- render: (consistency: string) => (
- <Tag color={consistency === 'consistent' ? 'success' : 'warning'}>
- {consistency === 'consistent' ? t('groupMgmt.consistent') :
t('groupMgmt.inconsistent')}
- </Tag>
- ),
- },
- { title: t('groupMgmt.subMode'), dataIndex: 'subMode', key: 'subMode' },
- {
- title: t('groupMgmt.expression'),
- dataIndex: 'expression',
- key: 'expression',
- render: (text: string) => (
- <code style={{ background: '#f5f5f5', padding: '2px 6px',
borderRadius: 4, fontSize: 12 }}>
- {text}
- </code>
- ),
- },
- {
- title: t('common.actions'),
- key: 'action',
- render: () => (
- <Button type="link" size="small" icon={<Eye size={14} />}>
- {t('groupMgmt.viewDistribution')}
- </Button>
- ),
- },
- ];
-
return (
<div style={{ padding: 0 }}>
<div
@@ -396,6 +179,7 @@ const GroupManagementPage = () => {
<Table
columns={columns}
dataSource={filteredGroupData}
+ locale={{ emptyText: t('groupMgmt.providerUnavailable') }}
pagination={{
pageSize: 10,
showTotal: (total) => `${t('common.total')} ${total} Group`,
@@ -404,151 +188,6 @@ const GroupManagementPage = () => {
size="middle"
/>
</Card>
-
- <Modal
- title={null}
- open={modalVisible}
- onCancel={() => setModalVisible(false)}
- footer={null}
- width={720}
- destroyOnClose
- >
- <div style={{ marginBottom: 16 }}>
- <h3 style={{ margin: 0, display: 'flex', alignItems: 'center' }}>
- <Users size={18} style={{ marginRight: 8, color: '#1677ff' }} />
- {selectedGroup}
- </h3>
- </div>
- <Tabs
- defaultActiveKey="overview"
- items={[
- {
- key: 'overview',
- label: t('groupMgmt.overview'),
- children: (
- <div>
- <Row gutter={16} style={{ marginBottom: 20 }}>
- <Col span={8}>
- <Card bordered={false} style={{ background: '#f6ffed' }}>
- <div style={{ color: '#666', fontSize: 12 }}>
- {t('groupMgmt.onlineInstances')}
- </div>
- <div style={{ fontSize: 24, fontWeight: 600 }}>
- 4{' '}
- <Tag color="success" style={{ marginLeft: 8 }}>
- {t('groupMgmt.online')}
- </Tag>
- </div>
- </Card>
- </Col>
- <Col span={8}>
- <Card bordered={false} style={{ background: '#fff2f0' }}>
- <div style={{ color: '#666', fontSize: 12 }}>
- {t('groupMgmt.totalDiff')}
- </div>
- <div style={{ fontSize: 24, fontWeight: 600, color:
'#ff4d4f' }}>1,280</div>
- </Card>
- </Col>
- <Col span={8}>
- <Card bordered={false} style={{ background: '#f0f5ff' }}>
- <div style={{ color: '#666', fontSize: 12 }}>
- {t('groupMgmt.subscribedTopics')}
- </div>
- <div style={{ fontSize: 24, fontWeight: 600 }}>3</div>
- </Card>
- </Col>
- </Row>
- <Descriptions column={2} bordered size="small">
- <Descriptions.Item label={t('groupMgmt.groupName')}>
- order-consumer-group
- </Descriptions.Item>
- <Descriptions.Item
label={t('groupMgmt.namespace')}>default</Descriptions.Item>
- <Descriptions.Item label={t('groupMgmt.cluster')}>
- cluster-production
- </Descriptions.Item>
- <Descriptions.Item label={t('groupMgmt.consumeMode')}>
- <Tag color="blue">{t('groupMgmt.clustering')}</Tag>
- </Descriptions.Item>
- <Descriptions.Item
label={t('groupMgmt.consumeType')}>PUSH</Descriptions.Item>
- <Descriptions.Item
label={t('groupMgmt.consumeDelay')}>12ms</Descriptions.Item>
- <Descriptions.Item
label={t('groupMgmt.maxRetry')}>16</Descriptions.Item>
- <Descriptions.Item label={t('groupMgmt.createdAt')}>
- 2025-03-15 10:30:00
- </Descriptions.Item>
- <Descriptions.Item label={t('groupMgmt.subscribedTopics')}
span={2}>
- ORDER_TOPIC, PAYMENT_TOPIC, INVENTORY_TOPIC
- </Descriptions.Item>
- </Descriptions>
- <h4 style={{ marginTop: 20, marginBottom: 12
}}>{t('groupMgmt.subscription')}</h4>
- <Table
- columns={subscriptionColumns}
- dataSource={subscriptionData}
- pagination={false}
- size="small"
- />
- </div>
- ),
- },
- {
- key: 'instances',
- label: t('groupMgmt.onlineInstances'),
- children: (
- <Table
- columns={[
- {
- title: t('groupMgmt.instanceId'),
- dataIndex: 'instanceId',
- key: 'instanceId',
- },
- { title: t('common.address'), dataIndex: 'address', key:
'address' },
- { title: t('brokerCluster.version'), dataIndex: 'version',
key: 'version' },
- {
- title: t('brokerCluster.status'),
- dataIndex: 'status',
- key: 'status',
- render: () => <Tag
color="success">{t('groupMgmt.online')}</Tag>,
- },
- ]}
- dataSource={instanceData}
- pagination={false}
- size="small"
- />
- ),
- },
- {
- key: 'progress',
- label: t('groupMgmt.consumeProgress'),
- children: (
- <Table
- columns={[
- { title: 'Topic', dataIndex: 'topic', key: 'topic' },
- { title: 'QueueId', dataIndex: 'queueId', key: 'queueId' },
- { title: 'Broker Offset', dataIndex: 'brokerOffset', key:
'brokerOffset' },
- {
- title: 'Consumer Offset',
- dataIndex: 'consumerOffset',
- key: 'consumerOffset',
- },
- {
- title: 'Diff',
- dataIndex: 'diff',
- key: 'diff',
- render: (v: number) => (
- <span style={{ color: v > 100 ? '#ff4d4f' : '#52c41a',
fontWeight: 500 }}>
- {v}
- </span>
- ),
- },
- ]}
- dataSource={progressData}
- pagination={false}
- size="small"
- />
- ),
- },
- ]}
- />
- </Modal>
</div>
);
};
diff --git a/web/src/pages/studio/__tests__/GroupManagement.test.tsx
b/web/src/pages/studio/__tests__/GroupManagement.test.tsx
index 3b93a966..05d48695 100644
--- a/web/src/pages/studio/__tests__/GroupManagement.test.tsx
+++ b/web/src/pages/studio/__tests__/GroupManagement.test.tsx
@@ -74,24 +74,25 @@ describe('GroupManagement Page', () => {
expect(screen.getByText('重置')).toBeInTheDocument();
});
- it('should display mock consumer group data in table', () => {
+ it('should show an explicit unavailable state instead of mock consumer
groups', () => {
renderWithProviders(<GroupManagement />);
- expect(screen.getByText('order-consumer-group')).toBeInTheDocument();
- expect(screen.getByText('payment-consumer-group')).toBeInTheDocument();
+
expect(screen.getByText('当前版本尚未接入真实消费组管理接口,已停止展示模拟消费组数据。')).toBeInTheDocument();
+ expect(screen.queryByText('order-consumer-group')).not.toBeInTheDocument();
+
expect(screen.queryByText('payment-consumer-group')).not.toBeInTheDocument();
});
- it('should render detail action buttons for each row', () => {
+ it('should not render row actions without real consumer group data', () => {
renderWithProviders(<GroupManagement />);
- const detailButtons = screen.getAllByText('详情');
- expect(detailButtons.length).toBeGreaterThan(0);
+ expect(screen.queryByText('详情')).not.toBeInTheDocument();
});
- it('should filter groups by search text', async () => {
+ it('should keep mock groups hidden when filtering by search text', async ()
=> {
const user = userEvent.setup();
renderWithProviders(<GroupManagement />);
const searchInput = screen.getByPlaceholderText('搜索消费组');
await user.type(searchInput, 'ORDER');
- expect(screen.getByText('order-consumer-group')).toBeInTheDocument();
+
expect(screen.getByText('当前版本尚未接入真实消费组管理接口,已停止展示模拟消费组数据。')).toBeInTheDocument();
+ expect(screen.queryByText('order-consumer-group')).not.toBeInTheDocument();
expect(screen.queryByText('payment-consumer-group')).not.toBeInTheDocument();
});
});