feat: 权限列表的创建与保存

pull/49/head
moonrailgun
parent 5e07b02c9c
commit 9631081b65

@ -90,6 +90,7 @@ export {
} from './manager/ui'; } from './manager/ui';
// model // model
export * as model from './model/__all__';
export { fetchAvailableServices } from './model/common'; export { fetchAvailableServices } from './model/common';
export { fetchGlobalConfig } from './model/config'; export { fetchGlobalConfig } from './model/config';
export { export {
@ -118,6 +119,10 @@ export {
createGroupPanel, createGroupPanel,
modifyGroupPanel, modifyGroupPanel,
deleteGroupPanel, deleteGroupPanel,
createGroupRole,
deleteGroupRole,
updateGroupRoleName,
updateGroupRolePermission,
} from './model/group'; } from './model/group';
export type { export type {
GroupPanel, GroupPanel,

@ -0,0 +1,8 @@
export * as common from './common';
export * as config from './config';
export * as converse from './converse';
export * as friend from './friend';
export * as group from './group';
export * as message from './message';
export * as plugin from './plugin';
export * as user from './user';

@ -250,3 +250,69 @@ export async function deleteGroupPanel(groupId: string, panelId: string) {
panelId, panelId,
}); });
} }
/**
*
* @param groupId id
* @param roleName
* @param permission
*/
export async function createGroupRole(
groupId: string,
roleName: string,
permission: string[]
) {
await request.post('/api/group/createGroupRole', {
groupId,
roleName,
permission,
});
}
/**
*
* @param groupId Id
* @param roleId Id
*/
export async function deleteGroupRole(groupId: string, roleId: string) {
await request.post('/api/group/deleteGroupRole', {
groupId,
roleId,
});
}
/**
*
* @param groupId Id
* @param roleId Id
* @param roleName
*/
export async function updateGroupRoleName(
groupId: string,
roleId: string,
roleName: string
) {
await request.post('/api/group/updateGroupRoleName', {
groupId,
roleId,
roleName,
});
}
/**
*
* @param groupId Id
* @param roleId Id
* @param permissions
*/
export async function updateGroupRolePermission(
groupId: string,
roleId: string,
permissions: string[]
) {
await request.post('/api/group/updateGroupRolePermission', {
groupId,
roleId,
permissions,
});
}

@ -0,0 +1,10 @@
import { t } from 'tailchat-shared';
export const permissionList = [
{
key: 'core.message',
title: t('发送消息'),
desc: t('允许成员在文字频道发送消息'),
default: true,
},
];

@ -3,24 +3,18 @@ import {
FullModalField, FullModalField,
} from '@/components/FullModal/Field'; } from '@/components/FullModal/Field';
import { IconBtn } from '@/components/IconBtn'; import { IconBtn } from '@/components/IconBtn';
import { Loading } from '@/components/Loading';
import { PillTabPane, PillTabs } from '@/components/PillTabs'; import { PillTabPane, PillTabs } from '@/components/PillTabs';
import { UserListItem } from '@/components/UserListItem'; import { UserListItem } from '@/components/UserListItem';
import { Button, Input } from 'antd'; import { Button, Input } from 'antd';
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import { Icon } from 'tailchat-design'; import { Icon } from 'tailchat-design';
import { t, useGroupInfo, useSearch, useUserInfoList } from 'tailchat-shared'; import { t, useGroupInfo, useSearch, useUserInfoList } from 'tailchat-shared';
import { permissionList } from './const';
import { PermissionItem } from './PermissionItem'; import { PermissionItem } from './PermissionItem';
import { RoleItem } from './RoleItem'; import { RoleItem } from './RoleItem';
import { useModifyPermission } from './useModifyPermission'; import { useModifyPermission } from './useModifyPermission';
import { useRoleActions } from './useRoleActions';
const permissionList = [
{
key: 'core.message',
title: t('发送消息'),
desc: t('允许成员在文字频道发送消息'),
default: true,
},
];
interface GroupPermissionProps { interface GroupPermissionProps {
groupId: string; groupId: string;
@ -43,115 +37,130 @@ export const GroupRole: React.FC<GroupPermissionProps> = React.memo((props) => {
}); });
const currentRoleInfo = useMemo( const currentRoleInfo = useMemo(
() => roles.find((r) => r._id === roleId), () => roles.find((r) => r._id === roleId),
[roleId] [roles, roleId]
); );
const currentRolePermissions = useMemo( const currentRolePermissions = useMemo(
() => currentRoleInfo?.permissions ?? [], () => currentRoleInfo?.permissions ?? [],
[roleId] [currentRoleInfo]
); );
const { isEditing, editingPermission, handleSwitchPermission } = const {
useModifyPermission(currentRolePermissions); loading,
handleCreateRole,
const handleAddMember = useCallback(() => {}, []); handleSavePermission,
handleChangeRoleName,
} = useRoleActions(groupId, roleId);
const handleResetPermission = useCallback(() => {}, []); const {
isEditing,
editingPermission,
setEditingPermission,
handleSwitchPermission,
} = useModifyPermission(currentRolePermissions);
const handleSavePermission = useCallback(() => {}, []); const handleAddMember = useCallback(() => {}, []);
const handleChangeRoleName = useCallback((text) => { const handleResetPermission = useCallback(() => {
console.log('text', text); setEditingPermission(
permissionList.filter((p) => p.default === true).map((p) => p.key)
);
}, []); }, []);
return ( return (
<div className="flex h-full"> <Loading spinning={loading}>
<div className="pr-2 mr-2 w-40 border-r border-white border-opacity-20"> <div className="flex h-full">
{/* 角色列表 */} <div className="pr-2 mr-2 w-40 border-r border-white border-opacity-20">
<RoleItem active={roleId === ''} onClick={() => setRoleId('')}> {/* 角色列表 */}
{t('所有人')} <RoleItem active={roleId === ''} onClick={() => setRoleId('')}>
</RoleItem> {t('所有人')}
{roles.map((r) => (
<RoleItem
key={r._id}
active={roleId === r._id}
onClick={() => setRoleId(r._id)}
>
{r.name}
</RoleItem> </RoleItem>
))}
<RoleItem active={false}>{t('添加角色')}</RoleItem> {roles.map((r) => (
</div> <RoleItem
key={r._id}
active={roleId === r._id}
onClick={() => setRoleId(r._id)}
>
{r.name}
</RoleItem>
))}
<div className="flex-1 overflow-y-auto"> <RoleItem active={false} onClick={handleCreateRole}>
<PillTabs> {t('添加角色')}
<PillTabPane key="summary" tab="概述"> </RoleItem>
{/* 权限概述 */} </div>
{currentRoleInfo && (
<div className="px-2"> <div className="flex-1 overflow-y-auto">
<FullModalField <PillTabs defaultActiveKey="permission">
title={t('角色名称')} <PillTabPane key="summary" tab={t('概述')} disabled={!roleId}>
value={currentRoleInfo.name} {/* 权限概述 */}
editable={true} {currentRoleInfo && (
renderEditor={DefaultFullModalInputEditorRender} <div className="px-2">
onSave={handleChangeRoleName} <FullModalField
/> title={t('角色名称')}
value={currentRoleInfo.name}
editable={true}
renderEditor={DefaultFullModalInputEditorRender}
onSave={handleChangeRoleName}
/>
</div>
)}
</PillTabPane>
<PillTabPane key="permission" tab={t('权限')}>
<div className="mb-2 space-x-2 text-right">
<Button onClick={handleResetPermission}>
{t('重置为默认值')}
</Button>
<Button
type="primary"
disabled={!isEditing}
onClick={() => handleSavePermission(editingPermission)}
>
{t('保存')}
</Button>
</div> </div>
)}
</PillTabPane>
<PillTabPane key="permission" tab="权限">
<div className="mb-2">
<Button onClick={handleResetPermission}>
{t('重置为默认值')}
</Button>
<Button
type="primary"
disabled={!isEditing}
onClick={handleSavePermission}
>
{t('保存')}
</Button>
</div>
{/* 权限详情 */} {/* 权限详情 */}
{permissionList.map((p) => ( {permissionList.map((p) => (
<PermissionItem <PermissionItem
key={p.key} key={p.key}
title={p.title} title={p.title}
desc={p.desc} desc={p.desc}
checked={editingPermission.includes(p.key)} checked={editingPermission.includes(p.key)}
onChange={(checked) => handleSwitchPermission(p.key, checked)} onChange={(checked) => handleSwitchPermission(p.key, checked)}
/> />
))} ))}
</PillTabPane> </PillTabPane>
<PillTabPane key="member" tab="管理成员" disabled={!roleId}> <PillTabPane key="member" tab={t('管理成员')} disabled={!roleId}>
{/* 管理成员 */} {/* 管理成员 */}
<div className="text-right mb-2 flex space-x-1"> <div className="text-right mb-2 flex space-x-1">
<Input <Input
placeholder={t('搜索成员')} placeholder={t('搜索成员')}
size="middle" size="middle"
suffix={<Icon fontSize={20} color="grey" icon="mdi:magnify" />} suffix={
value={searchText} <Icon fontSize={20} color="grey" icon="mdi:magnify" />
onChange={(e) => setSearchText(e.target.value)} }
/> value={searchText}
onChange={(e) => setSearchText(e.target.value)}
/>
<Button type="primary" onClick={handleAddMember}> <Button type="primary" onClick={handleAddMember}>
{t('添加成员')} {t('添加成员')}
</Button> </Button>
</div> </div>
{(isSearching ? filterMembers : userInfoList).map((m) => ( {(isSearching ? filterMembers : userInfoList).map((m) => (
<UserListItem <UserListItem
key={m._id} key={m._id}
userId={m._id} userId={m._id}
actions={[<IconBtn key="remove" icon="mdi:close" />]} actions={[<IconBtn key="remove" icon="mdi:close" />]}
/> />
))} ))}
</PillTabPane> </PillTabPane>
</PillTabs> </PillTabs>
</div>
</div> </div>
</div> </Loading>
); );
}); });
GroupRole.displayName = 'GroupRole'; GroupRole.displayName = 'GroupRole';

@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import _isEqual from 'lodash/isEqual'; import _isEqual from 'lodash/isEqual';
import _uniq from 'lodash/uniq'; import _uniq from 'lodash/uniq';
import _without from 'lodash/without'; import _without from 'lodash/without';
import { useAsyncFn } from 'tailchat-shared';
/** /**
* *
@ -9,7 +10,7 @@ import _without from 'lodash/without';
export function useModifyPermission(originPermission: string[]) { export function useModifyPermission(originPermission: string[]) {
const [editingPermission, setEditingPermission] = useState<string[]>([]); const [editingPermission, setEditingPermission] = useState<string[]>([]);
const isEditing = useMemo( const isEditing = useMemo(
() => _isEqual(new Set(originPermission), new Set(editingPermission)), () => !_isEqual(new Set(originPermission), new Set(editingPermission)),
[originPermission, editingPermission] [originPermission, editingPermission]
); );
@ -28,5 +29,10 @@ export function useModifyPermission(originPermission: string[]) {
[editingPermission] [editingPermission]
); );
return { isEditing, editingPermission, handleSwitchPermission }; return {
isEditing,
editingPermission,
setEditingPermission,
handleSwitchPermission,
};
} }

@ -0,0 +1,34 @@
import { model, t, useAsyncRequest } from 'tailchat-shared';
import { permissionList } from './const';
export function useRoleActions(groupId: string, roleId: string) {
const [{ loading: loading1 }, handleCreateRole] =
useAsyncRequest(async () => {
await model.group.createGroupRole(
groupId,
t('新身份组'),
permissionList.filter((p) => p.default).map((p) => p.key)
);
}, [groupId]);
const [{ loading: loading2 }, handleSavePermission] = useAsyncRequest(
async (permissions: string[]) => {
await model.group.updateGroupRolePermission(groupId, roleId, permissions);
},
[groupId, roleId]
);
const [{ loading: loading3 }, handleChangeRoleName] = useAsyncRequest(
async (newRoleName: string) => {
await model.group.updateGroupRoleName(groupId, roleId, newRoleName);
},
[groupId, roleId]
);
return {
loading: loading1 || loading2 || loading3,
handleCreateRole,
handleSavePermission,
handleChangeRoleName,
};
}

@ -20,7 +20,6 @@ import {
import { getPopupContainer } from './utils/dom-helper'; import { getPopupContainer } from './utils/dom-helper';
import { getUserJWT } from './utils/jwt-helper'; import { getUserJWT } from './utils/jwt-helper';
import _get from 'lodash/get'; import _get from 'lodash/get';
import _debounce from 'lodash/debounce';
if (isDevelopment) { if (isDevelopment) {
import('source-ref-open-vscode'); import('source-ref-open-vscode');

Loading…
Cancel
Save