Răsfoiți Sursa

feat:Add user statistics table to user management screen

riona-k 4 luni în urmă
părinte
comite
3deda1bc75

+ 7 - 1
apps/app/public/static/locales/en_US/admin.json

@@ -796,7 +796,13 @@
     "unset": "No",
     "related_username": "Related user's ",
     "cannot_invite_maximum_users": "Can not invite more than the maximum number of users.",
-    "current_users": "Current users:"
+    "current_users": "Current users:",
+    "user_statistics": {
+      "title": "User Statistics",
+      "total": "Total Users",
+      "active": "Active",
+      "inactive": "Inactive"
+    }
   },
   "user_group_management": {
     "user_group_management": "User Group Management",

+ 6 - 1
apps/app/public/static/locales/fr_FR/admin.json

@@ -796,7 +796,12 @@
     "unset": "Non",
     "related_username": "Utilisateur ",
     "cannot_invite_maximum_users": "La limite maximale d'utilisateurs invitables est atteinte.",
-    "current_users": "Utilisateurs:"
+    "current_users": "Utilisateurs:",
+    "user_statistics": {
+      "total": "Utilisateurs totaux",
+      "active": "Actifs",
+      "inactive": "Inactifs"
+    }
   },
   "user_group_management": {
     "user_group_management": "Gestion des groupes",

+ 8 - 2
apps/app/public/static/locales/ja_JP/admin.json

@@ -321,7 +321,6 @@
       "default": "上記のホスト情報をコピー",
       "done": "クリップボードにコピーしました!"
     },
-    "user_statistics": "ユーザーデータ",
     "bug_report": "バグを報告する",
     "submit_bug_report": "<a href='https://github.com/growilabs/growi/issues/new?assignees=&labels=bug&template=bug-report.md&title=Bug%3A' target='_blank' rel='noreferrer'>次に GitHub で Issue を投稿してください。</a>"
   },
@@ -806,8 +805,15 @@
     "unset": "未設定",
     "related_username": "関連付けられているユーザーの ",
     "cannot_invite_maximum_users": "ユーザーが上限に達したため招待できません。",
-    "current_users": "現在のユーザー数:"
+    "current_users": "現在のユーザー数:",
+    "user_statistics": {
+      "title": "ユーザー統計",
+      "total": "総ユーザー数",
+      "active": "アクティブ",
+      "inactive": "非アクティブ"
+    }
   },
+
   "user_group_management": {
     "user_group_management": "グループ管理",
     "create_group": "新規グループの作成",

+ 6 - 1
apps/app/public/static/locales/ko_KR/admin.json

@@ -796,7 +796,12 @@
     "unset": "아니요",
     "related_username": "관련 사용자 ",
     "cannot_invite_maximum_users": "최대 사용자 수 이상을 초대할 수 없습니다.",
-    "current_users": "현재 사용자:"
+    "current_users": "현재 사용자:",
+    "user_statistics": {
+      "total": "총 사용자",
+      "active": "활성",
+      "inactive": "비활성"
+    }
   },
   "user_group_management": {
     "user_group_management": "사용자 그룹 관리",

+ 6 - 1
apps/app/public/static/locales/zh_CN/admin.json

@@ -805,7 +805,12 @@
     "unset": "否",
     "related_username": "相关用户的",
     "cannot_invite_maximum_users": "邀请的用户数不能超过最大值。",
-    "current_users": "当前用户:"
+    "current_users": "当前用户:",
+    "user_statistics": {
+      "total": "用户总数",
+      "active": "活跃",
+      "inactive": "非活跃"
+    }
   },
   "user_group_management": {
     "user_group_management": "用户组管理",

+ 0 - 8
apps/app/src/client/components/Admin/AdminHome/AdminHome.jsx

@@ -16,7 +16,6 @@ import { withUnstatedContainers } from '../../UnstatedUtils';
 
 import { EnvVarsTable } from './EnvVarsTable';
 import SystemInfomationTable from './SystemInfomationTable';
-import UserStatisticsTable from './UserStatisticsTable';
 
 
 const logger = loggerFactory('growi:admin');
@@ -96,13 +95,6 @@ const AdminHome = (props) => {
         </div>
       </div>
 
-      <div className="row mb-5">
-        <div className="col-lg-12">
-          <h2 className="admin-setting-header">{t('admin:admin_top.user_statistics')}</h2>
-          <UserStatisticsTable />
-        </div>
-      </div>
-
       <div className="row mb-5">
         <div className="col-md-12">
           <h2 className="admin-setting-header">{t('admin:admin_top.bug_report')}</h2>

+ 0 - 50
apps/app/src/client/components/Admin/AdminHome/UserStatisticsTable.tsx

@@ -1,50 +0,0 @@
-import React from 'react';
-
-import AdminHomeContainer from '~/client/services/AdminHomeContainer';
-
-import { withUnstatedContainers } from '../../UnstatedUtils';
-
-type Props = {
-  adminHomeContainer: AdminHomeContainer,
-}
-
-const UserStatisticsTable: React.FC<Props> = (props: Props) => {
-  const { adminHomeContainer } = props;
-  const userStatistics = adminHomeContainer.state.userStatistics;
-
-  if (userStatistics == null) return null;
-
-  return (
-    <table className="table table-bordered user-stats-table">
-      <tbody>
-        <tr>
-          <th className="col-sm-4">Total Users</th>
-          <td>{ userStatistics.total }</td>
-        </tr>
-        <tr>
-          <th className="col-sm-4">Active Users</th>
-          <td>{ userStatistics.active.total }</td>
-        </tr>
-        <tr>
-          <th className="col-sm-4">Inactive Users</th>
-          <td>{ userStatistics.inactive.total }</td>
-        </tr>
-      </tbody>
-      <style jsx>{`
-    .user-stats-table {
-      table-layout: fixed;
-      width: 100%;
-    }
-    .user-stats-table th,
-    .user-stats-table td {
-      width: 50%;
-      vertical-align: top;
-    }
-  `}
-      </style>
-    </table>
-  );
-};
-
-const UserStatisticsTableWrapper = withUnstatedContainers(UserStatisticsTable, [AdminHomeContainer]);
-export default UserStatisticsTableWrapper;

+ 6 - 1
apps/app/src/client/components/Admin/UserManagement.tsx

@@ -13,6 +13,7 @@ import { withUnstatedContainers } from '../UnstatedUtils';
 
 import InviteUserControl from './Users/InviteUserControl';
 import PasswordResetModal from './Users/PasswordResetModal';
+import UserStatisticsTable from './Users/UserStatisticsTable';
 import UserTable from './Users/UserTable';
 
 import styles from './UserManagement.module.scss';
@@ -40,7 +41,8 @@ const UserManagement = (props: UserManagementProps) => {
   // for Next routing
   useEffect(() => {
     pagingHandler(1);
-  }, [pagingHandler]);
+    adminUsersContainer.retrieveUserStatistics();
+  }, [pagingHandler, adminUsersContainer]);
 
   const validateToggleStatus = (statusType: string) => {
     return (adminUsersContainer.isSelected(statusType)) ? (
@@ -134,6 +136,9 @@ const UserManagement = (props: UserManagementProps) => {
       </p>
 
       <h2>{t('user_management.user_management')}</h2>
+      <UserStatisticsTable
+        userStatistics={adminUsersContainer.state.userStatistics}
+      />
       <div className="border-top border-bottom">
 
         <div className="row d-flex justify-content-start align-items-center my-2">

+ 39 - 0
apps/app/src/client/components/Admin/Users/UserStatisticsTable.tsx

@@ -0,0 +1,39 @@
+import React from 'react';
+
+import { useTranslation } from 'next-i18next';
+
+type UserStatistics = {
+  total: number;
+  active: { total: number };
+  inactive: { total: number };
+};
+
+type Props = {
+  userStatistics?: UserStatistics | null;
+};
+
+const UserStatisticsTable: React.FC<Props> = ({ userStatistics }) => {
+  const { t } = useTranslation('admin');
+  if (userStatistics == null) return null;
+
+  return (
+    <table className="table table-bordered w-100">
+      <tbody>
+        <tr>
+          <th className="col-sm-4 align-top">{t('user_management.user_statistics.total')}</th>
+          <td className="align-top">{ userStatistics.active.total }</td>
+        </tr>
+        <tr>
+          <th className="col-sm-4 align-top">{t('user_management.user_statistics.active')}</th>
+          <td className="align-top">{ userStatistics.active.total }</td>
+        </tr>
+        <tr>
+          <th className="col-sm-4 align-top">{t('user_management.user_statistics.inactive')}</th>
+          <td className="align-top">{ userStatistics.inactive.total }</td>
+        </tr>
+      </tbody>
+    </table>
+  );
+};
+
+export default UserStatisticsTable;

+ 0 - 5
apps/app/src/client/services/AdminHomeContainer.js

@@ -36,7 +36,6 @@ export default class AdminHomeContainer extends Container {
       installedPlugins: null,
       isV5Compatible: null,
       isMaintenanceMode: null,
-      userStatistics: null,
     };
 
   }
@@ -60,9 +59,6 @@ export default class AdminHomeContainer extends Container {
       const response = await apiv3Get('/admin-home/');
       const { adminHomeParams } = response.data;
 
-      const statsRes = await apiv3Get('/statistics/user');
-      const userStatistics = statsRes.data.data;
-
       this.setState(prevState => ({
         ...prevState,
         growiVersion: adminHomeParams.growiVersion,
@@ -72,7 +68,6 @@ export default class AdminHomeContainer extends Container {
         envVars: adminHomeParams.envVars,
         isV5Compatible: adminHomeParams.isV5Compatible,
         isMaintenanceMode: adminHomeParams.isMaintenanceMode,
-        userStatistics,
       }));
     }
     catch (err) {

+ 10 - 0
apps/app/src/client/services/AdminUsersContainer.js

@@ -34,6 +34,7 @@ export default class AdminUsersContainer extends Container {
       pagingLimit: Infinity,
       selectedStatusList: new Set(['all']),
       searchText: '',
+      userStatistics: null,
     };
 
     this.showPasswordResetModal = this.showPasswordResetModal.bind(this);
@@ -158,6 +159,15 @@ export default class AdminUsersContainer extends Container {
 
   }
 
+  /**
+ * retrieve user statistics
+ */
+  async retrieveUserStatistics() {
+    const statsRes = await apiv3Get('/statistics/user');
+    const userStatistics = statsRes.data.data;
+    this.setState({ userStatistics });
+  }
+
   /**
    * create user invited
    * @memberOf AdminUsersContainer