mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Role picker: Refactor menu components (#60584)
* Simplify underlying components * Move state management deeper to RoleMenuGroupsSection component * Get rid of some unnecessary props passing * Reduce number of unnecessary re-renders * Simplify state
This commit is contained in:
parent
3d8890453f
commit
5ef545d290
@ -1,18 +1,20 @@
|
|||||||
import { cx } from '@emotion/css';
|
import { cx } from '@emotion/css';
|
||||||
import React, { FormEvent } from 'react';
|
import React, { FormEvent, memo } from 'react';
|
||||||
|
|
||||||
import { SelectableValue } from '@grafana/data';
|
|
||||||
import { Checkbox, Portal, useStyles2, useTheme2 } from '@grafana/ui';
|
import { Checkbox, Portal, useStyles2, useTheme2 } from '@grafana/ui';
|
||||||
import { getSelectStyles } from '@grafana/ui/src/components/Select/getSelectStyles';
|
import { getSelectStyles } from '@grafana/ui/src/components/Select/getSelectStyles';
|
||||||
|
|
||||||
import { getStyles } from './styles';
|
import { getStyles } from './styles';
|
||||||
|
|
||||||
interface RoleMenuGroupsOptionProps {
|
interface RoleMenuGroupsOptionProps {
|
||||||
data: SelectableValue<string>;
|
// display name
|
||||||
|
name: string;
|
||||||
|
// group id
|
||||||
|
value: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
onClick?: (value: string) => void;
|
onClick?: (value: string) => void;
|
||||||
onOpenSubMenu?: (value: string) => void;
|
onOpenSubMenu?: (value: string) => void;
|
||||||
onCloseSubMenu?: (value: string) => void;
|
onCloseSubMenu?: () => void;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
partiallySelected?: boolean;
|
partiallySelected?: boolean;
|
||||||
isFocused?: boolean;
|
isFocused?: boolean;
|
||||||
@ -21,84 +23,87 @@ interface RoleMenuGroupsOptionProps {
|
|||||||
root?: HTMLElement;
|
root?: HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RoleMenuGroupOption = React.forwardRef<HTMLDivElement, RoleMenuGroupsOptionProps>(
|
export const RoleMenuGroupOption = memo(
|
||||||
(
|
React.forwardRef<HTMLDivElement, RoleMenuGroupsOptionProps>(
|
||||||
{
|
(
|
||||||
data,
|
{
|
||||||
isFocused,
|
name,
|
||||||
isSelected,
|
value,
|
||||||
partiallySelected,
|
isFocused,
|
||||||
disabled,
|
isSelected,
|
||||||
onChange,
|
partiallySelected,
|
||||||
onClick,
|
disabled,
|
||||||
onOpenSubMenu,
|
onChange,
|
||||||
onCloseSubMenu,
|
onClick,
|
||||||
children,
|
onOpenSubMenu,
|
||||||
root,
|
onCloseSubMenu,
|
||||||
},
|
children,
|
||||||
ref
|
root,
|
||||||
) => {
|
},
|
||||||
const theme = useTheme2();
|
ref
|
||||||
const styles = getSelectStyles(theme);
|
) => {
|
||||||
const customStyles = useStyles2(getStyles);
|
const theme = useTheme2();
|
||||||
|
const styles = getSelectStyles(theme);
|
||||||
|
const customStyles = useStyles2(getStyles);
|
||||||
|
|
||||||
const wrapperClassName = cx(
|
const wrapperClassName = cx(
|
||||||
styles.option,
|
styles.option,
|
||||||
isFocused && styles.optionFocused,
|
isFocused && styles.optionFocused,
|
||||||
disabled && customStyles.menuOptionDisabled
|
disabled && customStyles.menuOptionDisabled
|
||||||
);
|
);
|
||||||
|
|
||||||
const onChangeInternal = (event: FormEvent<HTMLElement>) => {
|
const onChangeInternal = (event: FormEvent<HTMLElement>) => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.value) {
|
if (value) {
|
||||||
onChange(data.value);
|
onChange(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClickInternal = (event: FormEvent<HTMLElement>) => {
|
const onClickInternal = (event: FormEvent<HTMLElement>) => {
|
||||||
if (onClick) {
|
if (onClick) {
|
||||||
onClick(data.value!);
|
onClick(value!);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMouseEnter = () => {
|
const onMouseEnter = () => {
|
||||||
if (onOpenSubMenu) {
|
if (onOpenSubMenu) {
|
||||||
onOpenSubMenu(data.value!);
|
onOpenSubMenu(value!);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMouseLeave = () => {
|
const onMouseLeave = () => {
|
||||||
if (onCloseSubMenu) {
|
if (onCloseSubMenu) {
|
||||||
onCloseSubMenu(data.value!);
|
onCloseSubMenu();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
<div onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
|
||||||
<div ref={ref} className={wrapperClassName} aria-label="Role picker option" onClick={onClickInternal}>
|
<div ref={ref} className={wrapperClassName} aria-label="Role picker option" onClick={onClickInternal}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
value={isSelected}
|
value={isSelected}
|
||||||
className={cx(customStyles.menuOptionCheckbox, {
|
className={cx(customStyles.menuOptionCheckbox, {
|
||||||
[customStyles.checkboxPartiallyChecked]: partiallySelected,
|
[customStyles.checkboxPartiallyChecked]: partiallySelected,
|
||||||
})}
|
})}
|
||||||
onChange={onChangeInternal}
|
onChange={onChangeInternal}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<div className={cx(styles.optionBody, customStyles.menuOptionBody)}>
|
<div className={cx(styles.optionBody, customStyles.menuOptionBody)}>
|
||||||
<span>{data.displayName || data.name}</span>
|
<span>{name}</span>
|
||||||
<span className={customStyles.menuOptionExpand} />
|
<span className={customStyles.menuOptionExpand} />
|
||||||
|
</div>
|
||||||
|
{root && children && (
|
||||||
|
<Portal className={customStyles.subMenuPortal} root={root}>
|
||||||
|
{children}
|
||||||
|
</Portal>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{root && children && (
|
|
||||||
<Portal className={customStyles.subMenuPortal} root={root}>
|
|
||||||
{children}
|
|
||||||
</Portal>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
}
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
RoleMenuGroupOption.displayName = 'RoleMenuGroupOption';
|
RoleMenuGroupOption.displayName = 'RoleMenuGroupOption';
|
||||||
|
@ -1,37 +1,31 @@
|
|||||||
import React from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
|
|
||||||
|
import { useStyles2, getSelectStyles, useTheme2 } from '@grafana/ui';
|
||||||
import { Role } from 'app/types';
|
import { Role } from 'app/types';
|
||||||
|
|
||||||
import { RoleMenuGroupOption } from './RoleMenuGroupOption';
|
import { RoleMenuGroupOption } from './RoleMenuGroupOption';
|
||||||
import { RoleMenuOption } from './RoleMenuOption';
|
import { RoleMenuOption } from './RoleMenuOption';
|
||||||
import { RolePickerSubMenu } from './RolePickerSubMenu';
|
import { RolePickerSubMenu } from './RolePickerSubMenu';
|
||||||
|
import { getStyles } from './styles';
|
||||||
import { isNotDelegatable } from './utils';
|
import { isNotDelegatable } from './utils';
|
||||||
|
|
||||||
interface RoleMenuGroupsSectionProps {
|
interface RoleMenuGroupsSectionProps {
|
||||||
roles: Role[];
|
roles: Role[];
|
||||||
renderedName: string;
|
renderedName: string;
|
||||||
menuSectionStyle: string;
|
|
||||||
groupHeaderStyle: string;
|
|
||||||
optionBodyStyle: string;
|
|
||||||
showGroups?: boolean;
|
showGroups?: boolean;
|
||||||
optionGroups: Array<{
|
optionGroups: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
options: Role[];
|
options: Role[];
|
||||||
value: string;
|
value: string;
|
||||||
}>;
|
}>;
|
||||||
onChange: (value: string) => void;
|
onGroupChange: (value: string) => void;
|
||||||
onOpenSubMenuRMGS: (value: string) => void;
|
|
||||||
onCloseSubMenu?: (value: string) => void;
|
|
||||||
groupSelected: (group: string) => boolean;
|
groupSelected: (group: string) => boolean;
|
||||||
groupPartiallySelected: (group: string) => boolean;
|
groupPartiallySelected: (group: string) => boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
subMenuNode?: HTMLDivElement;
|
subMenuNode?: HTMLDivElement;
|
||||||
showSubMenu: boolean;
|
|
||||||
openedMenuGroup: string;
|
|
||||||
subMenuOptions: Role[];
|
|
||||||
selectedOptions: Role[];
|
selectedOptions: Role[];
|
||||||
onChangeSubMenu: (option: Role) => void;
|
onRoleChange: (option: Role) => void;
|
||||||
onClearSubMenu: () => void;
|
onClearSubMenu: (group: string) => void;
|
||||||
showOnLeftSubMenu: boolean;
|
showOnLeftSubMenu: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,53 +34,63 @@ export const RoleMenuGroupsSection = React.forwardRef<HTMLDivElement, RoleMenuGr
|
|||||||
{
|
{
|
||||||
roles,
|
roles,
|
||||||
renderedName,
|
renderedName,
|
||||||
menuSectionStyle,
|
|
||||||
groupHeaderStyle,
|
|
||||||
optionBodyStyle,
|
|
||||||
showGroups,
|
showGroups,
|
||||||
optionGroups,
|
optionGroups,
|
||||||
onChange,
|
onGroupChange,
|
||||||
groupSelected,
|
groupSelected,
|
||||||
groupPartiallySelected,
|
groupPartiallySelected,
|
||||||
onOpenSubMenuRMGS,
|
|
||||||
onCloseSubMenu,
|
|
||||||
subMenuNode,
|
subMenuNode,
|
||||||
showSubMenu,
|
|
||||||
openedMenuGroup,
|
|
||||||
subMenuOptions,
|
|
||||||
selectedOptions,
|
selectedOptions,
|
||||||
onChangeSubMenu,
|
onRoleChange,
|
||||||
onClearSubMenu,
|
onClearSubMenu,
|
||||||
showOnLeftSubMenu,
|
showOnLeftSubMenu,
|
||||||
},
|
},
|
||||||
_ref
|
_ref
|
||||||
) => {
|
) => {
|
||||||
|
const [showSubMenu, setShowSubMenu] = useState(false);
|
||||||
|
const [openedMenuGroup, setOpenedMenuGroup] = useState('');
|
||||||
|
|
||||||
|
const theme = useTheme2();
|
||||||
|
const selectStyles = getSelectStyles(theme);
|
||||||
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
|
const onOpenSubMenu = useCallback((value: string) => {
|
||||||
|
setOpenedMenuGroup(value);
|
||||||
|
setShowSubMenu(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onCloseSubMenu = useCallback(() => {
|
||||||
|
setShowSubMenu(false);
|
||||||
|
setOpenedMenuGroup('');
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{roles.length > 0 && (
|
{roles.length > 0 && (
|
||||||
<div className={menuSectionStyle}>
|
<div className={styles.menuSection}>
|
||||||
<div className={groupHeaderStyle}>{renderedName}</div>
|
<div className={styles.groupHeader}>{renderedName}</div>
|
||||||
<div className={optionBodyStyle}></div>
|
<div className={selectStyles.optionBody}></div>
|
||||||
{showGroups && !!optionGroups?.length
|
{showGroups && !!optionGroups?.length
|
||||||
? optionGroups.map((groupOption) => (
|
? optionGroups.map((groupOption) => (
|
||||||
<RoleMenuGroupOption
|
<RoleMenuGroupOption
|
||||||
data={groupOption}
|
|
||||||
key={groupOption.value}
|
key={groupOption.value}
|
||||||
|
name={groupOption.name}
|
||||||
|
value={groupOption.value}
|
||||||
isSelected={groupSelected(groupOption.value) || groupPartiallySelected(groupOption.value)}
|
isSelected={groupSelected(groupOption.value) || groupPartiallySelected(groupOption.value)}
|
||||||
partiallySelected={groupPartiallySelected(groupOption.value)}
|
partiallySelected={groupPartiallySelected(groupOption.value)}
|
||||||
disabled={groupOption.options?.every(isNotDelegatable)}
|
disabled={groupOption.options?.every(isNotDelegatable)}
|
||||||
onChange={onChange}
|
onChange={onGroupChange}
|
||||||
onOpenSubMenu={onOpenSubMenuRMGS}
|
onOpenSubMenu={onOpenSubMenu}
|
||||||
onCloseSubMenu={onCloseSubMenu}
|
onCloseSubMenu={onCloseSubMenu}
|
||||||
root={subMenuNode}
|
root={subMenuNode}
|
||||||
isFocused={showSubMenu && openedMenuGroup === groupOption.value}
|
isFocused={showSubMenu && openedMenuGroup === groupOption.value}
|
||||||
>
|
>
|
||||||
{showSubMenu && openedMenuGroup === groupOption.value && (
|
{showSubMenu && openedMenuGroup === groupOption.value && (
|
||||||
<RolePickerSubMenu
|
<RolePickerSubMenu
|
||||||
options={subMenuOptions}
|
options={groupOption.options}
|
||||||
selectedOptions={selectedOptions}
|
selectedOptions={selectedOptions}
|
||||||
onSelect={onChangeSubMenu}
|
onSelect={onRoleChange}
|
||||||
onClear={onClearSubMenu}
|
onClear={() => onClearSubMenu(openedMenuGroup)}
|
||||||
showOnLeft={showOnLeftSubMenu}
|
showOnLeft={showOnLeftSubMenu}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -98,7 +102,7 @@ export const RoleMenuGroupsSection = React.forwardRef<HTMLDivElement, RoleMenuGr
|
|||||||
key={option.uid}
|
key={option.uid}
|
||||||
isSelected={!!(option.uid && !!selectedOptions.find((opt) => opt.uid === option.uid))}
|
isSelected={!!(option.uid && !!selectedOptions.find((opt) => opt.uid === option.uid))}
|
||||||
disabled={isNotDelegatable(option)}
|
disabled={isNotDelegatable(option)}
|
||||||
onChange={onChangeSubMenu}
|
onChange={onRoleChange}
|
||||||
hideDescription
|
hideDescription
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
@ -71,10 +71,6 @@ export const RolePickerMenu = ({
|
|||||||
}: RolePickerMenuProps): JSX.Element => {
|
}: RolePickerMenuProps): JSX.Element => {
|
||||||
const [selectedOptions, setSelectedOptions] = useState<Role[]>(appliedRoles);
|
const [selectedOptions, setSelectedOptions] = useState<Role[]>(appliedRoles);
|
||||||
const [selectedBuiltInRole, setSelectedBuiltInRole] = useState<OrgRole | undefined>(basicRole);
|
const [selectedBuiltInRole, setSelectedBuiltInRole] = useState<OrgRole | undefined>(basicRole);
|
||||||
const [showSubMenu, setShowSubMenu] = useState(false);
|
|
||||||
const [openedMenuGroup, setOpenedMenuGroup] = useState('');
|
|
||||||
const [subMenuOptions, setSubMenuOptions] = useState<Role[]>([]);
|
|
||||||
const [optionGroups, setOptionGroups] = useState<{ [key: string]: RoleGroupOption[] }>({});
|
|
||||||
const [rolesCollection, setRolesCollection] = useState<{ [key: string]: RolesCollectionEntry }>({});
|
const [rolesCollection, setRolesCollection] = useState<{ [key: string]: RolesCollectionEntry }>({});
|
||||||
const subMenuNode = useRef<HTMLDivElement | null>(null);
|
const subMenuNode = useRef<HTMLDivElement | null>(null);
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
@ -92,7 +88,7 @@ export const RolePickerMenu = ({
|
|||||||
}
|
}
|
||||||
}, [selectedBuiltInRole, onBasicRoleSelect]);
|
}, [selectedBuiltInRole, onBasicRoleSelect]);
|
||||||
|
|
||||||
// Evaluate optionGroups and rolesCollection only if options changed, otherwise
|
// Evaluate rolesCollection only if options changed, otherwise
|
||||||
// it triggers unnecessary re-rendering of <RoleMenuGroupsSection /> component
|
// it triggers unnecessary re-rendering of <RoleMenuGroupsSection /> component
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const customRoles = options.filter(filterCustomRoles).sort(sortRolesByName);
|
const customRoles = options.filter(filterCustomRoles).sort(sortRolesByName);
|
||||||
@ -103,7 +99,6 @@ export const RolePickerMenu = ({
|
|||||||
custom: convertRolesToGroupOptions(customRoles).sort((a, b) => a.name.localeCompare(b.name)),
|
custom: convertRolesToGroupOptions(customRoles).sort((a, b) => a.name.localeCompare(b.name)),
|
||||||
plugin: convertRolesToGroupOptions(pluginRoles).sort((a, b) => a.name.localeCompare(b.name)),
|
plugin: convertRolesToGroupOptions(pluginRoles).sort((a, b) => a.name.localeCompare(b.name)),
|
||||||
};
|
};
|
||||||
setOptionGroups(optionGroups);
|
|
||||||
|
|
||||||
setRolesCollection({
|
setRolesCollection({
|
||||||
fixed: {
|
fixed: {
|
||||||
@ -118,7 +113,7 @@ export const RolePickerMenu = ({
|
|||||||
renderedName: `Custom roles`,
|
renderedName: `Custom roles`,
|
||||||
roles: customRoles,
|
roles: customRoles,
|
||||||
},
|
},
|
||||||
pluginRoles: {
|
plugin: {
|
||||||
groupType: GroupType.plugin,
|
groupType: GroupType.plugin,
|
||||||
optionGroup: optionGroups.plugin,
|
optionGroup: optionGroups.plugin,
|
||||||
renderedName: `Plugin roles`,
|
renderedName: `Plugin roles`,
|
||||||
@ -139,13 +134,13 @@ export const RolePickerMenu = ({
|
|||||||
|
|
||||||
const groupSelected = (groupType: GroupType, group: string) => {
|
const groupSelected = (groupType: GroupType, group: string) => {
|
||||||
const selectedGroupOptions = getSelectedGroupOptions(group);
|
const selectedGroupOptions = getSelectedGroupOptions(group);
|
||||||
const groupOptions = optionGroups[groupType].find((g) => g.value === group);
|
const groupOptions = rolesCollection[groupType]?.optionGroup.find((g) => g.value === group);
|
||||||
return selectedGroupOptions.length > 0 && selectedGroupOptions.length >= groupOptions!.options.length;
|
return selectedGroupOptions.length > 0 && selectedGroupOptions.length >= groupOptions!.options.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
const groupPartiallySelected = (groupType: GroupType, group: string) => {
|
const groupPartiallySelected = (groupType: GroupType, group: string) => {
|
||||||
const selectedGroupOptions = getSelectedGroupOptions(group);
|
const selectedGroupOptions = getSelectedGroupOptions(group);
|
||||||
const groupOptions = optionGroups[groupType].find((g) => g.value === group);
|
const groupOptions = rolesCollection[groupType]?.optionGroup.find((g) => g.value === group);
|
||||||
return selectedGroupOptions.length > 0 && selectedGroupOptions.length < groupOptions!.options.length;
|
return selectedGroupOptions.length > 0 && selectedGroupOptions.length < groupOptions!.options.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,7 +153,7 @@ export const RolePickerMenu = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onGroupChange = (groupType: GroupType, value: string) => {
|
const onGroupChange = (groupType: GroupType, value: string) => {
|
||||||
const group = optionGroups[groupType].find((g) => {
|
const group = rolesCollection[groupType]?.optionGroup.find((g) => {
|
||||||
return g.value === value;
|
return g.value === value;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -175,23 +170,6 @@ export const RolePickerMenu = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOpenSubMenu = (groupType: GroupType, value: string) => {
|
|
||||||
setOpenedMenuGroup(value);
|
|
||||||
setShowSubMenu(true);
|
|
||||||
const group = optionGroups[groupType].find((g) => {
|
|
||||||
return g.value === value;
|
|
||||||
});
|
|
||||||
if (group) {
|
|
||||||
setSubMenuOptions(group.options);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onCloseSubMenu = (value: string) => {
|
|
||||||
setShowSubMenu(false);
|
|
||||||
setOpenedMenuGroup('');
|
|
||||||
setSubMenuOptions([]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSelectedBuiltinRoleChange = (newRole: OrgRole) => {
|
const onSelectedBuiltinRoleChange = (newRole: OrgRole) => {
|
||||||
setSelectedBuiltInRole(newRole);
|
setSelectedBuiltInRole(newRole);
|
||||||
};
|
};
|
||||||
@ -200,10 +178,10 @@ export const RolePickerMenu = ({
|
|||||||
setSelectedOptions([]);
|
setSelectedOptions([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClearSubMenu = () => {
|
const onClearSubMenu = (group: string) => {
|
||||||
const options = selectedOptions.filter((role) => {
|
const options = selectedOptions.filter((role) => {
|
||||||
const groupName = getRoleGroup(role);
|
const roleGroup = getRoleGroup(role);
|
||||||
return groupName !== openedMenuGroup;
|
return roleGroup !== group;
|
||||||
});
|
});
|
||||||
setSelectedOptions(options);
|
setSelectedOptions(options);
|
||||||
};
|
};
|
||||||
@ -239,33 +217,23 @@ export const RolePickerMenu = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{Object.entries(rolesCollection).map(([groupId, collection]) => {
|
{Object.entries(rolesCollection).map(([groupId, collection]) => (
|
||||||
return (
|
<RoleMenuGroupsSection
|
||||||
<RoleMenuGroupsSection
|
key={groupId}
|
||||||
key={groupId}
|
roles={collection.roles}
|
||||||
roles={collection.roles}
|
renderedName={collection.renderedName}
|
||||||
renderedName={collection.renderedName}
|
showGroups={showGroups}
|
||||||
menuSectionStyle={customStyles.menuSection}
|
optionGroups={collection.optionGroup}
|
||||||
groupHeaderStyle={customStyles.groupHeader}
|
groupSelected={(group: string) => groupSelected(collection.groupType, group)}
|
||||||
optionBodyStyle={styles.optionBody}
|
groupPartiallySelected={(group: string) => groupPartiallySelected(collection.groupType, group)}
|
||||||
showGroups={showGroups}
|
onGroupChange={(group: string) => onGroupChange(collection.groupType, group)}
|
||||||
optionGroups={collection.optionGroup}
|
subMenuNode={subMenuNode?.current!}
|
||||||
groupSelected={(group: string) => groupSelected(collection.groupType, group)}
|
selectedOptions={selectedOptions}
|
||||||
groupPartiallySelected={(group: string) => groupPartiallySelected(collection.groupType, group)}
|
onRoleChange={onChange}
|
||||||
onChange={(group: string) => onGroupChange(collection.groupType, group)}
|
onClearSubMenu={onClearSubMenu}
|
||||||
onOpenSubMenuRMGS={(group: string) => onOpenSubMenu(collection.groupType, group)}
|
showOnLeftSubMenu={offset.horizontal > 0}
|
||||||
onCloseSubMenu={onCloseSubMenu}
|
/>
|
||||||
subMenuNode={subMenuNode?.current!}
|
))}
|
||||||
showSubMenu={showSubMenu}
|
|
||||||
openedMenuGroup={openedMenuGroup}
|
|
||||||
subMenuOptions={subMenuOptions}
|
|
||||||
selectedOptions={selectedOptions}
|
|
||||||
onChangeSubMenu={onChange}
|
|
||||||
onClearSubMenu={onClearSubMenu}
|
|
||||||
showOnLeftSubMenu={offset.horizontal > 0}
|
|
||||||
></RoleMenuGroupsSection>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</CustomScrollbar>
|
</CustomScrollbar>
|
||||||
<div className={customStyles.menuButtonRow}>
|
<div className={customStyles.menuButtonRow}>
|
||||||
<HorizontalGroup justify="flex-end">
|
<HorizontalGroup justify="flex-end">
|
||||||
|
Loading…
Reference in New Issue
Block a user