Web: Shared: Adapt tabs to selector for people/groups
This commit is contained in:
parent
1fe703a0c9
commit
16cc8962ee
@ -6,6 +6,7 @@ import { Base } from "../../themes";
|
|||||||
|
|
||||||
import { ComboBox } from "../combobox";
|
import { ComboBox } from "../combobox";
|
||||||
import { Text } from "../text";
|
import { Text } from "../text";
|
||||||
|
import { Submenu } from "../submenu";
|
||||||
|
|
||||||
const StyledSelector = styled.div`
|
const StyledSelector = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -53,6 +54,7 @@ const StyledBody = styled.div<{
|
|||||||
withHeader?: boolean;
|
withHeader?: boolean;
|
||||||
footerHeight: number;
|
footerHeight: number;
|
||||||
headerHeight: number;
|
headerHeight: number;
|
||||||
|
withTabs?: boolean;
|
||||||
}>`
|
}>`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ const StyledBody = styled.div<{
|
|||||||
? `calc(100% - 16px - ${props.headerHeight}px)`
|
? `calc(100% - 16px - ${props.headerHeight}px)`
|
||||||
: `calc(100% - 16px)`};
|
: `calc(100% - 16px)`};
|
||||||
|
|
||||||
padding: 16px 0 0 0;
|
padding: ${({ withTabs }) => (withTabs ? "8px 0 0 0" : "16px 0 0 0")};
|
||||||
|
|
||||||
.search-input,
|
.search-input,
|
||||||
.search-loader {
|
.search-loader {
|
||||||
@ -360,6 +362,15 @@ const StyledComboBox = styled(ComboBox)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledTabs = styled(Submenu)`
|
||||||
|
padding: 0 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.sticky-indent {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
StyledSelector.defaultProps = { theme: Base };
|
StyledSelector.defaultProps = { theme: Base };
|
||||||
StyledHeader.defaultProps = { theme: Base };
|
StyledHeader.defaultProps = { theme: Base };
|
||||||
StyledBody.defaultProps = { theme: Base };
|
StyledBody.defaultProps = { theme: Base };
|
||||||
@ -384,4 +395,5 @@ export {
|
|||||||
StyledNewNameHeader,
|
StyledNewNameHeader,
|
||||||
StyledButtonContainer,
|
StyledButtonContainer,
|
||||||
StyledComboBox,
|
StyledComboBox,
|
||||||
|
StyledTabs,
|
||||||
};
|
};
|
||||||
|
@ -83,7 +83,12 @@ const Selector = ({
|
|||||||
cancelButtonId,
|
cancelButtonId,
|
||||||
isChecked,
|
isChecked,
|
||||||
setIsChecked,
|
setIsChecked,
|
||||||
|
|
||||||
|
withTabs,
|
||||||
|
tabsData,
|
||||||
|
activeTabId,
|
||||||
}: SelectorProps) => {
|
}: SelectorProps) => {
|
||||||
|
const [areItemsUpdated, setAreItemsUpdated] = React.useState(false);
|
||||||
const [footerVisible, setFooterVisible] = React.useState<boolean>(false);
|
const [footerVisible, setFooterVisible] = React.useState<boolean>(false);
|
||||||
const [isSearch, setIsSearch] = React.useState<boolean>(false);
|
const [isSearch, setIsSearch] = React.useState<boolean>(false);
|
||||||
|
|
||||||
@ -304,6 +309,37 @@ const Selector = ({
|
|||||||
compareSelectedItems(cloneSelectedItems);
|
compareSelectedItems(cloneSelectedItems);
|
||||||
}
|
}
|
||||||
}, [items, selectedItems, isMultiSelect, compareSelectedItems]);
|
}, [items, selectedItems, isMultiSelect, compareSelectedItems]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!areItemsUpdated) return;
|
||||||
|
if (!newSelectedItems.length || !isMultiSelect || !items) {
|
||||||
|
setAreItemsUpdated(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasConflict = false;
|
||||||
|
|
||||||
|
const cloneItems = items.map((x) => {
|
||||||
|
if (x.isSelected) return { ...x };
|
||||||
|
|
||||||
|
const isSelected = newSelectedItems.some(
|
||||||
|
(selectedItem) => selectedItem.id === x.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isSelected) hasConflict = true;
|
||||||
|
|
||||||
|
return { ...x, isSelected };
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasConflict) {
|
||||||
|
setRenderedItems(cloneItems);
|
||||||
|
}
|
||||||
|
setAreItemsUpdated(false);
|
||||||
|
}, [areItemsUpdated, isMultiSelect, items, newSelectedItems]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setAreItemsUpdated(true);
|
||||||
|
}, [items]);
|
||||||
return (
|
return (
|
||||||
<StyledSelector
|
<StyledSelector
|
||||||
id={id}
|
id={id}
|
||||||
@ -366,6 +402,9 @@ const Selector = ({
|
|||||||
withFooterInput={withFooterInput}
|
withFooterInput={withFooterInput}
|
||||||
withFooterCheckbox={withFooterCheckbox}
|
withFooterCheckbox={withFooterCheckbox}
|
||||||
descriptionText={descriptionText}
|
descriptionText={descriptionText}
|
||||||
|
withTabs={withTabs}
|
||||||
|
tabsData={tabsData}
|
||||||
|
activeTabId={activeTabId}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{(footerVisible || alwaysShowFooter) && (
|
{(footerVisible || alwaysShowFooter) && (
|
||||||
@ -415,6 +454,7 @@ Selector.defaultProps = {
|
|||||||
alwaysShowFooter: false,
|
alwaysShowFooter: false,
|
||||||
disableAcceptButton: false,
|
disableAcceptButton: false,
|
||||||
withHeader: true,
|
withHeader: true,
|
||||||
|
withTabs: false,
|
||||||
|
|
||||||
selectedItems: [],
|
selectedItems: [],
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { RoomsType } from "../../enums";
|
import { RoomsType } from "../../enums";
|
||||||
import { AvatarRole } from "../avatar";
|
import { AvatarRole } from "../avatar";
|
||||||
|
import { TSubmenuItem } from "../submenu";
|
||||||
|
|
||||||
export type AccessRight = {
|
export type AccessRight = {
|
||||||
key: string;
|
key: string;
|
||||||
@ -84,6 +85,10 @@ export interface SelectorProps {
|
|||||||
cancelButtonId?: string;
|
cancelButtonId?: string;
|
||||||
isChecked?: boolean;
|
isChecked?: boolean;
|
||||||
setIsChecked?: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsChecked?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
|
||||||
|
withTabs?: boolean;
|
||||||
|
tabsData?: TSubmenuItem[];
|
||||||
|
activeTabId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HeaderProps {
|
export interface HeaderProps {
|
||||||
@ -135,6 +140,10 @@ export interface BodyProps {
|
|||||||
withFooterCheckbox?: boolean;
|
withFooterCheckbox?: boolean;
|
||||||
|
|
||||||
descriptionText?: string;
|
descriptionText?: string;
|
||||||
|
|
||||||
|
withTabs?: boolean;
|
||||||
|
tabsData?: TSubmenuItem[];
|
||||||
|
activeTabId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FooterProps {
|
export interface FooterProps {
|
||||||
@ -177,6 +186,7 @@ export type TSelectorItem = {
|
|||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
color?: string;
|
color?: string;
|
||||||
fileExst?: string;
|
fileExst?: string;
|
||||||
|
isGroup?: boolean;
|
||||||
roomType?: RoomsType;
|
roomType?: RoomsType;
|
||||||
shared: boolean;
|
shared: boolean;
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ import { SelectAll } from "./SelectAll";
|
|||||||
import { EmptyScreen } from "./EmptyScreen";
|
import { EmptyScreen } from "./EmptyScreen";
|
||||||
import { BreadCrumbs } from "./BreadCrumbs";
|
import { BreadCrumbs } from "./BreadCrumbs";
|
||||||
|
|
||||||
import { StyledBody } from "../Selector.styled";
|
import { StyledBody, StyledTabs } from "../Selector.styled";
|
||||||
import { BodyProps } from "../Selector.types";
|
import { BodyProps } from "../Selector.types";
|
||||||
import { Item } from "./Item";
|
import { Item } from "./Item";
|
||||||
|
|
||||||
@ -65,6 +65,10 @@ const Body = ({
|
|||||||
withFooterCheckbox,
|
withFooterCheckbox,
|
||||||
descriptionText,
|
descriptionText,
|
||||||
withHeader,
|
withHeader,
|
||||||
|
|
||||||
|
withTabs,
|
||||||
|
tabsData,
|
||||||
|
activeTabId,
|
||||||
}: BodyProps) => {
|
}: BodyProps) => {
|
||||||
const [bodyHeight, setBodyHeight] = React.useState(0);
|
const [bodyHeight, setBodyHeight] = React.useState(0);
|
||||||
|
|
||||||
@ -152,6 +156,7 @@ const Body = ({
|
|||||||
headerHeight={HEADER_HEIGHT}
|
headerHeight={HEADER_HEIGHT}
|
||||||
footerVisible={footerVisible}
|
footerVisible={footerVisible}
|
||||||
withHeader={withHeader}
|
withHeader={withHeader}
|
||||||
|
withTabs={withTabs}
|
||||||
>
|
>
|
||||||
{withBreadCrumbs ? (
|
{withBreadCrumbs ? (
|
||||||
isBreadCrumbsLoading ? (
|
isBreadCrumbsLoading ? (
|
||||||
@ -165,6 +170,14 @@ const Body = ({
|
|||||||
)
|
)
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{withTabs && tabsData && (
|
||||||
|
<StyledTabs
|
||||||
|
startSelect={0}
|
||||||
|
data={tabsData}
|
||||||
|
forsedActiveItemId={activeTabId}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{isSearchLoading || isBreadCrumbsLoading ? (
|
{isSearchLoading || isBreadCrumbsLoading ? (
|
||||||
searchLoader
|
searchLoader
|
||||||
) : withSearch || isSearch || (itemsCount > 0 && withSearch) ? (
|
) : withSearch || isSearch || (itemsCount > 0 && withSearch) ? (
|
||||||
|
@ -47,8 +47,17 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
|
|||||||
if (!item || (item && !item.id))
|
if (!item || (item && !item.id))
|
||||||
return <div style={style}>{rowLoader}</div>;
|
return <div style={style}>{rowLoader}</div>;
|
||||||
|
|
||||||
const { label, avatar, icon, role, isSelected, isDisabled, color, email } =
|
const {
|
||||||
item;
|
label,
|
||||||
|
avatar,
|
||||||
|
icon,
|
||||||
|
role,
|
||||||
|
isSelected,
|
||||||
|
isDisabled,
|
||||||
|
color,
|
||||||
|
email,
|
||||||
|
isGroup,
|
||||||
|
} = item;
|
||||||
|
|
||||||
const currentRole = role || AvatarRole.user;
|
const currentRole = role || AvatarRole.user;
|
||||||
|
|
||||||
@ -87,6 +96,8 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
|
|||||||
source={avatar || ""}
|
source={avatar || ""}
|
||||||
role={currentRole}
|
role={currentRole}
|
||||||
size={AvatarSize.min}
|
size={AvatarSize.min}
|
||||||
|
isGroup={isGroup}
|
||||||
|
userName={isGroup ? label : ""}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<RoomIcon
|
<RoomIcon
|
||||||
@ -98,7 +109,7 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{renderCustomItem ? (
|
{renderCustomItem ? (
|
||||||
renderCustomItem(label, typeLabel, email)
|
renderCustomItem(label, typeLabel, email, isGroup)
|
||||||
) : (
|
) : (
|
||||||
<Text
|
<Text
|
||||||
className="label"
|
className="label"
|
||||||
|
Loading…
Reference in New Issue
Block a user