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

imprv: User group detail page clean code (#5045)

* jsx -> tsx

* Typescriptized components & Wrap with unstated at the end to not use the return type of withTranslation in other files

* Typescriptized unstatedUtils

* Renamed state

* Explicit state type declaration

* Initial state as private member variable

* Added a null check

* Clean code

* Added comments for future tasks

* Fix lint

* Fix interface lint

* Replaced IUserGroup with IUserGroupHasObjectId

* Class Component to FC

* Class component to FC

* Removed unnecessary code

* Class component to FC

* Added a semicolon
Haku Mizuki 4 лет назад
Родитель
Сommit
dcd33295ab

+ 9 - 3
packages/app/src/client/services/AdminUserGroupDetailContainer.js

@@ -11,7 +11,7 @@ const logger = loggerFactory('growi:services:AdminUserGroupDetailContainer');
  * Service container for admin user group detail page (UserGroupDetailPage.jsx)
  * Service container for admin user group detail page (UserGroupDetailPage.jsx)
  * @extends {Container} unstated Container
  * @extends {Container} unstated Container
  */
  */
-export default class AdminAdminUserGroupDetailContainer extends Container {
+export default class AdminUserGroupDetailContainer extends Container {
 
 
   constructor(appContainer) {
   constructor(appContainer) {
     super();
     super();
@@ -27,8 +27,14 @@ export default class AdminAdminUserGroupDetailContainer extends Container {
     this.state = {
     this.state = {
       // TODO: [SPA] get userGroup from props
       // TODO: [SPA] get userGroup from props
       userGroup: JSON.parse(rootElem.getAttribute('data-user-group')),
       userGroup: JSON.parse(rootElem.getAttribute('data-user-group')),
-      userGroupRelations: [],
-      relatedPages: [],
+      userGroupRelations: [], // For user list
+
+      // TODO 85062: /_api/v3/user-groups/children?include_grand_child=boolean
+      childUserGroups: [], // TODO 85062: fetch data on init (findChildGroupsByParentIds) For child group list
+      grandChildUserGroups: [], // TODO 85062: fetch data on init (findChildGroupsByParentIds) For child group list
+
+      childUserGroupUsers: [], // TODO 85062: fetch data on init (findRelationsByGroupIds) For child group list
+      relatedPages: [], // For page list
       isUserGroupUserModalOpen: false,
       isUserGroupUserModalOpen: false,
       searchType: 'partial',
       searchType: 'partial',
       isAlsoMailSearched: false,
       isAlsoMailSearched: false,

+ 0 - 49
packages/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.jsx

@@ -1,49 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation } from 'react-i18next';
-
-import UserGroupEditForm from './UserGroupEditForm';
-import UserGroupUserTable from './UserGroupUserTable';
-import UserGroupUserModal from './UserGroupUserModal';
-import UserGroupPageList from './UserGroupPageList';
-import { withUnstatedContainers } from '../../UnstatedUtils';
-import AppContainer from '~/client/services/AppContainer';
-
-class UserGroupDetailPage extends React.Component {
-
-  render() {
-    const { t } = this.props;
-
-    return (
-      <div>
-        <a href="/admin/user-groups" className="btn btn-outline-secondary">
-          <i className="icon-fw ti-arrow-left" aria-hidden="true"></i>
-          {t('admin:user_group_management.back_to_list')}
-        </a>
-        <div className="mt-4 form-box">
-          <UserGroupEditForm />
-        </div>
-        <h2 className="admin-setting-header mt-4">{t('admin:user_group_management.user_list')}</h2>
-        <UserGroupUserTable />
-        <UserGroupUserModal />
-        <h2 className="admin-setting-header mt-4">{t('Page')}</h2>
-        <div className="page-list">
-          <UserGroupPageList />
-        </div>
-      </div>
-    );
-  }
-
-}
-
-UserGroupDetailPage.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
-};
-
-/**
- * Wrapper component for using unstated
- */
-const UserGroupDetailPageWrapper = withUnstatedContainers(UserGroupDetailPage, [AppContainer]);
-
-export default withTranslation()(UserGroupDetailPageWrapper);

+ 42 - 0
packages/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx

@@ -0,0 +1,42 @@
+import React, { FC } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import UserGroupEditForm from './UserGroupEditForm';
+import UserGroupUserTable from './UserGroupUserTable';
+import UserGroupUserModal from './UserGroupUserModal';
+import UserGroupPageList from './UserGroupPageList';
+import { withUnstatedContainers } from '../../UnstatedUtils';
+import AppContainer from '~/client/services/AppContainer';
+
+const UserGroupDetailPage: FC = () => {
+  const { t } = useTranslation();
+
+  return (
+    <div>
+      <a href="/admin/user-groups" className="btn btn-outline-secondary">
+        <i className="icon-fw ti-arrow-left" aria-hidden="true"></i>
+        {t('admin:user_group_management.back_to_list')}
+      </a>
+      {/* TODO 85062: Link to the ancestors group */}
+      <div className="mt-4 form-box">
+        <UserGroupEditForm />
+      </div>
+      <h2 className="admin-setting-header mt-4">{t('admin:user_group_management.user_list')}</h2>
+      <UserGroupUserTable />
+      <UserGroupUserModal />
+      <h2 className="admin-setting-header mt-4">{t('Page')}</h2>
+      <div className="page-list">
+        <UserGroupPageList />
+      </div>
+    </div>
+  );
+
+};
+
+
+/**
+ * Wrapper component for using unstated
+ */
+const UserGroupDetailPageWrapper = withUnstatedContainers(UserGroupDetailPage, [AppContainer]);
+
+export default UserGroupDetailPageWrapper;

+ 1 - 1
packages/app/src/server/routes/apiv3/user-group-relation.js

@@ -41,7 +41,7 @@ module.exports = (crowi) => {
    *                      type: object
    *                      type: object
    *                      description: contains arrays user objects related
    *                      description: contains arrays user objects related
    */
    */
-  router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => {
+  router.get('/', loginRequiredStrictly, adminRequired, async(req, res) => { // TODO 85062: enable groupIds to filter
     try {
     try {
       const relations = await UserGroupRelation.find().populate('relatedUser');
       const relations = await UserGroupRelation.find().populate('relatedUser');
 
 

+ 5 - 0
packages/app/src/server/routes/apiv3/user-group.js

@@ -84,6 +84,11 @@ module.exports = (crowi) => {
     }
     }
   });
   });
 
 
+  /*
+   * TODO 85062: GET /children ?include-grand-children=boolean fetch all children by parent ids
+   * if include-grand-children=true, return grand children as well
+   */
+
   validator.create = [
   validator.create = [
     body('name', 'Group name is required').trim().exists({ checkFalsy: true }),
     body('name', 'Group name is required').trim().exists({ checkFalsy: true }),
     body('description', 'Description must be a string').optional().isString(),
     body('description', 'Description must be a string').optional().isString(),