refactor: 权限组管理

pull/49/head
moonrailgun 3 years ago
parent 8e594008be
commit f78b367c55

@ -21,6 +21,18 @@ export interface GroupPanel {
meta?: Record<string, unknown>; meta?: Record<string, unknown>;
} }
export interface GroupRole {
_id: string;
/**
*
*/
name: string;
/**
* ,
*/
permissions: string[];
}
export interface GroupInfo { export interface GroupInfo {
_id: string; _id: string;
name: string; name: string;
@ -28,6 +40,7 @@ export interface GroupInfo {
owner: string; owner: string;
members: GroupMember[]; members: GroupMember[];
panels: GroupPanel[]; panels: GroupPanel[];
roles: GroupRole[];
pinnedPanelId?: string; // 被钉选的面板Id pinnedPanelId?: string; // 被钉选的面板Id
} }

@ -4,6 +4,8 @@ import React from 'react';
interface PermissionItemProps { interface PermissionItemProps {
title: string; title: string;
desc?: string; desc?: string;
checked: boolean;
onChange: (checked: boolean) => void;
} }
export const PermissionItem: React.FC<PermissionItemProps> = React.memo( export const PermissionItem: React.FC<PermissionItemProps> = React.memo(
@ -16,7 +18,7 @@ export const PermissionItem: React.FC<PermissionItemProps> = React.memo(
</Col> </Col>
<Col> <Col>
<Switch /> <Switch checked={props.checked} onChange={props.onChange} />
</Col> </Col>
</Row> </Row>

@ -3,6 +3,7 @@ import React from 'react';
export const RoleItem: React.FC<{ export const RoleItem: React.FC<{
active: boolean; active: boolean;
onClick?: () => void;
}> = React.memo((props) => { }> = React.memo((props) => {
return ( return (
<div <div
@ -12,6 +13,7 @@ export const RoleItem: React.FC<{
'bg-black bg-opacity-20': props.active, 'bg-black bg-opacity-20': props.active,
} }
)} )}
onClick={props.onClick}
> >
{props.children} {props.children}
</div> </div>

@ -1,20 +1,36 @@
import {
DefaultFullModalInputEditorRender,
FullModalField,
} from '@/components/FullModal/Field';
import { IconBtn } from '@/components/IconBtn'; import { IconBtn } from '@/components/IconBtn';
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 } 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 { PermissionItem } from './PermissionItem'; import { PermissionItem } from './PermissionItem';
import { RoleItem } from './RoleItem'; import { RoleItem } from './RoleItem';
import { useModifyPermission } from './useModifyPermission';
const permissionList = [
{
key: 'core.message',
title: t('发送消息'),
desc: t('允许成员在文字频道发送消息'),
default: true,
},
];
interface GroupPermissionProps { interface GroupPermissionProps {
groupId: string; groupId: string;
} }
export const GroupRole: React.FC<GroupPermissionProps> = React.memo((props) => { export const GroupRole: React.FC<GroupPermissionProps> = React.memo((props) => {
const { groupId } = props; const { groupId } = props;
const [roleId, setRoleId] = useState('');
const groupInfo = useGroupInfo(groupId); const groupInfo = useGroupInfo(groupId);
const members = groupInfo?.members ?? []; const roles = groupInfo?.roles ?? [];
const members = (groupInfo?.members ?? []).filter((m) => m.role === roleId);
const userInfoList = useUserInfoList(members.map((m) => m.userId)); const userInfoList = useUserInfoList(members.map((m) => m.userId));
const { const {
searchText, searchText,
@ -25,28 +41,91 @@ export const GroupRole: React.FC<GroupPermissionProps> = React.memo((props) => {
dataSource: userInfoList, dataSource: userInfoList,
filterFn: (item, searchText) => item.nickname.includes(searchText), filterFn: (item, searchText) => item.nickname.includes(searchText),
}); });
const currentRoleInfo = useMemo(
() => roles.find((r) => r._id === roleId),
[roleId]
);
const currentRolePermissions = useMemo(
() => currentRoleInfo?.permissions ?? [],
[roleId]
);
const { isEditing, editingPermission, handleSwitchPermission } =
useModifyPermission(currentRolePermissions);
const handleAddMember = useCallback(() => {}, []); const handleAddMember = useCallback(() => {}, []);
const handleResetPermission = useCallback(() => {}, []);
const handleSavePermission = useCallback(() => {}, []);
const handleChangeRoleName = useCallback((text) => {
console.log('text', text);
}, []);
return ( return (
<div className="flex h-full"> <div className="flex h-full">
<div className="pr-2 mr-2 w-40 border-r border-white border-opacity-20"> <div className="pr-2 mr-2 w-40 border-r border-white border-opacity-20">
{/* 角色列表 */} {/* 角色列表 */}
<RoleItem active={true}>{t('所有人')}</RoleItem> <RoleItem active={roleId === ''} onClick={() => setRoleId('')}>
{t('所有人')}
</RoleItem>
{roles.map((r) => (
<RoleItem
key={r._id}
active={roleId === r._id}
onClick={() => setRoleId(r._id)}
>
{r.name}
</RoleItem>
))}
<RoleItem active={false}>{t('添加角色')}</RoleItem> <RoleItem active={false}>{t('添加角色')}</RoleItem>
</div> </div>
<div className="flex-1 overflow-y-auto"> <div className="flex-1 overflow-y-auto">
<PillTabs> <PillTabs>
<PillTabPane key="summary" tab="概述">
{/* 权限概述 */}
{currentRoleInfo && (
<div className="px-2">
<FullModalField
title={t('角色名称')}
value={currentRoleInfo.name}
editable={true}
renderEditor={DefaultFullModalInputEditorRender}
onSave={handleChangeRoleName}
/>
</div>
)}
</PillTabPane>
<PillTabPane key="permission" tab="权限"> <PillTabPane key="permission" tab="权限">
<div className="mb-2">
<Button onClick={handleResetPermission}>
{t('重置为默认值')}
</Button>
<Button
type="primary"
disabled={!isEditing}
onClick={handleSavePermission}
>
{t('保存')}
</Button>
</div>
{/* 权限详情 */} {/* 权限详情 */}
<PermissionItem {permissionList.map((p) => (
title={t('发送消息')} <PermissionItem
desc={t('允许成员在文字频道发送消息')} key={p.key}
/> title={p.title}
desc={p.desc}
checked={editingPermission.includes(p.key)}
onChange={(checked) => handleSwitchPermission(p.key, checked)}
/>
))}
</PillTabPane> </PillTabPane>
<PillTabPane key="member" tab="管理成员"> <PillTabPane key="member" tab="管理成员" disabled={!roleId}>
{/* 管理成员 */} {/* 管理成员 */}
<div className="text-right mb-2 flex space-x-1"> <div className="text-right mb-2 flex space-x-1">
<Input <Input

@ -0,0 +1,32 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import _isEqual from 'lodash/isEqual';
import _uniq from 'lodash/uniq';
import _without from 'lodash/without';
/**
*
*/
export function useModifyPermission(originPermission: string[]) {
const [editingPermission, setEditingPermission] = useState<string[]>([]);
const isEditing = useMemo(
() => _isEqual(new Set(originPermission), new Set(editingPermission)),
[originPermission, editingPermission]
);
useEffect(() => {
setEditingPermission([...originPermission]);
}, [originPermission]);
const handleSwitchPermission = useCallback(
(permissionKey: string, enabled: boolean) => {
if (enabled) {
setEditingPermission(_uniq([...editingPermission, permissionKey]));
} else {
setEditingPermission(_without(editingPermission, permissionKey));
}
},
[editingPermission]
);
return { isEditing, editingPermission, handleSwitchPermission };
}
Loading…
Cancel
Save