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

Merge pull request #5600 from weseek/feat/91119-remove-child-group

feat: Remove child group from parent group
Yuki Takei 4 лет назад
Родитель
Сommit
97b76e98fa

+ 1 - 0
packages/app/resource/locales/en_US/admin/admin.json

@@ -472,6 +472,7 @@
   "user_group_management": {
     "create_group": "Create new group",
     "add_child_group": "Add child group",
+    "remove_child_group": "Remove",
     "deny_create_group": "You can't create a new group with the current settings.",
     "group_name": "Group name",
     "group_example": "e.g. : Group1",

+ 1 - 0
packages/app/resource/locales/ja_JP/admin/admin.json

@@ -471,6 +471,7 @@
   "user_group_management": {
     "create_group": "新規グループの作成",
     "add_child_group": "子グループの追加",
+    "remove_child_group": "解除",
     "deny_create_group": "新規グループの作成はできません。",
     "group_name": "グループ名",
     "group_example": "例: Group1",

+ 1 - 0
packages/app/resource/locales/zh_CN/admin/admin.json

@@ -481,6 +481,7 @@
   "user_group_management": {
     "create_group": "创建新组",
     "add_child_group": "添加一个子组",
+    "remove_child_group": "移除",
     "deny_create_group": "不能用当前设置创建新组。",
     "group_name": "组名",
     "group_example": "e.g.:第1组",

+ 25 - 1
packages/app/src/components/Admin/UserGroup/UserGroupTable.tsx

@@ -1,6 +1,7 @@
 import React, {
   FC, useState, useCallback, useEffect,
 } from 'react';
+
 import { useTranslation } from 'react-i18next';
 import { TFunctionResult } from 'i18next';
 import dateFnsFormat from 'date-fns/format';
@@ -16,6 +17,7 @@ type Props = {
   childUserGroups: IUserGroupHasId[],
   isAclEnabled: boolean,
   onEdit?: (userGroup: IUserGroupHasId) => void | Promise<void>,
+  onRemove?: (userGroup: IUserGroupHasId) => void | Promise<void>,
   onDelete?: (userGroup: IUserGroupHasId) => void | Promise<void>,
 };
 
@@ -73,7 +75,7 @@ const UserGroupTable: FC<Props> = (props: Props) => {
     });
   };
 
-  const onClickEdit = (e) => {
+  const onClickEdit = async(e) => {
     if (props.onEdit == null) {
       return;
     }
@@ -86,6 +88,25 @@ const UserGroupTable: FC<Props> = (props: Props) => {
     props.onEdit(userGroup);
   };
 
+  const onClickRemove = async(e) => {
+    if (props.onRemove == null) {
+      return;
+    }
+
+    const userGroup = findUserGroup(e);
+    if (userGroup == null) {
+      return;
+    }
+
+    try {
+      await props.onRemove(userGroup);
+      userGroup.parent = null;
+    }
+    catch {
+      //
+    }
+  };
+
   const onClickDelete = (e) => { // no preventDefault
     if (props.onDelete == null) {
       return;
@@ -179,6 +200,9 @@ const UserGroupTable: FC<Props> = (props: Props) => {
                           <button className="dropdown-item" type="button" role="button" onClick={onClickEdit} data-user-group-id={group._id}>
                             <i className="icon-fw icon-note"></i> {t('Edit')}
                           </button>
+                          <button className="dropdown-item" type="button" role="button" onClick={onClickRemove} data-user-group-id={group._id}>
+                            <i className="icon-fw fa fa-chain-broken"></i> {t('admin:user_group_management.remove_child_group')}
+                          </button>
                           <button className="dropdown-item" type="button" role="button" onClick={onClickDelete} data-user-group-id={group._id}>
                             <i className="icon-fw icon-fire text-danger"></i> {t('Delete')}
                           </button>

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

@@ -267,6 +267,26 @@ const UserGroupDetailPage: FC = () => {
     }
   }, [mutateChildUserGroups, setSelectedUserGroup, setDeleteModalShown]);
 
+  const removeChildUserGroup = useCallback(async(userGroupData: IUserGroupHasId) => {
+    try {
+      await apiv3Put(`/user-groups/${userGroupData._id}`, {
+        name: userGroupData.name,
+        description: userGroupData.description,
+        parentId: null,
+      });
+
+      toastSuccess(t('toaster.update_successed', { target: t('UserGroup') }));
+
+      // mutate
+      mutateChildUserGroups();
+      mutateSelectableChildUserGroups();
+    }
+    catch (err) {
+      toastError(err);
+      throw err;
+    }
+  }, [t, mutateChildUserGroups, mutateSelectableChildUserGroups]);
+
   /*
    * Dependencies
    */
@@ -337,6 +357,7 @@ const UserGroupDetailPage: FC = () => {
         childUserGroups={grandChildUserGroups}
         isAclEnabled={isAclEnabled ?? false}
         onEdit={showUpdateModal}
+        onRemove={removeChildUserGroup}
         onDelete={showDeleteModal}
         userGroupRelations={childUserGroupRelations}
       />

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

@@ -49,7 +49,7 @@ module.exports = (crowi) => {
     update: [
       body('name', 'Group name must be a string').optional().trim().isString(),
       body('description', 'Group description must be a string').optional().isString(),
-      body('parentId', 'parentId must be a string').optional().isString(),
+      body('parentId', 'ParentId must be a string or null').optional({ nullable: true }).isString(),
       body('forceUpdateParents', 'forceUpdateParents must be a boolean').optional().isBoolean(),
     ],
     delete: [