* feat: add customize toolkit (#3205) * chaoyang * fix-auth * add toolkit * add order * plugin usage * fix * delete console: * Fix: Fix fullscreen preview top positioning and improve Markdown rendering logic (#3247) * 完成任务:修复全屏预览顶部固定问题,优化 Markdown 渲染逻辑 * 有问题修改 * 问题再修改 * 修正问题 * fix: plugin standalone display issue (#3254) * 4.8.15 test (#3246) * o1 config * perf: system plugin code * 调整系统插件代码。增加html 渲染安全配置。 (#3258) * perf: base64 picker * perf: list app or dataset * perf: plugin config code * 小窗适配等问题 (#3257) * 小窗适配等问题 * git问题 * 小窗剩余问题 * feat: system plugin auth and lock version (#3265) * feat: system plugin auth and lock version * update comment * 4.8.15 test (#3267) * tmp log * perf: login direct * perf: iframe html code * remove log * fix: plugin standalone display (#3277) * refactor: 页面拆分&i18n拆分 (#3281) * refactor: account组件拆成独立页面 * script: 新增i18n json文件创建脚本 * refactor: 页面i18n拆分 * i18n: add en&hant * 4.8.15 test (#3285) * tmp log * remove log * fix: watch avatar refresh * perf: i18n code * fix(plugin): use intro instead of userguide (#3290) * Universal SSO (#3292) * tmp log * remove log * feat: common oauth * readme * perf: sso provider * remove sso code * perf: refresh plugins * feat: add api dataset (#3272) * add api-dataset * fix api-dataset * fix api dataset * fix ts * perf: create collection code (#3301) * tmp log * remove log * perf: i18n change * update version doc * feat: question guide from chatId * perf: create collection code * fix: request api * fix: request api * fix: tts auth and response type (#3303) * perf: md splitter * fix: tts auth and response type * fix: api file dataset (#3307) * perf: api dataset init (#3310) * perf: collection schema * perf: api dataset init * refactor: 团队管理独立页面 (#3302) * ui: 团队管理独立页面 * 代码优化 * fix * perf: sync collection and ui check (#3314) * perf: sync collection * remove script * perf: update api server * perf: api dataset parent * perf: team ui * perf: team 18n * update team ui * perf: ui check * perf: i18n * fix: debug variables & cronjob & system plugin callback load (#3315) * fix: debug variables & cronjob & system plugin callback load * fix type * fix * fix * fix: plugin dataset quote;perf: system variables init (#3316) * fix: plugin dataset quote * perf: system variables init * perf: node templates ui;fix: dataset import ui (#3318) * fix: dataset import ui * perf: node templates ui * perf: ui refresh * feat:套餐改名和套餐跳转配置 (#3309) * fixing:except Sidebar * 去除了多余的代码 * 修正了套餐说明的代码 * 修正了误删除的show_git代码 * 修正了名字部分等代码 * 修正了问题,遗留了其他和ui讨论不一致的部分 * 4.8.15 test (#3319) * remove log * pref: bill ui * pref: bill ui * perf: log * html渲染文档 (#3270) * html渲染文档 * 文档有点小问题 * feat: doc (#3322) * 集合重训练 (#3282) * rebaser * 一点补充 * 小问题 * 其他问题修正,删除集合保留文件的参数还没找到... * reTraining * delete uesless * 删除了一行错误代码 * 集合重训练部分 * fixing * 删除console代码 * feat: navbar item config (#3326) * perf: custom navbar code;perf: retraining code;feat: api dataset and dataset api doc (#3329) * feat: api dataset and dataset api doc * perf: retraining code * perf: custom navbar code * fix: ts (#3330) * fix: ts * fix: ts * retraining ui * perf: api collection filter * perf: retrining button --------- Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: Jiangween <145003935+Jiangween@users.noreply.github.com> Co-authored-by: papapatrick <109422393+Patrickill@users.noreply.github.com>
288 lines
9.9 KiB
TypeScript
288 lines
9.9 KiB
TypeScript
import React from 'react';
|
|
import {
|
|
Box,
|
|
Checkbox,
|
|
HStack,
|
|
Table,
|
|
TableContainer,
|
|
Tbody,
|
|
Td,
|
|
Th,
|
|
Thead,
|
|
Tr
|
|
} from '@chakra-ui/react';
|
|
import { useTranslation } from 'next-i18next';
|
|
import { useContextSelector } from 'use-context-selector';
|
|
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
|
import { getTeamClbs, updateMemberPermission } from '@/web/support/user/team/api';
|
|
import { useUserStore } from '@/web/support/user/useUserStore';
|
|
|
|
import { TeamContext } from '../context';
|
|
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
|
import Avatar from '@fastgpt/web/components/common/Avatar';
|
|
import MemberTag from '../../../../../components/support/user/team/Info/MemberTag';
|
|
import { DefaultGroupName } from '@fastgpt/global/support/user/team/group/constant';
|
|
import {
|
|
TeamManagePermissionVal,
|
|
TeamWritePermissionVal
|
|
} from '@fastgpt/global/support/permission/user/constant';
|
|
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
|
|
import { useCreation } from 'ahooks';
|
|
|
|
function PermissionManage() {
|
|
const { t } = useTranslation();
|
|
const { userInfo } = useUserStore();
|
|
const { groups, refetchMembers, refetchGroups, members, searchKey } = useContextSelector(
|
|
TeamContext,
|
|
(v) => v
|
|
);
|
|
|
|
const { runAsync: refetchClbs, data: clbs = [] } = useRequest2(getTeamClbs, {
|
|
manual: false,
|
|
refreshDeps: [userInfo?.team?.teamId]
|
|
});
|
|
|
|
const filteredGroups = useCreation(
|
|
() => groups?.filter((group) => group.name.toLowerCase().includes(searchKey.toLowerCase())),
|
|
[groups, searchKey]
|
|
);
|
|
const filteredMembers = useCreation(
|
|
() =>
|
|
members
|
|
?.filter((member) => member.memberName.toLowerCase().includes(searchKey.toLowerCase()))
|
|
.map((member) => {
|
|
const clb = clbs?.find((clb) => String(clb.tmbId) === String(member.tmbId));
|
|
const permission =
|
|
member.role === 'owner'
|
|
? new TeamPermission({ isOwner: true })
|
|
: new TeamPermission({ per: clb?.permission });
|
|
|
|
return { ...member, permission };
|
|
}),
|
|
[clbs, members, searchKey]
|
|
);
|
|
|
|
const { runAsync: onUpdateMemberPermission } = useRequest2(updateMemberPermission, {
|
|
onSuccess: () => {
|
|
refetchGroups();
|
|
refetchMembers();
|
|
refetchClbs();
|
|
}
|
|
});
|
|
|
|
const { runAsync: onAddPermission, loading: addLoading } = useRequest2(
|
|
async ({
|
|
groupId,
|
|
memberId,
|
|
per
|
|
}: {
|
|
groupId?: string;
|
|
memberId?: string;
|
|
per: 'write' | 'manage';
|
|
}) => {
|
|
if (groupId) {
|
|
const group = groups?.find((group) => group._id === groupId);
|
|
if (group) {
|
|
const permission = new TeamPermission({ per: group.permission.value });
|
|
switch (per) {
|
|
case 'write':
|
|
permission.addPer(TeamWritePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
groupId: group._id,
|
|
permission: permission.value
|
|
});
|
|
case 'manage':
|
|
permission.addPer(TeamManagePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
groupId: group._id,
|
|
permission: permission.value
|
|
});
|
|
}
|
|
}
|
|
}
|
|
if (memberId) {
|
|
const member = filteredMembers?.find((member) => String(member.tmbId) === memberId);
|
|
if (member) {
|
|
const permission = new TeamPermission({ per: member.permission.value });
|
|
switch (per) {
|
|
case 'write':
|
|
permission.addPer(TeamWritePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
memberId: String(member.tmbId),
|
|
permission: permission.value
|
|
});
|
|
case 'manage':
|
|
permission.addPer(TeamManagePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
memberId: String(member.tmbId),
|
|
permission: permission.value
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
const { runAsync: onRemovePermission, loading: removeLoading } = useRequest2(
|
|
async ({
|
|
groupId,
|
|
memberId,
|
|
per
|
|
}: {
|
|
groupId?: string;
|
|
memberId?: string;
|
|
per: 'write' | 'manage';
|
|
}) => {
|
|
if (groupId) {
|
|
const group = groups?.find((group) => group._id === groupId);
|
|
if (group) {
|
|
const permission = new TeamPermission({ per: group.permission.value });
|
|
switch (per) {
|
|
case 'write':
|
|
permission.removePer(TeamWritePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
groupId: group._id,
|
|
permission: permission.value
|
|
});
|
|
case 'manage':
|
|
permission.removePer(TeamManagePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
groupId: group._id,
|
|
permission: permission.value
|
|
});
|
|
}
|
|
}
|
|
}
|
|
if (memberId) {
|
|
const member = members?.find((member) => String(member.tmbId) === memberId);
|
|
if (member) {
|
|
const permission = new TeamPermission({ per: member.permission.value }); // Hint: member.permission is read-only
|
|
switch (per) {
|
|
case 'write':
|
|
permission.removePer(TeamWritePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
memberId: String(member.tmbId),
|
|
permission: permission.value
|
|
});
|
|
case 'manage':
|
|
permission.removePer(TeamManagePermissionVal);
|
|
return onUpdateMemberPermission({
|
|
memberId: String(member.tmbId),
|
|
permission: permission.value
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
const userManage = userInfo?.permission.hasManagePer;
|
|
|
|
return (
|
|
<TableContainer fontSize={'sm'}>
|
|
<Table>
|
|
<Thead>
|
|
<Tr bg={'white !important'}>
|
|
<Th bg="myGray.100" borderLeftRadius="md" maxW={'150px'}>
|
|
{t('user:team.group.group')} / {t('user:team.group.members')}
|
|
<QuestionTip ml="1" label={t('user:team.group.permission_tip')} />
|
|
</Th>
|
|
<Th bg="myGray.100">
|
|
<Box mx="auto" w="fit-content">
|
|
{t('user:team.group.permission.write')}
|
|
</Box>
|
|
</Th>
|
|
<Th bg="myGray.100" borderRightRadius="md">
|
|
<Box mx="auto" w="fit-content">
|
|
{t('user:team.group.permission.manage')}
|
|
<QuestionTip ml="1" label={t('user:team.group.manage_tip')} />
|
|
</Box>
|
|
</Th>
|
|
</Tr>
|
|
</Thead>
|
|
<Tbody>
|
|
{filteredGroups?.map((group) => (
|
|
<Tr key={group._id} overflow={'unset'} border="none">
|
|
<Td border="none">
|
|
<MemberTag
|
|
name={
|
|
group.name === DefaultGroupName ? userInfo?.team.teamName ?? '' : group.name
|
|
}
|
|
avatar={group.avatar}
|
|
/>
|
|
</Td>
|
|
<Td border="none">
|
|
<Box mx="auto" w="fit-content">
|
|
<Checkbox
|
|
isDisabled={!userManage}
|
|
isChecked={group.permission.hasWritePer}
|
|
onChange={(e) =>
|
|
e.target.checked
|
|
? onAddPermission({ groupId: group._id, per: 'write' })
|
|
: onRemovePermission({ groupId: group._id, per: 'write' })
|
|
}
|
|
/>
|
|
</Box>
|
|
</Td>
|
|
<Td border="none">
|
|
<Box mx="auto" w="fit-content">
|
|
<Checkbox
|
|
isDisabled={!userInfo?.permission.isOwner}
|
|
isChecked={group.permission.hasManagePer}
|
|
onChange={(e) =>
|
|
e.target.checked
|
|
? onAddPermission({ groupId: group._id, per: 'manage' })
|
|
: onRemovePermission({ groupId: group._id, per: 'manage' })
|
|
}
|
|
/>
|
|
</Box>
|
|
</Td>
|
|
</Tr>
|
|
))}
|
|
{filteredGroups?.length > 0 && filteredMembers?.length > 0 && (
|
|
<Tr borderBottom={'1px solid'} borderColor={'myGray.300'} />
|
|
)}
|
|
{filteredMembers?.map((member) => (
|
|
<Tr key={member.tmbId} overflow={'unset'} border="none">
|
|
<Td border="none">
|
|
<HStack>
|
|
<Avatar src={member.avatar} w="1.5rem" borderRadius={'50%'} />
|
|
<Box>{member.memberName}</Box>
|
|
</HStack>
|
|
</Td>
|
|
<Td border="none">
|
|
<Box mx="auto" w="fit-content">
|
|
<Checkbox
|
|
isDisabled={member.permission.isOwner || !userManage}
|
|
isChecked={member.permission.hasWritePer}
|
|
onChange={(e) =>
|
|
e.target.checked
|
|
? onAddPermission({ memberId: String(member.tmbId), per: 'write' })
|
|
: onRemovePermission({ memberId: String(member.tmbId), per: 'write' })
|
|
}
|
|
/>
|
|
</Box>
|
|
</Td>
|
|
<Td border="none">
|
|
<Box mx="auto" w="fit-content">
|
|
<Checkbox
|
|
isDisabled={member.permission.isOwner || !userInfo?.permission.isOwner}
|
|
isChecked={member.permission.hasManagePer}
|
|
onChange={(e) =>
|
|
e.target.checked
|
|
? onAddPermission({ memberId: String(member.tmbId), per: 'manage' })
|
|
: onRemovePermission({ memberId: String(member.tmbId), per: 'manage' })
|
|
}
|
|
/>
|
|
</Box>
|
|
</Td>
|
|
</Tr>
|
|
))}
|
|
</Tbody>
|
|
</Table>
|
|
</TableContainer>
|
|
);
|
|
}
|
|
|
|
export default PermissionManage;
|