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

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


The following commit(s) were added to refs/heads/master by this push:
     new 649bd45b fix(auth): preserve AppAuth filters during reload (#705)
649bd45b is described below

commit 649bd45bd0a1609b09d4b32c9c90b85544515a72
Author: Kazi Rezoanur Rahman <[email protected]>
AuthorDate: Tue Oct 13 08:16:50 2026 +0200

    fix(auth): preserve AppAuth filters during reload (#705)
    
    * fix(auth): preserve AppAuth filters during reload
    
    Reload now forwards `appKey` and `phone` with the active page size.
    Mutation refreshes use the model reload as the single fetch path.
    Removed the hardcoded 20-row page size and added regression coverage.
    `npm test` and `npm run lint` pass.
    
    Closes #624
    
    * fix(auth): guard optional callbacks in auth effects
---
 src/models/auth.js                      |  44 ++++++++---
 src/routes/System/AppAuth/index.js      |  92 +++++++++--------------
 src/routes/System/AppAuth/index.test.js | 126 ++++++++++++++++++++++++++++++++
 3 files changed, 191 insertions(+), 71 deletions(-)

diff --git a/src/models/auth.js b/src/models/auth.js
index 243b87f8..864b98b0 100644
--- a/src/models/auth.js
+++ b/src/models/auth.js
@@ -65,7 +65,9 @@ export default {
       const json = yield call(findAuthData, payload);
       if (json.code === 200) {
         const auth = json.data;
-        callback(auth);
+        if (typeof callback === "function") {
+          callback(auth);
+        }
       }
     },
     *fetchItemDel(params, { call }) {
@@ -73,7 +75,9 @@ export default {
       const json = yield call(findAuthDataDel, payload);
       if (json.code === 200) {
         const auth = json.data;
-        callback({ auth });
+        if (typeof callback === "function") {
+          callback({ auth });
+        }
       }
     },
     *fetchMeta(params, { call }) {
@@ -89,14 +93,18 @@ export default {
           };
           return item;
         });
-        callback({ dataList });
+        if (typeof callback === "function") {
+          callback({ dataList });
+        }
       }
     },
     *fetchMetaGroup(params, { call }) {
       const { payload, callback } = params;
       const json = yield call(getfetchMetaGroup, payload);
       if (json.code === 200) {
-        callback(json.data);
+        if (typeof callback === "function") {
+          callback(json.data);
+        }
       }
     },
     *add(params, { call, put }) {
@@ -104,7 +112,9 @@ export default {
       const json = yield call(addAuthData, payload);
       if (json.code === 200) {
         message.success(getIntlContent("SHENYU.COMMON.RESPONSE.ADD.SUCCESS"));
-        callback();
+        if (typeof callback === "function") {
+          callback();
+        }
         yield put({ type: "reload", fetchValue });
       } else {
         message.warn(json.message);
@@ -118,7 +128,9 @@ export default {
         message.success(
           getIntlContent("SHENYU.COMMON.RESPONSE.DELETE.SUCCESS"),
         );
-        callback();
+        if (typeof callback === "function") {
+          callback();
+        }
         yield put({ type: "reload", fetchValue });
       } else {
         message.warn(json.message);
@@ -132,7 +144,9 @@ export default {
         message.success(
           getIntlContent("SHENYU.COMMON.RESPONSE.UPDATE.SUCCESS"),
         );
-        callback();
+        if (typeof callback === "function") {
+          callback();
+        }
         yield put({ type: "reload", fetchValue });
       } else {
         message.warn(json.message);
@@ -145,7 +159,9 @@ export default {
         message.success(
           getIntlContent("SHENYU.COMMON.RESPONSE.UPDATE.SUCCESS"),
         );
-        callback();
+        if (typeof callback === "function") {
+          callback();
+        }
         yield put({ type: "reload", fetchValue });
       } else {
         message.warn(json.message);
@@ -153,8 +169,8 @@ export default {
     },
     *reload(params, { put }) {
       const { fetchValue } = params;
-      const { name, currentPage, pageSize, namespaceId } = fetchValue;
-      const payload = { name, currentPage, pageSize, namespaceId };
+      const { appKey, phone, currentPage, pageSize, namespaceId } = fetchValue;
+      const payload = { appKey, phone, currentPage, pageSize, namespaceId };
       yield put({ type: "fetch", payload });
     },
     *updateEn(params, { call, put }) {
@@ -164,7 +180,9 @@ export default {
         message.success(
           getIntlContent("SHENYU.COMMON.RESPONSE.UPDATE.SUCCESS"),
         );
-        callback();
+        if (typeof callback === "function") {
+          callback();
+        }
         yield put({ type: "reload", fetchValue });
       } else {
         message.warn(json.message);
@@ -177,7 +195,9 @@ export default {
         message.success(
           getIntlContent("SHENYU.COMMON.RESPONSE.UPDATE.SUCCESS"),
         );
-        callback();
+        if (typeof callback === "function") {
+          callback();
+        }
         yield put({ type: "reload", fetchValue });
       } else {
         message.warn(json.message);
diff --git a/src/routes/System/AppAuth/index.js 
b/src/routes/System/AppAuth/index.js
index 343c9199..6f4c4e77 100644
--- a/src/routes/System/AppAuth/index.js
+++ b/src/routes/System/AppAuth/index.js
@@ -83,34 +83,32 @@ export default class Auth extends Component {
     this.setState({ selectedRowKeys }, this.query);
   };
 
+  currentQueryPayload = (currentPage = this.state.currentPage) => {
+    const { currentNamespaceId } = this.props;
+    const { appKey, phone, pageSize } = this.state;
+    return {
+      appKey,
+      phone,
+      currentPage,
+      pageSize,
+      namespaceId: currentNamespaceId,
+    };
+  };
+
   query = () => {
-    const { dispatch, currentNamespaceId } = this.props;
-    const { appKey, phone, currentPage, pageSize } = this.state;
+    const { dispatch } = this.props;
     dispatch({
       type: "auth/fetch",
-      payload: {
-        appKey,
-        phone,
-        currentPage,
-        pageSize,
-        namespaceId: currentNamespaceId,
-      },
+      payload: this.currentQueryPayload(),
     });
   };
 
   // eslint-disable-next-line react/no-unused-class-component-methods
   getAllAuths = (page) => {
-    const { dispatch, currentNamespaceId } = this.props;
-    const { appKey, phone, pageSize } = this.state;
+    const { dispatch } = this.props;
     dispatch({
       type: "auth/fetch",
-      payload: {
-        appKey,
-        phone,
-        currentPage: page,
-        pageSize,
-        namespaceId: currentNamespaceId,
-      },
+      payload: this.currentQueryPayload(page),
     });
   };
 
@@ -122,10 +120,7 @@ export default class Auth extends Component {
     this.setState({ currentPage: 1, pageSize }, this.query);
   };
 
-  closeModal = (refresh) => {
-    if (refresh) {
-      this.setState({ popup: "" }, this.query);
-    }
+  closeModal = () => {
     this.setState({ popup: "" });
   };
 
@@ -150,13 +145,9 @@ export default class Auth extends Component {
                     ...values,
                     namespaceId: currentNamespaceId,
                   },
-                  fetchValue: {
-                    currentPage,
-                    pageSize: 20,
-                    namespaceId: currentNamespaceId,
-                  },
+                  fetchValue: this.currentQueryPayload(currentPage),
                   callback: () => {
-                    this.closeModal(true);
+                    this.closeModal();
                   },
                 });
               }}
@@ -172,7 +163,7 @@ export default class Auth extends Component {
 
   editClickMeta = (record) => {
     const { currentPage } = this.state;
-    const { dispatch, currentNamespaceId } = this.props;
+    const { dispatch } = this.props;
     dispatch({
       type: "auth/fetchItemDel",
       payload: {
@@ -205,13 +196,9 @@ export default class Auth extends Component {
                     dispatch({
                       type: "auth/updateDel",
                       payload: values,
-                      fetchValue: {
-                        currentPage,
-                        pageSize: 20,
-                        namespaceId: currentNamespaceId,
-                      },
+                      fetchValue: this.currentQueryPayload(currentPage),
                       callback: () => {
-                        this.closeModal(true);
+                        this.closeModal();
                       },
                     });
                   }}
@@ -232,7 +219,7 @@ export default class Auth extends Component {
   };
 
   deleteClick = () => {
-    const { dispatch, currentNamespaceId } = this.props;
+    const { dispatch } = this.props;
     const { selectedRowKeys } = this.state;
     if (selectedRowKeys && selectedRowKeys.length > 0) {
       dispatch({
@@ -240,11 +227,9 @@ export default class Auth extends Component {
         payload: {
           list: selectedRowKeys,
         },
-        fetchValue: {
-          namespaceId: currentNamespaceId,
-        },
+        fetchValue: this.currentQueryPayload(1),
         callback: () => {
-          this.setState({ selectedRowKeys: [], currentPage: 1 }, this.query);
+          this.setState({ selectedRowKeys: [], currentPage: 1 });
         },
       });
     } else {
@@ -256,7 +241,6 @@ export default class Auth extends Component {
   // 添加表格数据事件
 
   addClick = () => {
-    const { currentPage } = this.state;
     const { dispatch, currentNamespaceId } = this.props;
     dispatch({
       type: "auth/fetchMetaGroup",
@@ -270,14 +254,10 @@ export default class Auth extends Component {
                 dispatch({
                   type: "auth/add",
                   payload: { ...values, namespaceId: currentNamespaceId },
-                  fetchValue: {
-                    currentPage,
-                    pageSize: 20,
-                    namespaceId: currentNamespaceId,
-                  },
+                  fetchValue: this.currentQueryPayload(1),
                   callback: () => {
                     this.setState({ selectedRowKeys: [], currentPage: 1 });
-                    this.closeModal(true);
+                    this.closeModal();
                   },
                 });
               }}
@@ -292,16 +272,14 @@ export default class Auth extends Component {
   };
 
   openSwitch = ({ list, enabled, callback }) => {
-    const { dispatch, currentNamespaceId } = this.props;
+    const { dispatch } = this.props;
     dispatch({
       type: "auth/updateOp",
       payload: {
         list,
         enabled,
       },
-      fetchValue: {
-        namespaceId: currentNamespaceId,
-      },
+      fetchValue: this.currentQueryPayload(),
       callback,
     });
   };
@@ -320,7 +298,7 @@ export default class Auth extends Component {
             list: selectedRowKeys,
             enabled: !user.open,
             callback: () => {
-              this.setState({ selectedRowKeys: [] }, this.query);
+              this.setState({ selectedRowKeys: [] });
             },
           });
         },
@@ -332,16 +310,14 @@ export default class Auth extends Component {
   };
 
   statusSwitch = ({ list, enabled, callback }) => {
-    const { dispatch, currentNamespaceId } = this.props;
+    const { dispatch } = this.props;
     dispatch({
       type: "auth/updateEn",
       payload: {
         list,
         enabled,
       },
-      fetchValue: {
-        namespaceId: currentNamespaceId,
-      },
+      fetchValue: this.currentQueryPayload(),
       callback,
     });
   };
@@ -360,7 +336,7 @@ export default class Auth extends Component {
             list: selectedRowKeys,
             enabled: !user.enabled,
             callback: () => {
-              this.setState({ selectedRowKeys: [] }, this.query);
+              this.setState({ selectedRowKeys: [] });
             },
           });
         },
@@ -453,7 +429,6 @@ export default class Auth extends Component {
                   this.openSwitch({
                     list: [row.id],
                     enabled: checked,
-                    callback: this.query,
                   });
                 }}
               />
@@ -490,7 +465,6 @@ export default class Auth extends Component {
                   this.statusSwitch({
                     list: [row.id],
                     enabled: checked,
-                    callback: this.query,
                   });
                 }}
               />
diff --git a/src/routes/System/AppAuth/index.test.js 
b/src/routes/System/AppAuth/index.test.js
new file mode 100644
index 00000000..87993702
--- /dev/null
+++ b/src/routes/System/AppAuth/index.test.js
@@ -0,0 +1,126 @@
+/*
+ * 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 ConnectedAuth from "./index";
+import model from "../../../models/auth";
+
+jest.mock("./AddModal", () => () => null);
+jest.mock("./AddTable", () => () => null);
+jest.mock("./RelateMetadata", () => () => null);
+jest.mock("./SearchContent", () => () => null);
+jest.mock(
+  "../../../utils/AuthButton",
+  () =>
+    ({ children }) =>
+      children,
+);
+jest.mock("../../../utils/IntlUtils", () => ({
+  getCurrentLocale: jest.fn(),
+  getIntlContent: (key) => key,
+}));
+jest.mock("../../../services/api", () => ({
+  addAuthData: jest.fn(),
+  deleteAuths: jest.fn(),
+  findAuthData: jest.fn(),
+  findAuthDataDel: jest.fn(),
+  getAllAuths: jest.fn(),
+  getAllMetadata: jest.fn(),
+  getAllMetadatas: jest.fn(),
+  getfetchMetaGroup: jest.fn(),
+  syncAuthsData: jest.fn(),
+  updateAuthData: jest.fn(),
+  updateAuthDel: jest.fn(),
+  updateAuthEnabled: jest.fn(),
+  updateAuthOpened: jest.fn(),
+}));
+
+const Auth = ConnectedAuth.WrappedComponent;
+const put = (action) => ({ type: "put", action });
+
+const makeComponent = (dispatch) => {
+  const component = new Auth({
+    currentNamespaceId: "namespace-1",
+    dispatch,
+  });
+  component.setState = (update, callback) => {
+    const nextState =
+      typeof update === "function"
+        ? update(component.state, component.props)
+        : update;
+    component.state = { ...component.state, ...nextState };
+    if (callback) {
+      callback();
+    }
+  };
+  return component;
+};
+
+it("reloads auths with the active filters and page size", () => {
+  const fetchValue = {
+    appKey: "app-key",
+    phone: "13800000000",
+    currentPage: 2,
+    pageSize: 12,
+    namespaceId: "namespace-1",
+  };
+  const generator = model.effects.reload({ fetchValue }, { put });
+
+  expect(generator.next().value).toEqual(
+    put({
+      type: "fetch",
+      payload: fetchValue,
+    }),
+  );
+  expect(generator.next().done).toBe(true);
+});
+
+it("passes the current query to update without issuing a second fetch", () => {
+  const dispatch = jest.fn((action) => {
+    if (action.type === "auth/fetchItem") {
+      action.callback({ id: "auth-1" });
+    }
+  });
+  const component = makeComponent(dispatch);
+  component.state = {
+    ...component.state,
+    appKey: "app-key",
+    phone: "13800000000",
+    currentPage: 2,
+    pageSize: 12,
+  };
+
+  component.editClick({ id: "auth-1" });
+  component.state.popup.props.handleOk({ appKey: "updated-app-key" });
+
+  const updateCall = dispatch.mock.calls.find(
+    ([action]) => action.type === "auth/update",
+  );
+  expect(updateCall).toBeDefined();
+  const [updateAction] = updateCall;
+  expect(updateAction.fetchValue).toEqual({
+    appKey: "app-key",
+    phone: "13800000000",
+    currentPage: 2,
+    pageSize: 12,
+    namespaceId: "namespace-1",
+  });
+
+  updateAction.callback();
+  expect(
+    dispatch.mock.calls.filter(([action]) => action.type === "auth/fetch"),
+  ).toHaveLength(0);
+});

Reply via email to