diff --git a/packages/global/common/error/code/team.ts b/packages/global/common/error/code/team.ts index 7101364421de..7063695a14dd 100644 --- a/packages/global/common/error/code/team.ts +++ b/packages/global/common/error/code/team.ts @@ -19,6 +19,8 @@ export enum TeamErrEnum { orgMemberNotExist = 'orgMemberNotExist', orgMemberExist = 'orgMemberExist', orgNotExist = 'orgNotExist', + orgMoveSameParent = 'orgMoveSameParent', + orgMoveToChildren = 'orgMoveToChildren', orgParentNotExist = 'orgParentNotExist', deletingOrgWithChildren = 'deletingOrgWithChildren', deletingRootOrg = 'deletingRootOrg', diff --git a/packages/global/support/user/team/org/api.d.ts b/packages/global/support/user/team/org/api.d.ts index f7b9a5f222e0..eb6080b2997d 100644 --- a/packages/global/support/user/team/org/api.d.ts +++ b/packages/global/support/user/team/org/api.d.ts @@ -5,7 +5,6 @@ type postCreateOrgData = { parentId: string; description?: string; avatar?: string; - ownerTmbId?: string; }; type putUpdateOrgMembersData = { diff --git a/packages/global/support/user/team/org/type.d.ts b/packages/global/support/user/team/org/type.d.ts index 9a2e71bd3594..88f23dd2e7b8 100644 --- a/packages/global/support/user/team/org/type.d.ts +++ b/packages/global/support/user/team/org/type.d.ts @@ -1,6 +1,6 @@ -import { OrgMemberRole } from './constant'; +import type { TeamPermission } from 'support/permission/user/controller'; import { ResourcePermissionType } from '../type'; -import { TeamPermission } from 'support/permission/user/controller'; +import type { OrgMemberRole } from './constant'; type OrgSchemaType = { _id: string; diff --git a/packages/service/support/permission/org/controllers.ts b/packages/service/support/permission/org/controllers.ts index ddb66db9ead3..2be7740fa569 100644 --- a/packages/service/support/permission/org/controllers.ts +++ b/packages/service/support/permission/org/controllers.ts @@ -1,13 +1,13 @@ -import { MongoOrgMemberModel } from './orgMemberSchema'; -import { MongoOrgModel } from './orgSchema'; -import { OrgMemberRole } from '@fastgpt/global/support/user/team/org/constant'; -import type { AuthModeType, AuthResponseType } from '../type'; -import { parseHeaderCert } from '../controller'; +import { TeamErrEnum } from '@fastgpt/global/common/error/code/team'; import { TeamPermission } from '@fastgpt/global/support/permission/user/controller'; -import { getTmbInfoByTmbId } from '../../user/team/controller'; +import { OrgMemberRole } from '@fastgpt/global/support/user/team/org/constant'; import type { OrgSchemaType } from '@fastgpt/global/support/user/team/org/type'; -import { TeamErrEnum } from '@fastgpt/global/common/error/code/team'; import type { ClientSession } from 'mongoose'; +import { getTmbInfoByTmbId } from '../../user/team/controller'; +import { parseHeaderCert } from '../controller'; +import type { AuthModeType, AuthResponseType } from '../type'; +import { MongoOrgMemberModel } from './orgMemberSchema'; +import { MongoOrgModel } from './orgSchema'; // if role1 > role2, return 1 // if role1 < role2, return -1 @@ -90,7 +90,7 @@ export const getOrgMemberRole = async ({ } else { return role; } - if (role == OrgMemberRole.owner) { + if (role === OrgMemberRole.owner) { return role; } // Check the parent orgs @@ -114,7 +114,8 @@ export const getOrgMemberRole = async ({ if (parentRole === OrgMemberRole.owner) { role = parentRole; break; - } else if (parentRole === OrgMemberRole.admin && role === OrgMemberRole.member) { + } + if (parentRole === OrgMemberRole.admin && role === OrgMemberRole.member) { role = parentRole; } } diff --git a/packages/service/support/permission/org/orgSchema.ts b/packages/service/support/permission/org/orgSchema.ts index 5936d730accc..3d5657f5276a 100644 --- a/packages/service/support/permission/org/orgSchema.ts +++ b/packages/service/support/permission/org/orgSchema.ts @@ -1,13 +1,13 @@ import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant'; +import { OrgCollectionName } from '@fastgpt/global/support/user/team/org/constant'; +import type { OrgSchemaType } from '@fastgpt/global/support/user/team/org/type'; import { connectionMongo, getMongoModel } from '../../../common/mongo'; -import { OrgMemberCollectionName } from './orgMemberSchema'; import { ResourcePermissionCollectionName } from '../schema'; -import { OrgSchemaType } from '@fastgpt/global/support/user/team/org/type'; -import { OrgCollectionName } from '@fastgpt/global/support/user/team/org/constant'; +import { OrgMemberCollectionName } from './orgMemberSchema'; const { Schema } = connectionMongo; function requiredStringPath(this: OrgSchemaType) { - return typeof this.path === 'string' ? false : true; + return typeof this.path !== 'string'; } export const OrgSchema = new Schema( diff --git a/packages/web/i18n/en/account_team.json b/packages/web/i18n/en/account_team.json index 25fcea4189a9..65976bba3ad4 100644 --- a/packages/web/i18n/en/account_team.json +++ b/packages/web/i18n/en/account_team.json @@ -3,6 +3,7 @@ "confirm_delete_group": "Confirm to delete group?", "confirm_leave_team": "Confirmed to leave the team? \n \nAfter you log out, all your resources in the team (applications, knowledge bases, folders, managed groups, etc.) will be transferred to the team owner.", "confirm_delete_org": "Confirm to delete organization?", + "confirm_delete_member": "Confirm to delete member?", "create_group": "Create group", "delete": "delete", "edit_info": "Edit information", @@ -15,6 +16,7 @@ "create_sub_org": "Create sub-organization", "edit_org_info": "Edit organization information", "move_org": "Move organization", + "move_member": "Move member", "delete_org": "Delete organization", "remark": "remark", "label_sync": "Tag sync", diff --git a/packages/web/i18n/zh-CN/account_team.json b/packages/web/i18n/zh-CN/account_team.json index 84519765b8f0..f63470682e26 100644 --- a/packages/web/i18n/zh-CN/account_team.json +++ b/packages/web/i18n/zh-CN/account_team.json @@ -30,8 +30,10 @@ "create_sub_org": "创建子组织", "edit_org_info": "编辑组织信息", "move_org": "移动组织", + "move_member": "移动成员", "delete_org": "删除组织", "confirm_delete_org": "确认删除组织?", + "confirm_delete_member": "确认删除成员?", "transfer_ownership": "转让所有者", "delete": "删除", diff --git a/packages/web/i18n/zh-Hant/account_team.json b/packages/web/i18n/zh-Hant/account_team.json index 67372b1e4488..bffc37abd9d5 100644 --- a/packages/web/i18n/zh-Hant/account_team.json +++ b/packages/web/i18n/zh-Hant/account_team.json @@ -3,6 +3,7 @@ "confirm_delete_group": "確認刪除群組?", "confirm_leave_team": "確認離開該團隊? \n \n退出後,您在該團隊所有的資源( 應用程式、知識庫、資料夾、管理的群組等)均轉讓給團隊所有者。", "confirm_delete_org": "確認刪除組織?", + "confirm_delete_member": "確認刪除成員?", "create_group": "建立群組", "delete": "刪除", "edit_info": "編輯訊息", @@ -15,6 +16,7 @@ "create_sub_org": "建立子組織", "edit_org_info": "編輯組織訊息", "move_org": "移動組織", + "move_member": "移動成員", "delete_org": "刪除組織", "remark": "備註", "label_sync": "標籤同步", diff --git a/projects/app/src/pages/account/team/components/OrgManage/OrgInfoModal.tsx b/projects/app/src/pages/account/team/components/OrgManage/OrgInfoModal.tsx index fa3b7b37ec46..56b7850cbdf5 100644 --- a/projects/app/src/pages/account/team/components/OrgManage/OrgInfoModal.tsx +++ b/projects/app/src/pages/account/team/components/OrgManage/OrgInfoModal.tsx @@ -48,7 +48,6 @@ function OrgInfoModal({ setValue('name', editOrg?.name ?? ''); setValue('avatar', editOrg?.avatar); setValue('description', editOrg?.description); - console.log(editOrg); }, [editOrg, setValue]); const { run: onCreate, loading: isLoadingCreate } = useRequest2( diff --git a/projects/app/src/pages/account/team/components/OrgManage/OrgMemberModal.tsx b/projects/app/src/pages/account/team/components/OrgManage/OrgMemberModal.tsx new file mode 100644 index 000000000000..d36c0837ae80 --- /dev/null +++ b/projects/app/src/pages/account/team/components/OrgManage/OrgMemberModal.tsx @@ -0,0 +1,299 @@ +import { putUpdateOrgMembers } from '@/web/support/user/team/org/api'; +import { useUserStore } from '@/web/support/user/useUserStore'; +import { + Box, + Button, + Checkbox, + Flex, + Grid, + HStack, + ModalBody, + ModalFooter +} from '@chakra-ui/react'; +import { DEFAULT_TEAM_AVATAR } from '@fastgpt/global/common/system/constants'; +import type { GroupMemberRole } from '@fastgpt/global/support/permission/memberGroup/constant'; +import type { OrgMemberRole } from '@fastgpt/global/support/user/team/org/constant'; +import Avatar from '@fastgpt/web/components/common/Avatar'; +import MyIcon from '@fastgpt/web/components/common/Icon'; +import type { IconNameType } from '@fastgpt/web/components/common/Icon/type'; +import SearchInput from '@fastgpt/web/components/common/Input/SearchInput'; +import MyModal from '@fastgpt/web/components/common/MyModal'; +import Tag from '@fastgpt/web/components/common/Tag'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; +import { useToast } from '@fastgpt/web/hooks/useToast'; +import { useTranslation } from 'next-i18next'; +import type React from 'react'; +import { useEffect, useMemo, useState } from 'react'; +import { useContextSelector } from 'use-context-selector'; +import { TeamContext } from '../context'; + +export type GroupFormType = { + members: { + tmbId: string; + role: `${GroupMemberRole}`; + }[]; +}; + +function CheckboxIcon({ + name +}: { + isChecked?: boolean; + isIndeterminate?: boolean; + name: IconNameType; +}) { + return ; +} + +function OrgMemberModal({ onClose, editOrgId }: { onClose: () => void; editOrgId?: string }) { + // 1. Owner can not be deleted, toast + // 2. Owner/Admin can manage members + // 3. Owner can add/remove admins + const { t } = useTranslation(); + const { userInfo } = useUserStore(); + const { toast } = useToast(); + const [hoveredMemberId, setHoveredMemberId] = useState(undefined); + const { + members: allMembers, + orgs, + refetchOrgs, + refetchMembers + } = useContextSelector(TeamContext, (v) => v); + + const org = useMemo(() => orgs.find((item) => item._id === editOrgId), [editOrgId, orgs]); + + const [members, setMembers] = useState<{ tmbId: string; role: `${OrgMemberRole}` }[]>( + org?.members || [] + ); + + useEffect(() => { + setMembers(org?.members || []); + }, [org]); + + const [searchKey, setSearchKey] = useState(''); + const filtered = useMemo(() => { + return [ + ...allMembers.filter((member) => { + if (member.memberName.toLowerCase().includes(searchKey.toLowerCase())) return true; + return false; + }) + ]; + }, [searchKey, allMembers]); + + const { run: onUpdate, loading: isLoadingUpdate } = useRequest2( + async () => { + if (!editOrgId) return; + return putUpdateOrgMembers({ + orgId: editOrgId, + members + }); + }, + { + onSuccess: () => Promise.all([onClose(), refetchOrgs(), refetchMembers()]) + } + ); + + const isSelected = (memberId: string) => { + return members.find((item) => item.tmbId === memberId); + }; + + const myRole = useMemo(() => { + if (userInfo?.team.permission.hasManagePer) { + return 'owner'; + } + return members.find((item) => item.tmbId === userInfo?.team.tmbId)?.role ?? 'member'; + }, [members, userInfo]); + + const handleToggleSelect = (memberId: string) => { + if ( + myRole === 'owner' && + memberId === org?.members.find((item) => item.role === 'owner')?.tmbId + ) { + toast({ + title: t('user:team.group.toast.can_not_delete_owner'), + status: 'error' + }); + return; + } + + if ( + myRole === 'admin' && + org?.members.find((item) => String(item.tmbId) === memberId)?.role !== 'member' + ) { + return; + } + + if (isSelected(memberId)) { + setMembers(members.filter((item) => item.tmbId !== memberId)); + } else { + setMembers([...members, { tmbId: memberId, role: 'member' }]); + } + }; + + const handleToggleAdmin = (memberId: string) => { + if (myRole === 'owner' && isSelected(memberId)) { + const oldRole = members.find((item) => item.tmbId === memberId)?.role; + if (oldRole === 'admin') { + setMembers( + members.map((item) => (item.tmbId === memberId ? { ...item, role: 'member' } : item)) + ); + } else { + setMembers( + members.map((item) => (item.tmbId === memberId ? { ...item, role: 'admin' } : item)) + ); + } + } + }; + + const isLoading = isLoadingUpdate; + return ( + + + + + { + setSearchKey(e.target.value); + }} + /> + + {filtered.map((member) => { + return ( + handleToggleSelect(member.tmbId)} + > + } + pointerEvents="none" + /> + + {member.memberName} + + ); + })} + + + + {`${t('common:chosen')}:${members.length}`} + + {members.map((member) => { + return ( + setHoveredMemberId(member.tmbId)} + onMouseLeave={() => setHoveredMemberId(undefined)} + justifyContent="space-between" + py="2" + px={3} + borderRadius={'md'} + key={member.tmbId + member.role} + _hover={{ bg: 'myGray.50' }} + _notLast={{ mb: 2 }} + > + + item.tmbId === member.tmbId)?.avatar} + w="1.5rem" + borderRadius={'md'} + /> + + {allMembers.find((item) => item.tmbId === member.tmbId)?.memberName} + + + + {(() => { + if (member.role === 'owner') { + return ( + + {t('user:team.group.role.owner')} + + ); + } + if (member.role === 'admin') { + return ( + + {t('user:team.group.role.admin')} + {myRole === 'owner' && ( + handleToggleAdmin(member.tmbId)} + /> + )} + + ); + } + if (member.role === 'member') { + return ( + myRole === 'owner' && + hoveredMemberId === member.tmbId && ( + handleToggleAdmin(member.tmbId)} + > + {t('user:team.group.set_as_admin')} + + ) + ); + } + })()} + + {(myRole === 'owner' || (myRole === 'admin' && member.role === 'member')) && ( + handleToggleSelect(member.tmbId)} + /> + )} + + ); + })} + + + + + + + + + ); +} + +export default OrgMemberModal; diff --git a/projects/app/src/pages/account/team/components/OrgManage/OrgMoveModal.tsx b/projects/app/src/pages/account/team/components/OrgManage/OrgMoveModal.tsx index c8af2ee1eea3..5a356bef728e 100644 --- a/projects/app/src/pages/account/team/components/OrgManage/OrgMoveModal.tsx +++ b/projects/app/src/pages/account/team/components/OrgManage/OrgMoveModal.tsx @@ -1,15 +1,78 @@ -import { Modal, ModalBody } from '@chakra-ui/react'; +import { putMoveOrg, putMoveOrgMember } from '@/web/support/user/team/org/api'; +import { Button, Modal, ModalBody, ModalFooter } from '@chakra-ui/react'; import type { OrgType } from '@fastgpt/global/support/user/team/org/type'; -import type { TeamTmbItemType } from '@fastgpt/global/support/user/team/type'; +import type { TeamMemberItemType, TeamTmbItemType } from '@fastgpt/global/support/user/team/type'; import MyModal from '@fastgpt/web/components/common/MyModal'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; +import { useTranslation } from 'next-i18next'; +import { useState } from 'react'; import OrgTree from './OrgTree'; -function OrgMoveModal({ orgs, team }: { orgs: OrgType[]; team: TeamTmbItemType }) { +function OrgMoveModal({ + movingOrg, + movingTmb, + orgs, + team, + onClose, + onSuccess +}: { + movingOrg?: OrgType; + movingTmb?: { tmbId: string; orgId: string }; + orgs: OrgType[]; + team: TeamTmbItemType; + onClose: () => void; + onSuccess: () => void; +}) { + const { t } = useTranslation(); + const [selectedOrg, selectOrg] = useState(); + + const { runAsync: moveOrg, loading: loadingOrg } = useRequest2(putMoveOrg, { + onSuccess: () => { + onClose(); + onSuccess(); + } + }); + + const { runAsync: moveTmb, loading: loadingTmb } = useRequest2(putMoveOrgMember, { + onSuccess: () => { + onClose(); + onSuccess(); + } + }); + + const handleConfirm = () => { + if (!selectedOrg) return; + if (movingTmb) { + moveTmb(movingTmb.orgId, movingTmb.tmbId, selectedOrg._id); + } else if (movingOrg) { + moveOrg(movingOrg._id, selectedOrg._id); + } + }; + + const loading = loadingOrg || loadingTmb; + return ( - + - + + + + ); } diff --git a/projects/app/src/pages/account/team/components/OrgManage/OrgTree.tsx b/projects/app/src/pages/account/team/components/OrgManage/OrgTree.tsx index ce850cd9c1bc..7d91f6fe82ad 100644 --- a/projects/app/src/pages/account/team/components/OrgManage/OrgTree.tsx +++ b/projects/app/src/pages/account/team/components/OrgManage/OrgTree.tsx @@ -26,12 +26,14 @@ function OrgTreeNode({ const [isExpanded, toggleIsExpanded] = useToggle(false); return ( - + @@ -48,20 +50,18 @@ function OrgTreeNode({ {org.name} - {isExpanded && children.length > 0 && ( - - {children.map((child) => ( - - ))} - - )} + {isExpanded && + children.length > 0 && + children.map((child) => ( + + ))} ); } @@ -69,23 +69,31 @@ function OrgTreeNode({ function OrgTree({ orgs, teamName, - teamAvatar -}: { orgs: OrgType[]; teamAvatar: string; teamName: string }) { + teamAvatar, + selectedOrg, + selectOrg +}: { + orgs: OrgType[]; + teamAvatar: string; + teamName: string; + selectedOrg?: OrgType; + selectOrg?: (org: OrgType | undefined) => void; +}) { const root = orgs[0]; if (!root) return null; const children = useMemo( () => orgs.filter((item) => item.path === `${root.path}/${root._id}`), [root, orgs] ); - const [selectedOrg, selectOrg] = useState(); return ( - + selectOrg?.(root)} cursor="pointer" - _hover={{ bgColor: 'gray.100' }} + _hover={{ bgColor: selectedOrg === root ? 'blue.200' : 'gray.100' }} borderRadius="4px" + p="4px" transition={'background 0.1s'} {...(selectedOrg === root ? { bgColor: 'blue.100' } : {})} > diff --git a/projects/app/src/pages/account/team/components/OrgManage/index.tsx b/projects/app/src/pages/account/team/components/OrgManage/index.tsx index b4cd28443cdb..33703744916b 100644 --- a/projects/app/src/pages/account/team/components/OrgManage/index.tsx +++ b/projects/app/src/pages/account/team/components/OrgManage/index.tsx @@ -1,4 +1,4 @@ -import { deleteOrg } from '@/web/support/user/team/org/api'; +import { deleteOrg, deleteOrgMember } from '@/web/support/user/team/org/api'; import { useUserStore } from '@/web/support/user/useUserStore'; import { Box, @@ -22,21 +22,19 @@ import { import { DEFAULT_ORG_AVATAR } from '@fastgpt/global/common/system/constants'; import type { OrgType } from '@fastgpt/global/support/user/team/org/type'; import Avatar from '@fastgpt/web/components/common/Avatar'; -import AvatarGroup from '@fastgpt/web/components/common/Avatar/AvatarGroup'; import MyIcon from '@fastgpt/web/components/common/Icon'; import type { IconNameType } from '@fastgpt/web/components/common/Icon/type'; -import MyBox from '@fastgpt/web/components/common/MyBox'; -import MyMenu, { MenuItemType } from '@fastgpt/web/components/common/MyMenu'; +import MyMenu from '@fastgpt/web/components/common/MyMenu'; import { useConfirm } from '@fastgpt/web/hooks/useConfirm'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useTranslation } from 'next-i18next'; -import dynamic from 'next/dynamic'; import { useEffect, useMemo, useState } from 'react'; import { useContextSelector } from 'use-context-selector'; import MemberTag from '../../../../../components/support/user/team/Info/MemberTag'; import { TeamContext } from '../context'; import IconButton from './IconButton'; import OrgInfoModal from './OrgInfoModal'; +import OrgMemberModal from './OrgMemberModal'; import OrgMoveModal from './OrgMoveModal'; function ActionButton({ @@ -105,7 +103,28 @@ function MemberTable() { [orgs, currentOrg] ); + const orgList = useMemo( + () => + orgs + .filter((org) => org.path === currentPath.path) + .map((org) => { + // calc org members count + let count = org.members.length; + for (const item of orgs.filter((item) => + item.path.startsWith(`${org.path}/${org._id}`) + )) { + count += item.members.length; + } + + return { ...org, count }; + }), + [orgs, currentPath] + ); + const [editOrg, setEditOrg] = useState(); + const [editMemberOrgId, setEditMemberOrgId] = useState(); + const [movingOrg, setMovingOrg] = useState(); + const [movingTmb, setMovingTmb] = useState<{ tmbId: string; orgId: string } | undefined>(); const [createOrgParentId, setCreateOrgParentId] = useState(); const { ConfirmModal: ConfirmDeleteOrgModal, openConfirm: openDeleteOrgModal } = useConfirm({ @@ -113,14 +132,27 @@ function MemberTable() { content: t('account_team:confirm_delete_org') }); + const { ConfirmModal: ConfirmDeleteMember, openConfirm: openDeleteMemberModal } = useConfirm({ + type: 'delete', + content: t('account_team:confirm_delete_member') + }); + const { runAsync: deleteOrgReq } = useRequest2(deleteOrg, { onSuccess: () => { refetchOrgs(); refetchMembers(); } }); + const { runAsync: deleteMemberReq } = useRequest2(deleteOrgMember, { + onSuccess: () => { + refetchOrgs(); + refetchMembers(); + } + }); const deleteOrgHandler = (orgId: string) => openDeleteOrgModal(() => deleteOrgReq(orgId))(); + const deleteMemberHandler = (orgId: string, tmbId: string) => + openDeleteMemberModal(() => deleteMemberReq(orgId, tmbId))(); return ( @@ -152,60 +184,53 @@ function MemberTable() { - {orgs - .filter((org) => org.path === currentPath.path) - .map((org) => ( - - - setCurrentOrg(org)}> - - {org.members.length} - - - + {orgList.map((org) => ( + + + setCurrentOrg(org)}> + + {org.count} + + + - - + + + } + menuList={[ + { + children: [ + { + icon: 'edit', + label: t('account_team:edit_info'), + onClick: () => setEditOrg(org) + }, + { + icon: 'common/file/move', + label: t('common:Move'), + onClick: () => setMovingOrg(org) + }, + { + icon: 'delete', + label: t('account_team:delete'), + type: 'danger', + onClick: () => deleteOrgHandler(org._id) + } + ] } - menuList={[ - { - children: [ - { - icon: 'edit', - label: t('account_team:edit_info'), - onClick: () => { - setEditOrg(org); - } - }, - { - icon: 'common/file/move', - label: t('common:Move'), - onClick: () => { - // TODO - console.log(org._id); - } - }, - { - icon: 'delete', - label: t('account_team:delete'), - type: 'danger', - onClick: () => deleteOrgHandler(org._id) - } - ] - } - ]} - /> - - - ))} + ]} + /> + + + ))} {currentOrg?.members.map((member) => { const memberInfo = members.find((m) => m.tmbId === member.tmbId); if (!memberInfo) return null; @@ -215,43 +240,46 @@ function MemberTable() { - - } - menuList={[ - { - children: [ - { - icon: 'edit', - label: t('account_team:remark'), - onClick: () => { - // TODO - console.log(member.tmbId); - } - }, - { - icon: 'common/file/move', - label: t('common:Move'), - onClick: () => { - // TODO - console.log(member.tmbId); - } - }, - { - icon: 'delete', - label: t('account_team:delete'), - type: 'danger', - onClick: () => { - // TODO - console.log(member.tmbId); - } - } - ] + {member.role !== 'owner' && ( + } - ]} - /> + menuList={[ + { + children: [ + // { + // icon: 'edit', + // label: t('account_team:remark'), + // onClick: () => { + // // TODO + // console.log(member.tmbId); + // } + // }, + { + icon: 'common/file/move', + label: t('common:Move'), + onClick: () => + setMovingTmb({ tmbId: member.tmbId, orgId: currentOrg!._id }) + }, + { + icon: 'delete', + label: t('account_team:delete'), + type: 'danger', + onClick: () => deleteMemberHandler(currentOrg!._id, member.tmbId) + } + ] + } + ]} + /> + )} ); @@ -299,20 +327,14 @@ function MemberTable() { { - // TODO - console.log('manage member'); - }} + onClick={() => setEditMemberOrgId(currentOrg?._id)} /> {currentOrg?.path !== '' && ( <> { - // TODO - console.log('move org'); - }} + onClick={() => setMovingOrg(currentOrg)} /> - + { + setMovingOrg(undefined); + setMovingTmb(undefined); + }} + onSuccess={() => { + refetchOrgs(); + refetchMembers(); + }} + /> + setEditMemberOrgId(undefined)} /> + ); } diff --git a/projects/app/src/web/support/user/team/org/api.ts b/projects/app/src/web/support/user/team/org/api.ts index 1c0cc79b57b4..a8b2fbc74327 100644 --- a/projects/app/src/web/support/user/team/org/api.ts +++ b/projects/app/src/web/support/user/team/org/api.ts @@ -1,11 +1,10 @@ import { DELETE, GET, POST, PUT } from '@/web/common/api/request'; -import { OrgType } from '@fastgpt/global/support/user/team/org/type'; -import { +import type { postCreateOrgData, putUpdateOrgData, - putUpdateOrgMembersData, - putChnageOrgOwnerData + putUpdateOrgMembersData } from '@fastgpt/global/support/user/team/org/api'; +import type { OrgType } from '@fastgpt/global/support/user/team/org/type'; export const getOrgList = () => GET('/proApi/support/user/team/org/list'); @@ -15,14 +14,20 @@ export const postCreateOrg = (data: postCreateOrgData) => export const deleteOrg = (orgId: string) => DELETE('/proApi/support/user/team/org/delete', { orgId }); +export const deleteOrgMember = (orgId: string, tmbId: string) => + DELETE('/proApi/support/user/team/org/deleteMember', { orgId, tmbId }); + export const putMoveOrg = (orgId: string, parentId: string) => PUT('/proApi/support/user/team/org/move', { orgId, parentId }); +export const putMoveOrgMember = (orgId: string, tmbId: string, newOrgId: string) => + PUT('/proApi/support/user/team/org/moveMember', { orgId, tmbId, newOrgId }); + export const putUpdateOrg = (data: putUpdateOrgData) => PUT('/proApi/support/user/team/org/update', data); export const putUpdateOrgMembers = (data: putUpdateOrgMembersData) => PUT('/proApi/support/user/team/org/updateMembers', data); -export const putChnageOrgOwner = (data: putChnageOrgOwnerData) => - PUT('/proApi/support/user/team/org/changeOwner', data); +// export const putChnageOrgOwner = (data: putChnageOrgOwnerData) => +// PUT('/proApi/support/user/team/org/changeOwner', data);