mirror of https://github.com/msgbyte/tailchat
feat: add AdvanceGroupPanelPermission controller
include fetch and set, now under DevContainerpull/146/merge
parent
e85c39e570
commit
86ef2d5c20
@ -0,0 +1,15 @@
|
|||||||
|
import { useCallback, useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export function useEditValue<T>(value: T, onChange: (val: T) => void) {
|
||||||
|
const [inner, setInner] = useState(value);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
setInner(value);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
const onSave = useCallback(() => {
|
||||||
|
onChange(inner);
|
||||||
|
}, [inner, onChange]);
|
||||||
|
|
||||||
|
return [inner, setInner, onSave] as const;
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import { useLayoutEffect, useState } from 'react';
|
||||||
|
import { useEvent } from './useEvent';
|
||||||
|
|
||||||
|
export function useLazyValue<T>(value: T, onChange: (val: T) => void) {
|
||||||
|
const [inner, setInner] = useState(value);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
setInner(value);
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
const handleChange = useEvent((val: T) => {
|
||||||
|
setInner(val);
|
||||||
|
onChange(val);
|
||||||
|
});
|
||||||
|
|
||||||
|
return [inner, handleChange] as const;
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
import { PermissionList } from '@/components/PermissionList';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import React, { PropsWithChildren, useState } from 'react';
|
||||||
|
import {
|
||||||
|
ALL_PERMISSION,
|
||||||
|
getDefaultPermissionList,
|
||||||
|
t,
|
||||||
|
useAppSelector,
|
||||||
|
useEvent,
|
||||||
|
useLazyValue,
|
||||||
|
} from 'tailchat-shared';
|
||||||
|
import _isEqual from 'lodash/isEqual';
|
||||||
|
|
||||||
|
interface AdvanceGroupPanelPermissionProps {
|
||||||
|
height?: number;
|
||||||
|
groupId: string;
|
||||||
|
panelId: string;
|
||||||
|
onChange: (
|
||||||
|
permissionMap: Record<string | typeof ALL_PERMISSION, string[]> | undefined
|
||||||
|
) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AdvanceGroupPanelPermission: React.FC<AdvanceGroupPanelPermissionProps> =
|
||||||
|
React.memo((props) => {
|
||||||
|
const [selectedRoleId, setSelectedRoleId] = useState<
|
||||||
|
typeof ALL_PERMISSION | string
|
||||||
|
>(ALL_PERMISSION);
|
||||||
|
|
||||||
|
const roles = useAppSelector((state) => {
|
||||||
|
const groupInfo = state.group.groups[props.groupId];
|
||||||
|
return groupInfo.roles;
|
||||||
|
});
|
||||||
|
|
||||||
|
const permissionMap: Record<string | typeof ALL_PERMISSION, string[]> =
|
||||||
|
useAppSelector((state) => {
|
||||||
|
const groupInfo = state.group.groups[props.groupId];
|
||||||
|
const panelInfo = groupInfo.panels.find((p) => p.id === props.panelId);
|
||||||
|
if (!panelInfo) {
|
||||||
|
return { [ALL_PERMISSION]: getDefaultPermissionList() };
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
[ALL_PERMISSION]:
|
||||||
|
panelInfo.fallbackPermissions ?? getDefaultPermissionList(),
|
||||||
|
...panelInfo.permissionMap,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, _isEqual);
|
||||||
|
|
||||||
|
const [editPermissionMap, setEditPermissionMap] = useLazyValue(
|
||||||
|
permissionMap,
|
||||||
|
props.onChange
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleUpdatePermissionMap = useEvent((permissions: string[]) => {
|
||||||
|
const newMap = { ...editPermissionMap, [selectedRoleId]: permissions };
|
||||||
|
setEditPermissionMap(newMap);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSyncWithGroup = useEvent(() => {
|
||||||
|
setEditPermissionMap({
|
||||||
|
[ALL_PERMISSION]: getDefaultPermissionList(),
|
||||||
|
});
|
||||||
|
props.onChange(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex" style={{ width: 540 }}>
|
||||||
|
<div>
|
||||||
|
<RoleItem
|
||||||
|
active={selectedRoleId === ALL_PERMISSION}
|
||||||
|
onClick={() => setSelectedRoleId(ALL_PERMISSION)}
|
||||||
|
>
|
||||||
|
{t('所有人')}
|
||||||
|
</RoleItem>
|
||||||
|
{roles.map((r) => (
|
||||||
|
<RoleItem
|
||||||
|
key={r._id}
|
||||||
|
active={selectedRoleId === r._id}
|
||||||
|
onClick={() => setSelectedRoleId(r._id)}
|
||||||
|
>
|
||||||
|
{r.name}
|
||||||
|
</RoleItem>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 overflow-auto" style={{ height: props.height }}>
|
||||||
|
<div className="text-right">
|
||||||
|
<Button onClick={handleSyncWithGroup}>{t('与群组配置同步')}</Button>
|
||||||
|
</div>
|
||||||
|
<PermissionList
|
||||||
|
value={editPermissionMap[selectedRoleId] ?? []}
|
||||||
|
onChange={handleUpdatePermissionMap}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
AdvanceGroupPanelPermission.displayName = 'AdvanceGroupPanelPermission';
|
||||||
|
|
||||||
|
const RoleItem: React.FC<
|
||||||
|
PropsWithChildren<{
|
||||||
|
active: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
|
}>
|
||||||
|
> = React.memo((props) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
'px-2 py-1 rounded cursor-pointer mb-1 hover:bg-black hover:bg-opacity-20',
|
||||||
|
{
|
||||||
|
'bg-black bg-opacity-20': props.active,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
RoleItem.displayName = 'RoleItem';
|
Loading…
Reference in New Issue