support "Configure Data Permission" search (#164) (#169)

Co-authored-by: wenyu.dai <“wenyu.dai@qq.com”>
diff --git a/src/routes/System/User/DataPermModal.js b/src/routes/System/User/DataPermModal.js
index f960dfa..75c582d 100644
--- a/src/routes/System/User/DataPermModal.js
+++ b/src/routes/System/User/DataPermModal.js
@@ -15,30 +15,45 @@
  * limitations under the License.
  */
 
-import React, { Component } from 'react';
-import { Modal, Tree, Icon, Button, Checkbox, Table, Row, Col } from 'antd';
+import React, { Component } from "react";
+import {
+  Modal,
+  Tree,
+  Icon,
+  Button,
+  Checkbox,
+  Table,
+  Row,
+  Col,
+  Input,
+  Empty
+} from "antd";
 import { connect } from "dva";
-import { getIntlContent } from '../../../utils/IntlUtils';
+import { getIntlContent } from "../../../utils/IntlUtils";
+import { titleCase } from "../../../utils/utils";
 
 const { TreeNode } = Tree;
+const { Search } = Input;
 
 @connect(({ dataPermission, resource, global, loading }) => ({
   dataPermission,
   resource,
   global,
-  selectorPermisionLoading: loading.effects["dataPermission/fetchDataPermisionSelectors"],
-  rulePermisionLoading: loading.effects["dataPermission/fetchDataPermisionRules"]
+  selectorPermisionLoading:
+    loading.effects["dataPermission/fetchDataPermisionSelectors"],
+  rulePermisionLoading:
+    loading.effects["dataPermission/fetchDataPermisionRules"]
 }))
 export default class DataPermModal extends Component {
-
   constructor(props) {
     super(props);
     this.state = {
-      currentPlugin:null,
+      currentPlugin: null,
       currentPermissionSelectorPage: 1,
       selectorData: null,
       pageSize: 12,
-      ruleListMap:{}
+      ruleListMap: {},
+      searchValue: ""
     };
   }
 
@@ -57,7 +72,7 @@
         callback: () => {}
       }
     });
-  }
+  };
 
   getPermissionSelectorList = page => {
     const { dispatch, userId } = this.props;
@@ -70,13 +85,13 @@
         userId,
         pluginId: currentPlugin.pluginId
       },
-      callback: (res)=>{
+      callback: res => {
         this.setState({
           selectorData: res
-        })
+        });
       }
     });
-  }
+  };
 
   getPermissionRuleList = (selectorId, page) => {
     const { dispatch, userId } = this.props;
@@ -90,13 +105,16 @@
         pluginId: currentPlugin.pluginId,
         selectorId
       },
-      callback: (res) =>{
-        if(res.dataList && res.dataList.length > 0) {
-          res.dataList.forEach(e=>{
+      callback: res => {
+        if (res.dataList && res.dataList.length > 0) {
+          res.dataList.forEach(e => {
             e.selectorId = selectorId;
-          })
+          });
         }
-        if(ruleListMap[selectorId] && ruleListMap[selectorId].currentRulePage) {
+        if (
+          ruleListMap[selectorId] &&
+          ruleListMap[selectorId].currentRulePage
+        ) {
           res.currentRulePage = ruleListMap[selectorId].currentRulePage;
         } else {
           res.currentRulePage = 1;
@@ -104,26 +122,31 @@
         ruleListMap[selectorId] = res;
         this.setState({
           ruleListMap
-        })
+        });
       }
     });
-  }
+  };
 
   onSelectPlugin = (selectedKeys, e) => {
     const currentPlugin = e.node.props.dataRef;
-    this.setState({
-      currentPlugin,
-      currentPermissionSelectorPage: 1,
-      ruleListMap: {}
-    }, () => {
-      this.getPermissionSelectorList(1);
-    })
-  }
+    this.setState(
+      {
+        currentPlugin,
+        currentPermissionSelectorPage: 1,
+        ruleListMap: {}
+      },
+      () => {
+        this.getPermissionSelectorList(1);
+      }
+    );
+  };
 
-  handleCheckSelector = (record) => {
+  handleCheckSelector = record => {
     const { dispatch, userId } = this.props;
     const { currentPermissionSelectorPage } = this.state;
-    let type = record.isChecked ? "dataPermission/deletePermisionSelector" : "dataPermission/addPermisionSelector";
+    let type = record.isChecked
+      ? "dataPermission/deletePermisionSelector"
+      : "dataPermission/addPermisionSelector";
     dispatch({
       type,
       payload: {
@@ -131,16 +154,18 @@
         userId
       },
       callback: () => {
-        this.getPermissionSelectorList(currentPermissionSelectorPage)
-        this.getPermissionRuleList(record.dataId,1)
+        this.getPermissionSelectorList(currentPermissionSelectorPage);
+        this.getPermissionRuleList(record.dataId, 1);
       }
-    })
-  }
+    });
+  };
 
-  handleCheckRule = (record) => {
+  handleCheckRule = record => {
     const { dispatch, userId } = this.props;
     const { currentPermissionSelectorPage, ruleListMap } = this.state;
-    let type = record.isChecked ? "dataPermission/deletePermisionRule" : "dataPermission/addPermisionRule";
+    let type = record.isChecked
+      ? "dataPermission/deletePermisionRule"
+      : "dataPermission/addPermisionRule";
     dispatch({
       type,
       payload: {
@@ -148,16 +173,16 @@
         userId
       },
       callback: () => {
-        this.getPermissionSelectorList(currentPermissionSelectorPage)
+        this.getPermissionSelectorList(currentPermissionSelectorPage);
         let page = ruleListMap[record.selectorId].currentRulePage || 1;
-        this.getPermissionRuleList(record.selectorId,page)
+        this.getPermissionRuleList(record.selectorId, page);
       }
-    })
-  }
+    });
+  };
 
   handleExpandRuleTable = (expanded, record) => {
-    this.getPermissionRuleList(record.dataId,1)
-  }
+    this.getPermissionRuleList(record.dataId, 1);
+  };
 
   selectorPageOnchange = page => {
     this.setState({ currentPermissionSelectorPage: page });
@@ -167,89 +192,169 @@
   rulePageOnchange = (page, selectorId) => {
     let { ruleListMap } = this.state;
     ruleListMap[selectorId].currentRulePage = page;
-    this.setState({
-      ruleListMap
-    },()=>{
-      this.getPermissionRuleList(selectorId,page);
-    })
-
-  }
-
-  renderPluginTree = ()=>{
-    let { global: { plugins }, resource: { menuTree } } = this.props;
-    let pluginMenuList = menuTree.filter(e=>e.url === "/plug");
-
-    if(pluginMenuList && pluginMenuList.length > 0){
-      pluginMenuList[0].children.forEach(p => {
-        if(plugins.some(e => e.name === p.name)) {
-          p.pluginId = plugins.filter(e => e.name === p.name)[0].id;
-        }
-      })
-      return (
-        <Tree
-          style={{background:"white"}}
-          defaultExpandAll
-          onSelect={this.onSelectPlugin}
-          showIcon
-        >
-          {this.renderTreeNodes(pluginMenuList)}
-        </Tree>
-      )
-    }
-  }
-
-  renderTreeNodes = (data) => {
-    data = data.sort((a,b)=>(a.sort||0)-(b.sort||0));
-    return data.map(item => {
-      item.title =  item.meta.title;
-      if (item.title.startsWith("SHENYU.")) {
-        item.title = getIntlContent(item.title);
+    this.setState(
+      {
+        ruleListMap
+      },
+      () => {
+        this.getPermissionRuleList(selectorId, page);
       }
+    );
+  };
+
+  filterPlugin = () => {
+    let {
+      global: { plugins },
+      resource: { menuTree }
+    } = this.props;
+    const { searchValue } = this.state;
+    let pluginMenuList = menuTree.filter(e => e.url === "/plug");
+    if (pluginMenuList && pluginMenuList.length > 0) {
+      pluginMenuList = pluginMenuList[0].children;
+      const treeData = [];
+      pluginMenuList.forEach(plugin => {
+        if (
+          typeof searchValue === "string" &&
+          searchValue.length &&
+          !plugin.name
+            .toLocaleLowerCase()
+            .includes(searchValue.toLocaleLowerCase())
+        ) {
+          return;
+        }
+        const currentPluginInfo = plugins.find(v => v.name === plugin.name);
+        let currentCategory = treeData.find(
+          tree => tree.title === currentPluginInfo.role
+        );
+        if (!currentCategory) {
+          treeData.push({
+            title: currentPluginInfo.role,
+            key: currentPluginInfo.role,
+            selectable: false,
+            icon: "unordered-list",
+            sort: plugin.sort,
+            children: []
+          });
+          currentCategory = treeData[treeData.length - 1];
+        }
+        currentCategory.children.push({
+          key: currentPluginInfo.id,
+          title: titleCase(currentPluginInfo.name),
+          selectable: true,
+          sort: plugin.sort,
+          icon: plugin.meta.icon,
+          pluginId: currentPluginInfo.id
+        });
+      });
+
+      pluginMenuList = treeData;
+    }
+    return pluginMenuList;
+  };
+
+  onSearch = e => {
+    const { value } = e.target;
+    this.setState({
+      searchValue: value
+    });
+  };
+
+  renderPluginTree = () => {
+    let pluginMenuList = this.filterPlugin();
+    return (
+      <Row gutter={[16, 16]}>
+        <Col span={24}>
+          <Search
+            placeholder={getIntlContent("SHENYU.PLUGIN.INPUTNAME")}
+            onChange={this.onSearch}
+          />
+        </Col>
+        {pluginMenuList.length > 0 ? (
+          <Col span={24}>
+            <Tree
+              defaultExpandAll
+              style={{ background: "white" }}
+              onSelect={this.onSelectPlugin}
+              showIcon
+            >
+              {this.renderTreeNodes(pluginMenuList)}
+            </Tree>
+          </Col>
+        ) : (
+          <Col span={24}>
+            <Empty />
+          </Col>
+        )}
+      </Row>
+    );
+  };
+
+  renderTreeNodes = data => {
+    return data.map(item => {
       if (item.children && item.children.length > 0) {
         return (
-          <TreeNode selectable={false} title={item.title} icon={item.meta.icon&&<Icon type={item.meta.icon} />} key={item.id} dataRef={item}>
+          <TreeNode
+            selectable={item.selectable}
+            title={item.title}
+            icon={<Icon type={item.icon} />}
+            key={item.key}
+            dataRef={item}
+          >
             {this.renderTreeNodes(item.children)}
           </TreeNode>
         );
       } else {
-        return <TreeNode icon={item.meta.icon&&<Icon type={item.meta.icon} />} title={item.title} key={item.id} dataRef={item} />;
+        return (
+          <TreeNode
+            icon={<Icon type={item.icon} />}
+            title={item.title}
+            key={item.key}
+            dataRef={item}
+          />
+        );
       }
     });
-  }
+  };
 
   renderSelectorRuleTable = () => {
-    const {
-      currentPermissionSelectorPage,
-      pageSize
-    } = this.state;
+    const { currentPermissionSelectorPage, pageSize } = this.state;
     const { selectorData, ruleListMap } = this.state;
     const ruleColumns = [
       {
         title: getIntlContent("SHENYU.SYSTEM.DATA.PERMISSION.CHECKED"),
-        dataIndex: 'isChecked',
-        width:90,
-        key: 'isChecked',
+        dataIndex: "isChecked",
+        width: 90,
+        key: "isChecked",
         render: (isChecked, record) => {
-          return <Checkbox checked={isChecked} onClick={this.handleCheckRule.bind(this,record)}  />
+          return (
+            <Checkbox
+              checked={isChecked}
+              onClick={this.handleCheckRule.bind(this, record)}
+            />
+          );
         }
       },
-      { title: getIntlContent("SHENYU.SYSTEM.DATA.PERMISSION.RULENAME"), dataIndex: 'dataName', key: 'dataName' },
+      {
+        title: getIntlContent("SHENYU.SYSTEM.DATA.PERMISSION.RULENAME"),
+        dataIndex: "dataName",
+        key: "dataName"
+      }
     ];
-    const expandedRowRender = (record) => {
-      let ruleData = ruleListMap&&ruleListMap[record.dataId];
-      let currentRulePage = ruleData&&ruleData.currentRulePage;
+    const expandedRowRender = record => {
+      let ruleData = ruleListMap && ruleListMap[record.dataId];
+      let currentRulePage = ruleData && ruleData.currentRulePage;
       return (
         <Table
           size="small"
           bordered
           columns={ruleColumns}
-          dataSource={ruleData&&ruleData.dataList}
+          dataSource={ruleData && ruleData.dataList}
           pagination={{
-            total: (ruleData&&ruleData.total) || 0,
+            total: (ruleData && ruleData.total) || 0,
             current: currentRulePage || 1,
             pageSize,
-            onChange: (page) => {
-              this.rulePageOnchange(page,record.dataId);
+            onChange: page => {
+              this.rulePageOnchange(page, record.dataId);
             }
           }}
         />
@@ -259,38 +364,43 @@
     const columns = [
       {
         title: getIntlContent("SHENYU.SYSTEM.DATA.PERMISSION.CHECKED"),
-        dataIndex: 'isChecked',
-        width:90,
-        key: 'isChecked',
+        dataIndex: "isChecked",
+        width: 90,
+        key: "isChecked",
         render: (isChecked, record) => {
-          return <Checkbox checked={isChecked} onClick={this.handleCheckSelector.bind(this,record)} />
+          return (
+            <Checkbox
+              checked={isChecked}
+              onClick={this.handleCheckSelector.bind(this, record)}
+            />
+          );
         }
       },
       {
         title: getIntlContent("SHENYU.SYSTEM.DATA.PERMISSION.SELECTORNAME"),
-        dataIndex: 'dataName',
-        key: 'dataName'
-      },
+        dataIndex: "dataName",
+        key: "dataName"
+      }
     ];
 
     return (
       <Table
-        style={{width:"350px"}}
+        style={{ width: "350px" }}
         size="small"
         bordered
         columns={columns}
         expandedRowRender={expandedRowRender}
-        dataSource={selectorData&&selectorData.dataList}
+        dataSource={selectorData && selectorData.dataList}
         onExpand={this.handleExpandRuleTable}
         pagination={{
-          total: selectorData&&selectorData.total,
+          total: selectorData && selectorData.total,
           current: currentPermissionSelectorPage,
           pageSize,
           onChange: this.selectorPageOnchange
         }}
       />
     );
-  }
+  };
 
   render() {
     let { handleCancel } = this.props;
@@ -309,14 +419,12 @@
         ]}
       >
         <Row gutter={20}>
-          <Col span={10} style={{minWidth:280}}>
+          <Col span={10} style={{ minWidth: 280 }}>
             {this.renderPluginTree()}
           </Col>
-          <Col span={14}>
-            {this.renderSelectorRuleTable()}
-          </Col>
+          <Col span={14}>{this.renderSelectorRuleTable()}</Col>
         </Row>
       </Modal>
-    )
+    );
   }
 }