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 77f5c126e fix(settings): save data sources without query credentials 
(#2657)
77f5c126e is described below

commit 77f5c126e65e8c66e7be8f66d41df0adaba71f10
Author: btlqql <[email protected]>
AuthorDate: Wed Sep 2 17:07:54 2026 +0800

    fix(settings): save data sources without query credentials (#2657)
---
 web/src/pages/settings/DataSourceTab.tsx           | 12 ++++++++-
 .../settings/__tests__/DataSourceTab.test.tsx      | 31 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/web/src/pages/settings/DataSourceTab.tsx 
b/web/src/pages/settings/DataSourceTab.tsx
index df7140bca..81fa9087d 100644
--- a/web/src/pages/settings/DataSourceTab.tsx
+++ b/web/src/pages/settings/DataSourceTab.tsx
@@ -99,6 +99,14 @@ const testFieldNames = (auth?: string) => {
   return ['type', 'url', 'auth'];
 };
 
+const saveFieldNames: (keyof DataSourceFormValues)[] = [
+  'name',
+  'type',
+  'url',
+  'auth',
+  'instanceIds',
+];
+
 const withoutSecrets = (values: DataSourceFormValues): Partial<DataSource> => {
   const sanitized = { ...values };
   secretFieldNames.forEach((field) => {
@@ -233,7 +241,9 @@ export const DataSourceTab = () => {
 
   const handleSubmit = async () => {
     try {
-      const values = await dsForm.validateFields();
+      // Credentials are supplied per metrics query and are only used here by 
the
+      // connection test. Saving metadata must not require re-entering them.
+      const values = await dsForm.validateFields(saveFieldNames);
       const dataSourceValues = withoutSecrets(values);
       setSubmitting(true);
       const saved = editingDataSource
diff --git a/web/src/pages/settings/__tests__/DataSourceTab.test.tsx 
b/web/src/pages/settings/__tests__/DataSourceTab.test.tsx
index ca3f1a5a8..68ba44bd0 100644
--- a/web/src/pages/settings/__tests__/DataSourceTab.test.tsx
+++ b/web/src/pages/settings/__tests__/DataSourceTab.test.tsx
@@ -25,6 +25,7 @@ import {
   listAllDataSources,
   listDataSourcesPage,
   testDataSource,
+  updateDataSource,
 } from '../../../api/settings';
 import { LangProvider } from '../../../i18n/LangContext';
 import { LANGUAGE_STORAGE_KEY } from '../../../i18n/languagePreference';
@@ -346,6 +347,36 @@ describe('DataSourceTab', () => {
     });
   });
 
+  it('updates authenticated data source metadata without requiring query 
credentials', async () => {
+    localStorage.setItem(LANGUAGE_STORAGE_KEY, 'en');
+    vi.mocked(updateDataSource).mockResolvedValue({
+      ...sources[1],
+      name: 'Thanos primary',
+    });
+    const user = userEvent.setup({ pointerEventsCheck: 0 });
+    render(
+      <App>
+        <DataSourceTab />
+      </App>,
+    );
+    await screen.findByText('Thanos DR');
+
+    const editButtons = screen.getAllByRole('button', { name: /edit/i });
+    await user.click(editButtons[1]);
+    const dialog = await screen.findByRole('dialog');
+    const nameInput = within(dialog).getByDisplayValue('Thanos DR');
+    await user.clear(nameInput);
+    await user.type(nameInput, 'Thanos primary');
+    await user.click(within(dialog).getByRole('button', { name: 'OK' }));
+
+    await waitFor(() =>
+      expect(updateDataSource).toHaveBeenCalledWith({
+        ...sources[1],
+        name: 'Thanos primary',
+      }),
+    );
+  });
+
   it('creates and tests a Grafana Mimir data source', async () => {
     vi.mocked(testDataSource).mockResolvedValue({ success: true, message: 'ok' 
});
     vi.mocked(createDataSource).mockResolvedValue({

Reply via email to