jam411 3 lat temu
rodzic
commit
8a90f4973d

+ 3 - 0
packages/app/src/components/Admin/UserGroup/UserGroupForm.tsx

@@ -57,6 +57,8 @@ export const UserGroupForm: FC<Props> = (props: Props) => {
     >
 
       <fieldset>
+        <h2 className="admin-setting-header">{t('user_group_management.basic_info')}</h2>
+
         {
           userGroup?.createdAt != null && (
             <div className="form-group row">
@@ -65,6 +67,7 @@ export const UserGroupForm: FC<Props> = (props: Props) => {
             </div>
           )
         }
+
         <div className="form-group row">
           <label htmlFor="name" className="col-md-2 col-form-label">
             {t('user_group_management.group_name')}

+ 101 - 107
packages/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx

@@ -19,23 +19,21 @@ import { useIsAclEnabled } from '~/stores/context';
 import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
 import {
   useSWRxUserGroupPages, useSWRxUserGroupRelationList, useSWRxChildUserGroupList, useSWRxUserGroup,
-  useSWRxSelectableParentUserGroups, useSWRxSelectableChildUserGroups, useSWRxAncestorUserGroups,
-  useSWRxUserGroupRelations,
+  useSWRxSelectableParentUserGroups, useSWRxSelectableChildUserGroups, useSWRxAncestorUserGroups, useSWRxUserGroupRelations,
 } from '~/stores/user-group';
 
-
 import styles from './UserGroupDetailPage.module.scss';
 
 const UserGroupPageList = dynamic(() => import('./UserGroupPageList'), { ssr: false });
 const UserGroupUserTable = dynamic(() => import('./UserGroupUserTable'), { ssr: false });
-const UserGroupDropdown = dynamic(() => import('../UserGroup/UserGroupDropdown').then(mod => mod.UserGroupDropdown), { ssr: false });
-const UserGroupForm = dynamic(() => import('../UserGroup/UserGroupForm').then(mod => mod.UserGroupForm), { ssr: false });
-const UserGroupTable = dynamic(() => import('../UserGroup/UserGroupTable').then(mod => mod.UserGroupTable), { ssr: false });
 
-// Modals
 const UserGroupUserModal = dynamic(() => import('./UserGroupUserModal'), { ssr: false });
-const UserGroupModal = dynamic(() => import('../UserGroup/UserGroupModal').then(mod => mod.UserGroupModal), { ssr: false });
+
 const UserGroupDeleteModal = dynamic(() => import('../UserGroup/UserGroupDeleteModal').then(mod => mod.UserGroupDeleteModal), { ssr: false });
+const UserGroupDropdown = dynamic(() => import('../UserGroup/UserGroupDropdown').then(mod => mod.UserGroupDropdown), { ssr: false });
+const UserGroupForm = dynamic(() => import('../UserGroup/UserGroupForm').then(mod => mod.UserGroupForm), { ssr: false });
+const UserGroupModal = dynamic(() => import('../UserGroup/UserGroupModal').then(mod => mod.UserGroupModal), { ssr: false });
+const UserGroupTable = dynamic(() => import('../UserGroup/UserGroupTable').then(mod => mod.UserGroupTable), { ssr: false });
 const UpdateParentConfirmModal = dynamic(() => import('./UpdateParentConfirmModal').then(mod => mod.UpdateParentConfirmModal), { ssr: false });
 
 
@@ -47,84 +45,52 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
   const { t } = useTranslation('admin');
   const router = useRouter();
   const xss = useMemo(() => new Xss(), []);
-
   const { userGroupId: currentUserGroupId } = props;
 
   const { data: currentUserGroup } = useSWRxUserGroup(currentUserGroupId);
-  const { data: userGroupRelations, mutate: mutateUserGroupRelations } = useSWRxUserGroupRelations(currentUserGroupId);
-
-  const notExistsUerGroup = !(currentUserGroup === undefined) && currentUserGroup == null;
-
-  useEffect(() => {
-    if (!objectIdUtils.isValidObjectId(currentUserGroupId) || notExistsUerGroup) {
-      router.push('/admin/user-groups');
-    }
-  }, [currentUserGroup, currentUserGroupId, notExistsUerGroup, router]);
-
-  /*
-   * state
-   */
   const [searchType, setSearchType] = useState<SearchType>(SearchTypes.PARTIAL);
   const [isAlsoMailSearched, setAlsoMailSearched] = useState<boolean>(false);
   const [isAlsoNameSearched, setAlsoNameSearched] = useState<boolean>(false);
   const [selectedUserGroup, setSelectedUserGroup] = useState<IUserGroupHasId | undefined>(undefined); // not null but undefined (to use defaultProps in UserGroupDeleteModal)
-
-  // Modal State
   const [isCreateModalShown, setCreateModalShown] = useState<boolean>(false);
   const [isUpdateModalShown, setUpdateModalShown] = useState<boolean>(false);
   const [isDeleteModalShown, setDeleteModalShown] = useState<boolean>(false);
   const [isUserGroupUserModalShown, setIsUserGroupUserModalShown] = useState<boolean>(false);
 
+  const isLoading = currentUserGroup === undefined;
+  const notExistsUerGroup = !isLoading && currentUserGroup == null;
+
+  useEffect(() => {
+    if (!objectIdUtils.isValidObjectId(currentUserGroupId) || notExistsUerGroup) {
+      router.push('/admin/user-groups');
+    }
+  }, [currentUserGroup, currentUserGroupId, notExistsUerGroup, router]);
+
+
   /*
    * Fetch
    */
+  const { data: userGroupPages } = useSWRxUserGroupPages(currentUserGroupId, 10, 0);
+
+  const { data: userGroupRelations, mutate: mutateUserGroupRelations } = useSWRxUserGroupRelations(currentUserGroupId);
+
   const { data: childUserGroupsList, mutate: mutateChildUserGroups } = useSWRxChildUserGroupList(currentUserGroupId ? [currentUserGroupId] : [], true);
   const childUserGroups = childUserGroupsList != null ? childUserGroupsList.childUserGroups : [];
   const grandChildUserGroups = childUserGroupsList != null ? childUserGroupsList.grandChildUserGroups : [];
   const childUserGroupIds = childUserGroups.map(group => group._id);
-  const { data: userGroupRelationList } = useSWRxUserGroupRelationList(childUserGroupIds);
+
+  const { data: userGroupRelationList, mutate: mutateUserGroupRelationList } = useSWRxUserGroupRelationList(childUserGroupIds);
   const childUserGroupRelations = userGroupRelationList != null ? userGroupRelationList : [];
 
-  const { data: userGroupPages } = useSWRxUserGroupPages(currentUserGroupId, 10, 0);
   const { data: selectableParentUserGroups, mutate: mutateSelectableParentUserGroups } = useSWRxSelectableParentUserGroups(currentUserGroupId);
   const { data: selectableChildUserGroups, mutate: mutateSelectableChildUserGroups } = useSWRxSelectableChildUserGroups(currentUserGroupId);
+
   const { data: ancestorUserGroups, mutate: mutateAncestorUserGroups } = useSWRxAncestorUserGroups(currentUserGroupId);
+
   const { data: isAclEnabled } = useIsAclEnabled();
 
   const { open: openUpdateParentConfirmModal } = useUpdateUserGroupConfirmModal();
 
-  // Modal function
-  // Update
-  const showUpdateModal = useCallback((group: IUserGroupHasId) => {
-    setUpdateModalShown(true);
-    setSelectedUserGroup(group);
-  }, [setUpdateModalShown]);
-
-  const hideUpdateModal = useCallback(() => {
-    setUpdateModalShown(false);
-    setSelectedUserGroup(undefined);
-  }, [setUpdateModalShown]);
-
-  // Create
-  const showCreateModal = useCallback(() => {
-    setCreateModalShown(true);
-  }, [setCreateModalShown]);
-
-  const hideCreateModal = useCallback(() => {
-    setCreateModalShown(false);
-  }, [setCreateModalShown]);
-
-  // Delete
-  const showDeleteModal = useCallback(async(group: IUserGroupHasId) => {
-    setSelectedUserGroup(group);
-    setDeleteModalShown(true);
-  }, [setSelectedUserGroup, setDeleteModalShown]);
-
-  const hideDeleteModal = useCallback(() => {
-    setSelectedUserGroup(undefined);
-    setDeleteModalShown(false);
-  }, [setSelectedUserGroup, setDeleteModalShown]);
-
   /*
    * Function
    */
@@ -209,7 +175,6 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
     try {
       await apiv3Post(`/user-groups/${currentUserGroupId}/users/${username}`);
       setIsUserGroupUserModalShown(false);
-
       mutateUserGroupRelations();
     }
     catch (err) {
@@ -222,13 +187,22 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
     try {
       await apiv3Delete(`/user-groups/${currentUserGroupId}/users/${username}`);
       toastSuccess(`Removed "${xss.process(username)}" from "${xss.process(currentUserGroup?.name)}"`);
-
-      mutateUserGroupRelations();
+      mutateUserGroupRelationList();
     }
     catch (err) {
       toastError(new Error(`Unable to remove "${xss.process(username)}" from "${xss.process(currentUserGroup?.name)}"`));
     }
-  }, [currentUserGroup?.name, currentUserGroupId, mutateUserGroupRelations, xss]);
+  }, [currentUserGroup?.name, currentUserGroupId, mutateUserGroupRelationList, xss]);
+
+  const showUpdateModal = useCallback((group: IUserGroupHasId) => {
+    setUpdateModalShown(true);
+    setSelectedUserGroup(group);
+  }, [setUpdateModalShown]);
+
+  const hideUpdateModal = useCallback(() => {
+    setUpdateModalShown(false);
+    setSelectedUserGroup(undefined);
+  }, [setUpdateModalShown]);
 
   const updateChildUserGroup = useCallback(async(userGroupData: IUserGroupHasId) => {
     try {
@@ -237,7 +211,9 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         description: userGroupData.description,
         parentId: userGroupData.parent,
       });
+
       toastSuccess(t('toaster.update_successed', { target: t('UserGroup'), ns: 'commons' }));
+
       // mutate
       mutateChildUserGroups();
 
@@ -259,6 +235,14 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
     );
   }, [openUpdateParentConfirmModal, currentUserGroupId, onSubmitUpdateGroup]);
 
+  const showCreateModal = useCallback(() => {
+    setCreateModalShown(true);
+  }, [setCreateModalShown]);
+
+  const hideCreateModal = useCallback(() => {
+    setCreateModalShown(false);
+  }, [setCreateModalShown]);
+
   const createChildUserGroup = useCallback(async(userGroupData: IUserGroup) => {
     try {
       await apiv3Post('/user-groups', {
@@ -266,6 +250,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         description: userGroupData.description,
         parentId: currentUserGroupId,
       });
+
       toastSuccess(t('toaster.update_successed', { target: t('UserGroup'), ns: 'commons' }));
 
       // mutate
@@ -280,6 +265,16 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
     }
   }, [currentUserGroupId, t, mutateChildUserGroups, mutateSelectableChildUserGroups, mutateSelectableParentUserGroups, hideCreateModal]);
 
+  const showDeleteModal = useCallback(async(group: IUserGroupHasId) => {
+    setSelectedUserGroup(group);
+    setDeleteModalShown(true);
+  }, [setSelectedUserGroup, setDeleteModalShown]);
+
+  const hideDeleteModal = useCallback(() => {
+    setSelectedUserGroup(undefined);
+    setDeleteModalShown(false);
+  }, [setSelectedUserGroup, setDeleteModalShown]);
+
   const deleteChildUserGroupById = useCallback(async(deleteGroupId: string, actionName: string, transferToUserGroupId: string) => {
     try {
       const res = await apiv3Delete(`/user-groups/${deleteGroupId}`, {
@@ -307,6 +302,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         description: userGroupData.description,
         parentId: null,
       });
+
       toastSuccess(t('toaster.update_successed', { target: t('UserGroup'), ns: 'commons' }));
 
       // mutate
@@ -357,7 +353,6 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
       </nav>
 
       <div className="mt-4 form-box">
-        <h2 className="admin-setting-header">{t('user_group_management.basic_info')}</h2>
         <UserGroupForm
           userGroup={currentUserGroup}
           selectableParentUserGroups={selectableParentUserGroups}
@@ -365,37 +360,32 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
           onSubmit={onClickSubmitForm}
         />
       </div>
-      <div>
-        <h2 className="admin-setting-header mt-4">{t('user_group_management.user_list')}</h2>
-        <UserGroupUserTable
-          userGroupRelations={userGroupRelations}
-          onClickPlusBtn={() => setIsUserGroupUserModalShown(true)}
-          onClickRemoveUserBtn={removeUserByUsername}
-        />
-      </div>
-      <div>
-        <h2 className="admin-setting-header mt-4">{t('user_group_management.child_group_list')}</h2>
-        <UserGroupDropdown
-          selectableUserGroups={selectableChildUserGroups}
-          onClickAddExistingUserGroupButton={onClickAddExistingUserGroupButtonHandler}
-          onClickCreateUserGroupButton={showCreateModal}
-        />
-        <UserGroupTable
-          userGroups={childUserGroups}
-          childUserGroups={grandChildUserGroups}
-          isAclEnabled={isAclEnabled ?? false}
-          onEdit={showUpdateModal}
-          onRemove={removeChildUserGroup}
-          onDelete={showDeleteModal}
-          userGroupRelations={childUserGroupRelations}
-        />
-      </div>
-      <div>
-        <h2 className="admin-setting-header mt-4">{t('Page')}</h2>
-        <div className={`page-list ${styles['page-list']}`}>
-          <UserGroupPageList userGroupId={currentUserGroupId} relatedPages={userGroupPages} />
-        </div>
-      </div>
+      <h2 className="admin-setting-header mt-4">{t('user_group_management.user_list')}</h2>
+      <UserGroupUserTable
+        userGroupRelations={userGroupRelations}
+        onClickPlusBtn={() => setIsUserGroupUserModalShown(true)}
+        onClickRemoveUserBtn={removeUserByUsername}
+      />
+      <UserGroupUserModal
+        isOpen={isUserGroupUserModalShown}
+        userGroup={currentUserGroup}
+        searchType={searchType}
+        isAlsoMailSearched={isAlsoMailSearched}
+        isAlsoNameSearched={isAlsoNameSearched}
+        onClickAddUserBtn={addUserByUsername}
+        onSearchApplicableUsers={fetchApplicableUsers}
+        onSwitchSearchType={switchSearchType}
+        onClose={() => setIsUserGroupUserModalShown(false)}
+        onToggleIsAlsoMailSearched={toggleIsAlsoMailSearched}
+        onToggleIsAlsoNameSearched={toggleAlsoNameSearched}
+      />
+
+      <h2 className="admin-setting-header mt-4">{t('user_group_management.child_group_list')}</h2>
+      <UserGroupDropdown
+        selectableUserGroups={selectableChildUserGroups}
+        onClickAddExistingUserGroupButton={onClickAddExistingUserGroupButtonHandler}
+        onClickCreateUserGroupButton={showCreateModal}
+      />
 
       <UserGroupModal
         userGroup={selectedUserGroup}
@@ -404,27 +394,26 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         isShow={isUpdateModalShown}
         onHide={hideUpdateModal}
       />
+
       <UserGroupModal
-        userGroup={undefined}
         buttonLabel={t('Create')}
         onClickSubmit={createChildUserGroup}
         isShow={isCreateModalShown}
         onHide={hideCreateModal}
       />
+
       <UpdateParentConfirmModal />
-      <UserGroupUserModal
-        isOpen={isUserGroupUserModalShown}
-        userGroup={currentUserGroup}
-        searchType={searchType}
-        isAlsoMailSearched={isAlsoMailSearched}
-        isAlsoNameSearched={isAlsoNameSearched}
-        onClickAddUserBtn={addUserByUsername}
-        onSearchApplicableUsers={fetchApplicableUsers}
-        onSwitchSearchType={switchSearchType}
-        onClose={() => setIsUserGroupUserModalShown(false)}
-        onToggleIsAlsoMailSearched={toggleIsAlsoMailSearched}
-        onToggleIsAlsoNameSearched={toggleAlsoNameSearched}
+
+      <UserGroupTable
+        userGroups={childUserGroups}
+        childUserGroups={grandChildUserGroups}
+        isAclEnabled={isAclEnabled ?? false}
+        onEdit={showUpdateModal}
+        onRemove={removeChildUserGroup}
+        onDelete={showDeleteModal}
+        userGroupRelations={childUserGroupRelations}
       />
+
       <UserGroupDeleteModal
         userGroups={childUserGroups}
         deleteUserGroup={selectedUserGroup}
@@ -432,6 +421,11 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         isShow={isDeleteModalShown}
         onHide={hideDeleteModal}
       />
+
+      <h2 className="admin-setting-header mt-4">{t('Page')}</h2>
+      <div className={`page-list ${styles['page-list']}`}>
+        <UserGroupPageList userGroupId={currentUserGroupId} relatedPages={userGroupPages} />
+      </div>
     </div>
   );
 };