-
Notifications
You must be signed in to change notification settings - Fork 337
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add AdvanceGroupPanelPermission controller
include fetch and set, now under DevContainer
- Loading branch information
1 parent
e85c39e
commit 86ef2d5
Showing
8 changed files
with
228 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
120 changes: 120 additions & 0 deletions
120
client/web/src/components/modals/GroupPanel/AdvanceGroupPanelPermission.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters