Просмотр исходного кода

Merge pull request #1727 from weseek/imprv/input-status-server-connector

Imprv/input status server connector
ryuichi-e 6 лет назад
Родитель
Сommit
b5eecc47e5

+ 22 - 11
src/client/js/components/Admin/UserManagement.jsx

@@ -36,6 +36,10 @@ class UserManagement extends React.Component {
     }
   }
 
+  /**
+   * For checking same check box twice
+   * @param {string} statusType
+   */
   handleClick(statusType) {
     const { adminUsersContainer } = this.props;
     if (!this.validateToggleStatus(statusType)) {
@@ -49,14 +53,21 @@ class UserManagement extends React.Component {
     adminUsersContainer.handleClick(statusType);
   }
 
+  /**
+   * Workaround user status check box
+   * @param {string} statusType
+   */
   validateToggleStatus(statusType) {
     if (this.props.adminUsersContainer.isSelected(statusType)) {
-      // if else status is selected, then true
       return this.props.adminUsersContainer.state.selectedStatusList.size > 1;
     }
     return true;
   }
 
+  /**
+   * Workaround increamental search
+   * @param {string} event
+   */
   handleChangeSearchText(event) {
     this.props.adminUsersContainer.handleChangeSearchText(event.target.value);
   }
@@ -124,8 +135,8 @@ class UserManagement extends React.Component {
                 type="checkbox"
                 id="c1"
                 className="mr-1"
-                checked={adminUsersContainer.isSelected('All')}
-                onClick={() => { this.handleClick('All') }}
+                checked={adminUsersContainer.isSelected('all')}
+                onClick={() => { this.handleClick('all') }}
               />
               <label htmlFor="c1" className="mr-2">All</label>
 
@@ -133,8 +144,8 @@ class UserManagement extends React.Component {
                 type="checkbox"
                 id="c2"
                 className="mr-1"
-                checked={adminUsersContainer.isSelected('Approval Pending')}
-                onClick={() => { this.handleClick('Approval Pending') }}
+                checked={adminUsersContainer.isSelected('registered')}
+                onClick={() => { this.handleClick('registered') }}
               />
               <label htmlFor="c2" className="label label-info mr-2">Approval Pending</label>
 
@@ -142,8 +153,8 @@ class UserManagement extends React.Component {
                 type="checkbox"
                 id="c3"
                 className="mr-1"
-                checked={adminUsersContainer.isSelected('Active')}
-                onClick={() => { this.handleClick('Active') }}
+                checked={adminUsersContainer.isSelected('active')}
+                onClick={() => { this.handleClick('active') }}
               />
               <label htmlFor="c3" className="label label-success mr-2">Active</label>
 
@@ -151,8 +162,8 @@ class UserManagement extends React.Component {
                 type="checkbox"
                 id="c4"
                 className="mr-1"
-                checked={adminUsersContainer.isSelected('Suspended')}
-                onClick={() => { this.handleClick('Suspended') }}
+                checked={adminUsersContainer.isSelected('suspended')}
+                onClick={() => { this.handleClick('suspended') }}
               />
               <label htmlFor="c4" className="label label-warning mr-2">Suspended</label>
 
@@ -160,8 +171,8 @@ class UserManagement extends React.Component {
                 type="checkbox"
                 id="c5"
                 className="mr-1"
-                checked={adminUsersContainer.isSelected('Invited')}
-                onClick={() => { this.handleClick('Invited') }}
+                checked={adminUsersContainer.isSelected('invited')}
+                onClick={() => { this.handleClick('invited') }}
               />
               <label htmlFor="c5" className="label label-info">Invited</label>
             </div>

+ 14 - 4
src/client/js/services/AdminUsersContainer.js

@@ -1,5 +1,4 @@
 import { Container } from 'unstated';
-
 import loggerFactory from '@alias/logger';
 
 // eslint-disable-next-line no-unused-vars
@@ -18,13 +17,15 @@ export default class AdminUsersContainer extends Container {
 
     this.state = {
       users: [],
+      sort: 'status',
+      sortOrder: 'asc',
       isPasswordResetModalShown: false,
       isUserInviteModalShown: false,
       userForPasswordResetModal: null,
       totalUsers: 0,
       activePage: 1,
       pagingLimit: Infinity,
-      selectedStatusList: new Set(['All']),
+      selectedStatusList: new Set(['all']),
       searchText: '',
       notifyComment: '',
     };
@@ -50,7 +51,7 @@ export default class AdminUsersContainer extends Container {
   }
 
   handleClick(statusType) {
-    const all = 'All';
+    const all = 'all';
     if (this.isSelected(statusType)) {
       this.deleteStatusFromList(statusType);
     }
@@ -75,16 +76,19 @@ export default class AdminUsersContainer extends Container {
     const { selectedStatusList } = this.state;
     selectedStatusList.add(statusType);
     this.setState({ selectedStatusList });
+    this.retrieveUsersByPagingNum(1);
   }
 
   deleteStatusFromList(statusType) {
     const { selectedStatusList } = this.state;
     selectedStatusList.delete(statusType);
     this.setState({ selectedStatusList });
+    this.retrieveUsersByPagingNum(1);
   }
 
   handleChangeSearchText(searchText) {
     this.setState({ searchText });
+    this.retrieveUsersByPagingNum(1);
   }
 
   clearSearchText() {
@@ -98,7 +102,13 @@ export default class AdminUsersContainer extends Container {
    */
   async retrieveUsersByPagingNum(selectedPage) {
 
-    const params = { page: selectedPage };
+    const params = {
+      page: selectedPage,
+      sort: this.state.sort,
+      sortOrder: this.state.sortOrder,
+      selectedStatusList: Array.from(this.state.selectedStatusList),
+      searchText: this.state.searchText,
+    };
     const { data } = await this.appContainer.apiv3.get('/users', params);
 
     if (data.paginateResult == null) {

+ 13 - 50
src/server/routes/apiv3/users.js

@@ -77,47 +77,6 @@ module.exports = (crowi) => {
 
   const { ApiV3FormValidator } = crowi.middlewares;
 
-  /**
-   * @swagger
-   *
-   *  paths:
-   *    /users:
-   *      get:
-   *        tags: [Users]
-   *        operationId: listUsers
-   *        summary: /users
-   *        description: Get users
-   *        responses:
-   *          200:
-   *            description: users are fetched
-   *            content:
-   *              application/json:
-   *                schema:
-   *                  properties:
-   *                    paginateResult:
-   *                      $ref: '#/components/schemas/PaginateResult'
-   */
-  router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
-    const page = parseInt(req.query.page) || 1;
-
-    try {
-      const paginateResult = await User.paginate(
-        { status: { $ne: User.STATUS_DELETED } },
-        {
-          sort: { status: 1, username: 1, createdAt: 1 },
-          page,
-          limit: PAGE_ITEMS,
-        },
-      );
-      return res.apiv3({ paginateResult });
-    }
-    catch (err) {
-      const msg = 'Error occurred in fetching user group list';
-      logger.error('Error', err);
-      return res.apiv3Err(new ErrorV3(msg, 'user-group-list-fetch-failed'), 500);
-    }
-  });
-
   const statusNo = {
     registered: User.STATUS_REGISTERED,
     active: User.STATUS_ACTIVE,
@@ -127,7 +86,7 @@ module.exports = (crowi) => {
 
   validator.statusList = [
     // validate status list status array match to statusNo
-    body('statusList').custom((value) => {
+    query('selectedStatusList').custom((value) => {
       const error = [];
       value.forEach((status) => {
         if (!Object.keys(statusNo)) {
@@ -137,27 +96,31 @@ module.exports = (crowi) => {
       return (error.length === 0);
     }),
     // validate sortOrder : asc or desc
-    body('sortOrder').isIn(['asc', 'desc']),
+    query('sortOrder').isIn(['asc', 'desc']),
     // validate sort : what column you will sort
-    body('sort').isIn(['status', 'username', 'name', 'email', 'createdAt', 'lastLoginAt']),
+    query('sort').isIn(['id', 'status', 'username', 'name', 'email', 'createdAt', 'lastLoginAt']),
     query('page').isInt({ min: 1 }),
   ];
 
-  router.get('/search-user-status/', validator.statusList, ApiV3FormValidator, async(req, res) => {
+  // TODO write swagger
+
+  router.get('/', validator.statusList, ApiV3FormValidator, async(req, res) => {
+
     const page = parseInt(req.query.page) || 1;
     // status
-    const { statusList } = req.body;
-    const statusNoList = statusList.map(element => statusNo[element]);
+    const { selectedStatusList } = req.query;
+    const statusNoList = (selectedStatusList.includes('all')) ? Object.values(statusNo) : selectedStatusList.map(element => statusNo[element]);
+
     // Search from input
-    const inputWord = req.body.inputWord || '';
-    const searchWord = new RegExp(`${inputWord}`);
+    const searchText = req.query.searchText || '';
+    const searchWord = new RegExp(`${searchText}`);
     const orColumns = ['name', 'username', 'email'];
     const orOutput = {};
     orColumns.forEach((element) => {
       orOutput[element] = { $in: searchWord };
     });
     // Sort
-    const { sort, sortOrder } = req.body;
+    const { sort, sortOrder } = req.query;
     const sortOutput = {
       [sort]: (sortOrder === 'desc') ? -1 : 1,
     };