Web: Files: Templates: fixed TemplateAccessSettingsPanel
This commit is contained in:
parent
f18602ac44
commit
f141269ec2
@ -143,11 +143,20 @@ const toListItem = (
|
||||
} as TSelectorItem;
|
||||
};
|
||||
|
||||
type AddUsersPanelProps = {
|
||||
export type TSelectorInfo =
|
||||
| { withInfo: true; infoText: string; withInfoBadge?: boolean }
|
||||
| {
|
||||
withInfo?: undefined;
|
||||
infoText?: undefined;
|
||||
withInfoBadge?: undefined;
|
||||
};
|
||||
|
||||
type AddUsersPanelProps = TSelectorInfo & {
|
||||
isEncrypted: boolean;
|
||||
defaultAccess: ShareAccessRights;
|
||||
onClose: () => void;
|
||||
onParentPanelClose: () => void;
|
||||
setActiveTabId: (tab: string) => void;
|
||||
|
||||
setDataItems: (items: TSelectorItem[]) => void;
|
||||
|
||||
@ -189,6 +198,9 @@ const AddUsersPanel = ({
|
||||
|
||||
invitedUsers,
|
||||
disableDisabledUsers,
|
||||
infoText,
|
||||
withInfo,
|
||||
setActiveTabId: setActiveTabIdProp,
|
||||
}: AddUsersPanelProps) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation([
|
||||
@ -301,10 +313,14 @@ const AddUsersPanel = ({
|
||||
(access) => access.access === accessRight,
|
||||
)[0];
|
||||
|
||||
const changeActiveTab = useCallback((tab: number | string) => {
|
||||
setActiveTabId(`${tab}`);
|
||||
isFirstLoad.current = true;
|
||||
}, []);
|
||||
const changeActiveTab = useCallback(
|
||||
(tab: number | string) => {
|
||||
setActiveTabIdProp(`${tab}`);
|
||||
setActiveTabId(`${tab}`);
|
||||
isFirstLoad.current = true;
|
||||
},
|
||||
[setActiveTabIdProp],
|
||||
);
|
||||
|
||||
const onSearch = useCallback(
|
||||
(value: string, callback?: Function) => {
|
||||
@ -565,6 +581,8 @@ const AddUsersPanel = ({
|
||||
isLoading={isLoading}
|
||||
searchLoader={<SearchLoader />}
|
||||
isSearchLoading={isInit}
|
||||
infoText={infoText}
|
||||
withInfo={withInfo}
|
||||
rowLoader={
|
||||
<RowLoader
|
||||
isUser
|
||||
|
@ -26,20 +26,14 @@
|
||||
|
||||
import styled, { css } from "styled-components";
|
||||
import { Heading } from "@docspace/shared/components/heading";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { DropDown } from "@docspace/shared/components/drop-down";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { ToggleButton } from "@docspace/shared/components/toggle-button";
|
||||
import { mobile, commonIconsStyles } from "@docspace/shared/utils";
|
||||
import CheckIcon from "PUBLIC_DIR/images/check.edit.react.svg";
|
||||
import CrossIcon from "PUBLIC_DIR/images/cross.edit.react.svg";
|
||||
import CrossIconMobile from "PUBLIC_DIR/images/cross.react.svg";
|
||||
import DeleteIcon from "PUBLIC_DIR/images/mobile.actions.remove.react.svg";
|
||||
import { isMobile, desktop, commonInputStyles } from "@docspace/shared/utils";
|
||||
import Base from "@docspace/shared/themes/base";
|
||||
|
||||
@ -210,6 +204,17 @@ const StyledRow = styled.div`
|
||||
.combo-buttons_expander-icon path {
|
||||
fill: ${(props) => props.theme.text.disableColor};
|
||||
}
|
||||
|
||||
.remove-icon {
|
||||
cursor: pointer;
|
||||
margin-inline-start: auto;
|
||||
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.text.disableColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledInviteInput = styled.div`
|
||||
@ -266,21 +271,6 @@ const StyledInviteInput = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledAccessSelector = styled.div`
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-left: 16px;
|
||||
`
|
||||
: css`
|
||||
margin-right: 16px;
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledEditInput = styled(TextInput)`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledInviteInputContainer = styled.div`
|
||||
position: relative;
|
||||
display: flex;
|
||||
@ -350,12 +340,6 @@ const SearchItemText = styled(Text)`
|
||||
|
||||
SearchItemText.defaultProps = { theme: Base };
|
||||
|
||||
const StyledEditButton = styled(Button)`
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0px;
|
||||
`;
|
||||
|
||||
const iconStyles = css`
|
||||
${commonIconsStyles}
|
||||
path {
|
||||
@ -366,37 +350,12 @@ const iconStyles = css`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCheckIcon = styled(CheckIcon)`
|
||||
${iconStyles}
|
||||
`;
|
||||
|
||||
StyledCheckIcon.defaultProps = { theme: Base };
|
||||
|
||||
const StyledCrossIcon = styled(CrossIcon)`
|
||||
${iconStyles}
|
||||
`;
|
||||
|
||||
StyledCrossIcon.defaultProps = { theme: Base };
|
||||
|
||||
const StyledDeleteIcon = styled(DeleteIcon)`
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: auto;
|
||||
`
|
||||
: css`
|
||||
margin-left: auto;
|
||||
`}
|
||||
|
||||
${iconStyles}
|
||||
`;
|
||||
|
||||
StyledDeleteIcon.defaultProps = { theme: Base };
|
||||
|
||||
const StyledHelpButton = styled(HelpButton)`
|
||||
margin-inline-start: 8px;
|
||||
`;
|
||||
|
||||
const StyledButtons = styled(Box)`
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
@ -415,17 +374,6 @@ const StyledLink = styled(Link)`
|
||||
theme.interfaceDirection === "rtl" ? `left` : `right`};
|
||||
`;
|
||||
|
||||
const ResetLink = styled(Link)`
|
||||
float: ${({ theme }) =>
|
||||
theme.interfaceDirection === "rtl" ? `right` : `left`};
|
||||
padding: 0 16px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 13px;
|
||||
color: ${(props) => props.theme.createEditRoomDialog.commonParam.textColor};
|
||||
font-style: normal;
|
||||
line-height: 15px;
|
||||
`;
|
||||
|
||||
StyledButtons.defaultProps = { theme: Base };
|
||||
|
||||
const StyledToggleButton = styled(ToggleButton)`
|
||||
@ -459,60 +407,7 @@ const StyledControlContainer = styled.div`
|
||||
left: unset;
|
||||
}
|
||||
`;
|
||||
const StyledInviteLanguage = styled.div`
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
margin-top: -12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
height: 28px;
|
||||
color: ${(props) =>
|
||||
props.theme.createEditRoomDialog.commonParam.descriptionColor};
|
||||
margin-bottom: 4px;
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
.list-link {
|
||||
margin-left: 4px;
|
||||
color: ${(props) => props.theme.createEditRoomDialog.commonParam.textColor};
|
||||
}
|
||||
|
||||
.invitation-language {
|
||||
color: ${(props) =>
|
||||
props.theme.createEditRoomDialog.commonParam.descriptionColor};
|
||||
}
|
||||
.language-combo-box {
|
||||
.combo-button {
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.combo-buttons_arrow-icon {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.combo-button_closed:not(:hover) .combo-button-label {
|
||||
color: ${(props) =>
|
||||
props.theme.createEditRoomDialog.commonParam.descriptionColor};
|
||||
}
|
||||
.combo-button_closed:not(:hover) .combo-buttons_arrow-icon {
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) =>
|
||||
props.theme.createEditRoomDialog.commonParam.descriptionColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.language-combo-box-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
`;
|
||||
const StyledCrossIconMobile = styled(CrossIconMobile)`
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
@ -522,6 +417,32 @@ const StyledCrossIconMobile = styled(CrossIconMobile)`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledBody = styled.div`
|
||||
display: contents;
|
||||
|
||||
${({ isDisabled, theme }) =>
|
||||
isDisabled
|
||||
? css`
|
||||
.invite-input-text {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
color: ${theme.text.disableColor};
|
||||
}
|
||||
.invite-input-avatar {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.invite-input {
|
||||
box-shadow: unset !important;
|
||||
}
|
||||
`
|
||||
: css`
|
||||
.invite-input-text {
|
||||
color: ${theme.text.color};
|
||||
}
|
||||
`};
|
||||
`;
|
||||
|
||||
StyledCrossIcon.defaultProps = { theme: Base };
|
||||
export {
|
||||
StyledBlock,
|
||||
@ -533,21 +454,14 @@ export {
|
||||
StyledInviteInputContainer,
|
||||
StyledDropDown,
|
||||
SearchItemText,
|
||||
StyledEditInput,
|
||||
StyledEditButton,
|
||||
StyledCheckIcon,
|
||||
StyledCrossIcon,
|
||||
StyledHelpButton,
|
||||
StyledDeleteIcon,
|
||||
StyledButtons,
|
||||
StyledLink,
|
||||
ResetLink,
|
||||
ScrollList,
|
||||
StyledAccessSelector,
|
||||
StyledToggleButton,
|
||||
StyledDescription,
|
||||
StyledInviteLanguage,
|
||||
StyledControlContainer,
|
||||
StyledCrossIconMobile,
|
||||
StyledInviteUserBody,
|
||||
StyledBody,
|
||||
};
|
||||
|
@ -45,6 +45,7 @@ import {
|
||||
StyledSubHeader,
|
||||
StyledToggleButton,
|
||||
StyledDescription,
|
||||
StyledBody,
|
||||
} from "./StyledInvitePanel";
|
||||
|
||||
import ItemsList from "./sub-components/ItemsList";
|
||||
@ -69,8 +70,6 @@ const TemplateAccessSettingsPanel = ({
|
||||
const [addUsersPanelVisible, setAddUsersPanelVisible] = useState(false);
|
||||
const [isMobileView, setIsMobileView] = useState(isMobile());
|
||||
|
||||
const invitePanelBodyRef = useRef();
|
||||
|
||||
const zIndex = 311;
|
||||
|
||||
useEffect(() => {
|
||||
@ -139,29 +138,31 @@ const TemplateAccessSettingsPanel = ({
|
||||
{t("Files:TemplateAvailableDescription")}
|
||||
</StyledDescription>
|
||||
</StyledBlock>
|
||||
<InviteInput
|
||||
t={t}
|
||||
onClose={onClose}
|
||||
inviteItems={inviteItems}
|
||||
setInviteItems={setInviteItems}
|
||||
roomType={roomType}
|
||||
addUsersPanelVisible={addUsersPanelVisible}
|
||||
setAddUsersPanelVisible={setAddUsersPanelVisible}
|
||||
isMobileView={isMobileView}
|
||||
/>
|
||||
<StyledSubHeader>{t("Files:AccessToTemplate")}</StyledSubHeader>
|
||||
{hasInvitedUsers && (
|
||||
<ItemsList
|
||||
<StyledBody isDisabled={isAvailable}>
|
||||
<InviteInput
|
||||
t={t}
|
||||
onClose={onClose}
|
||||
inviteItems={inviteItems}
|
||||
setInviteItems={setInviteItems}
|
||||
setHasErrors={setHasErrors}
|
||||
roomType={roomType}
|
||||
scrollAllPanelContent={scrollAllPanelContent}
|
||||
invitePanelBodyRef={invitePanelBodyRef}
|
||||
addUsersPanelVisible={addUsersPanelVisible}
|
||||
setAddUsersPanelVisible={setAddUsersPanelVisible}
|
||||
isMobileView={isMobileView}
|
||||
isDisabled={isAvailable}
|
||||
/>
|
||||
)}
|
||||
<StyledSubHeader className="invite-input-text">
|
||||
{t("Files:AccessToTemplate")}
|
||||
</StyledSubHeader>
|
||||
{hasInvitedUsers && (
|
||||
<ItemsList
|
||||
t={t}
|
||||
inviteItems={inviteItems}
|
||||
setInviteItems={setInviteItems}
|
||||
scrollAllPanelContent={scrollAllPanelContent}
|
||||
isDisabled={isAvailable}
|
||||
/>
|
||||
)}
|
||||
</StyledBody>
|
||||
</>
|
||||
);
|
||||
}, [
|
||||
@ -171,7 +172,6 @@ const TemplateAccessSettingsPanel = ({
|
||||
setHasErrors,
|
||||
scrollAllPanelContent,
|
||||
hasInvitedUsers,
|
||||
invitePanelBodyRef,
|
||||
]);
|
||||
|
||||
const invitePanelNode = (
|
||||
@ -195,7 +195,7 @@ const TemplateAccessSettingsPanel = ({
|
||||
{
|
||||
<>
|
||||
{scrollAllPanelContent ? (
|
||||
<div className="invite-panel-body" ref={invitePanelBodyRef}>
|
||||
<div className="invite-panel-body">
|
||||
<Scrollbar>{bodyInvitePanel}</Scrollbar>
|
||||
</div>
|
||||
) : (
|
||||
|
@ -48,7 +48,7 @@ import withCultureNames from "SRC_DIR/HOCs/withCultureNames";
|
||||
import { checkIfAccessPaid } from "SRC_DIR/helpers";
|
||||
|
||||
import AddUsersPanel from "../../AddUsersPanel";
|
||||
import { getTopFreeRole } from "../utils";
|
||||
import { getAccessOptions, getTopFreeRole } from "../utils";
|
||||
|
||||
import {
|
||||
StyledSubHeader,
|
||||
@ -60,13 +60,14 @@ import {
|
||||
StyledDescription,
|
||||
StyledCrossIcon,
|
||||
} from "../StyledInvitePanel";
|
||||
import { getDefaultAccessUser } from "@docspace/shared/utils/getDefaultAccessUser";
|
||||
|
||||
const minSearchValue = 1;
|
||||
const PEOPLE_TAB_ID = "0";
|
||||
|
||||
const InviteInput = ({
|
||||
t,
|
||||
roomId = 254, //TODO: Templates
|
||||
roomId = 281, //TODO: Templates
|
||||
onClose,
|
||||
roomType,
|
||||
inviteItems,
|
||||
@ -74,9 +75,12 @@ const InviteInput = ({
|
||||
addUsersPanelVisible,
|
||||
setAddUsersPanelVisible,
|
||||
isMobileView,
|
||||
isOwner,
|
||||
standalone,
|
||||
isDisabled,
|
||||
}) => {
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [selectedTab, setSelectedTab] = useState("");
|
||||
const [selectedTab, setSelectedTab] = useState(PEOPLE_TAB_ID);
|
||||
const [usersList, setUsersList] = useState([]);
|
||||
const [isAddEmailPanelBlocked, setIsAddEmailPanelBlocked] = useState(true);
|
||||
const [dropDownWidth, setDropDownWidth] = useState(0);
|
||||
@ -267,13 +271,22 @@ const InviteInput = ({
|
||||
const filter = new Filter();
|
||||
filter.role = [EmployeeType.Admin, EmployeeType.User]; // 1(EmployeeType.User) - RoomAdmin | 3(EmployeeType.Admin) - DocSpaceAdmin
|
||||
|
||||
const accessOptions = getAccessOptions(
|
||||
t,
|
||||
roomType,
|
||||
false,
|
||||
true,
|
||||
isOwner,
|
||||
standalone,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledSubHeader>
|
||||
<StyledSubHeader className="invite-input-text">
|
||||
{t("Files:AddUsersOrGroups")}
|
||||
|
||||
<StyledLink
|
||||
className="link-list"
|
||||
className="link-list invite-input-text"
|
||||
fontWeight="600"
|
||||
type="action"
|
||||
isHovered
|
||||
@ -301,6 +314,7 @@ const InviteInput = ({
|
||||
isAutoFocussed={true}
|
||||
type="search"
|
||||
withBorder={false}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
|
||||
<div className="append" onClick={onClearInput}>
|
||||
@ -331,6 +345,7 @@ const InviteInput = ({
|
||||
onClose={closeUsersPanel}
|
||||
visible={addUsersPanelVisible}
|
||||
tempDataItems={inviteItems}
|
||||
accessOptions={accessOptions}
|
||||
setDataItems={addItems}
|
||||
isMultiSelect
|
||||
withoutBackground={isMobileView}
|
||||
@ -349,6 +364,7 @@ const InviteInput = ({
|
||||
filter={filter}
|
||||
setActiveTabId={getSelectedTab}
|
||||
isUsersList
|
||||
defaultAccess={getDefaultAccessUser(roomType)}
|
||||
/>
|
||||
)}
|
||||
</StyledInviteInputContainer>
|
||||
|
@ -24,50 +24,16 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import InfoEditReactSvgUrl from "PUBLIC_DIR/images/info.edit.react.svg?url";
|
||||
import AtReactSvgUrl from "PUBLIC_DIR/images/@.react.svg?url";
|
||||
import AlertSvgUrl from "PUBLIC_DIR/images/icons/12/alert.react.svg?url";
|
||||
import { useState, useEffect } from "react";
|
||||
import RemoveReactSvgUrl from "PUBLIC_DIR/images/remove.react.svg?url";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import { parseAddresses } from "@docspace/shared/utils";
|
||||
import { getAccessOptions } from "../utils";
|
||||
import { getUserTypeLabel } from "@docspace/shared/utils/common";
|
||||
import { StyledInviteUserBody } from "../StyledInvitePanel";
|
||||
|
||||
import {
|
||||
StyledEditInput,
|
||||
StyledEditButton,
|
||||
StyledCheckIcon,
|
||||
StyledCrossIcon,
|
||||
StyledHelpButton,
|
||||
StyledDeleteIcon,
|
||||
StyledInviteUserBody,
|
||||
} from "../StyledInvitePanel";
|
||||
import { filterGroupRoleOptions, filterUserRoleOptions } from "SRC_DIR/helpers";
|
||||
|
||||
const Item = ({
|
||||
t,
|
||||
item,
|
||||
setInviteItems,
|
||||
inviteItems,
|
||||
changeInviteItem,
|
||||
setHasErrors,
|
||||
roomType,
|
||||
isOwner,
|
||||
standalone,
|
||||
}) => {
|
||||
const {
|
||||
avatar,
|
||||
displayName,
|
||||
email,
|
||||
id,
|
||||
errors,
|
||||
access,
|
||||
isGroup,
|
||||
name: groupName,
|
||||
warning,
|
||||
} = item;
|
||||
const Item = ({ t, item, setInviteItems, inviteItems, isDisabled }) => {
|
||||
const { avatar, displayName, email, id, isGroup, name: groupName } = item;
|
||||
|
||||
const name = isGroup
|
||||
? groupName
|
||||
@ -78,30 +44,6 @@ const Item = ({
|
||||
: email;
|
||||
const source = !!avatar ? avatar : isGroup ? "" : AtReactSvgUrl;
|
||||
|
||||
const [edit, setEdit] = useState(false);
|
||||
const [inputValue, setInputValue] = useState(name);
|
||||
const [parseErrors, setParseErrors] = useState(errors);
|
||||
|
||||
console.log("roomType", roomType);
|
||||
|
||||
const accesses = getAccessOptions(
|
||||
t,
|
||||
roomType,
|
||||
true,
|
||||
true,
|
||||
isOwner,
|
||||
standalone,
|
||||
);
|
||||
|
||||
const filteredAccesses = item.isGroup
|
||||
? filterGroupRoleOptions(accesses)
|
||||
: filterUserRoleOptions(accesses, item, true);
|
||||
|
||||
console.log("filteredAccesses", filteredAccesses);
|
||||
|
||||
const defaultAccess = filteredAccesses.find(
|
||||
(option) => option.access === +access,
|
||||
);
|
||||
const getUserType = (item) => {
|
||||
if (item.isOwner) return "owner";
|
||||
if (item.isAdmin) return "admin";
|
||||
@ -111,86 +53,29 @@ const Item = ({
|
||||
};
|
||||
|
||||
const type = getUserType(item);
|
||||
|
||||
const typeLabel = item?.isEmailInvite
|
||||
? getUserTypeLabel(defaultAccess.type, t)
|
||||
: (type === "user" && defaultAccess?.type !== type) ||
|
||||
(defaultAccess?.type === "manager" && type !== "admin")
|
||||
? getUserTypeLabel(defaultAccess.type, t)
|
||||
: getUserTypeLabel(type, t);
|
||||
|
||||
const errorsInList = () => {
|
||||
const hasErrors = inviteItems.some((item) => !!item.errors?.length);
|
||||
setHasErrors(hasErrors);
|
||||
};
|
||||
|
||||
const onEdit = (e) => {
|
||||
if (e.detail === 2) {
|
||||
setEdit(true);
|
||||
}
|
||||
};
|
||||
|
||||
const cancelEdit = (e) => {
|
||||
setInputValue(name);
|
||||
setEdit(false);
|
||||
};
|
||||
|
||||
const saveEdit = (e) => {
|
||||
const value = inputValue === "" ? name : inputValue;
|
||||
|
||||
setEdit(false);
|
||||
validateValue(value);
|
||||
};
|
||||
|
||||
const onKeyPress = (e) => {
|
||||
if (edit) {
|
||||
if (e.key === "Enter") {
|
||||
saveEdit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("keyup", onKeyPress);
|
||||
return () => document.removeEventListener("keyup", onKeyPress);
|
||||
});
|
||||
|
||||
const validateValue = (value) => {
|
||||
const email = parseAddresses(value);
|
||||
const parseErrors = email[0].parseErrors;
|
||||
const errors = !!parseErrors.length ? parseErrors : [];
|
||||
|
||||
setParseErrors(errors);
|
||||
changeInviteItem({ id, email: value, errors }).then(() => errorsInList());
|
||||
};
|
||||
|
||||
const changeValue = (e) => {
|
||||
const value = e.target.value.trim();
|
||||
|
||||
setInputValue(value);
|
||||
};
|
||||
|
||||
const hasError = parseErrors && !!parseErrors.length;
|
||||
const typeLabel = getUserTypeLabel(type, t);
|
||||
|
||||
const removeItem = () => {
|
||||
const newItems = inviteItems.filter((item) => item.id !== id);
|
||||
|
||||
setInviteItems(newItems);
|
||||
};
|
||||
|
||||
const selectItemAccess = (selected) => {
|
||||
if (selected.key === "remove") return removeItem();
|
||||
// const canDelete = !isOwner; //TODO: Templates
|
||||
const canDelete = isDisabled ? false : true; //TODO: Templates
|
||||
|
||||
changeInviteItem({ id, access: selected.access });
|
||||
};
|
||||
|
||||
const textProps = !!avatar || isGroup ? {} : { onClick: onEdit };
|
||||
|
||||
const displayBody = (
|
||||
return (
|
||||
<>
|
||||
<Avatar
|
||||
size="min"
|
||||
role={type}
|
||||
source={source}
|
||||
isGroup={isGroup}
|
||||
userName={groupName}
|
||||
className="invite-input-avatar"
|
||||
/>
|
||||
<StyledInviteUserBody>
|
||||
<Text {...textProps} truncate noSelect>
|
||||
{inputValue}
|
||||
<Text truncate noSelect className="invite-input-text">
|
||||
{name}
|
||||
</Text>
|
||||
|
||||
{!isGroup && (
|
||||
@ -206,62 +91,15 @@ const Item = ({
|
||||
</Text>
|
||||
)}
|
||||
</StyledInviteUserBody>
|
||||
|
||||
{hasError ? (
|
||||
<>
|
||||
<StyledHelpButton
|
||||
iconName={InfoEditReactSvgUrl}
|
||||
displayType="auto"
|
||||
offsetRight={0}
|
||||
tooltipContent={t("EmailErrorMessage")}
|
||||
openOnClick={false}
|
||||
size={16}
|
||||
color="#F21C0E"
|
||||
/>
|
||||
<StyledDeleteIcon
|
||||
className="delete-icon"
|
||||
size="medium"
|
||||
onClick={removeItem}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{warning && (
|
||||
<div className="warning">
|
||||
<StyledHelpButton
|
||||
tooltipContent={warning}
|
||||
iconName={AlertSvgUrl}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
{canDelete && (
|
||||
<ReactSVG
|
||||
className="remove-icon"
|
||||
src={RemoveReactSvgUrl}
|
||||
onClick={removeItem}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
const okIcon = <StyledCheckIcon size="scale" />;
|
||||
const cancelIcon = <StyledCrossIcon size="scale" />;
|
||||
|
||||
const editBody = (
|
||||
<>
|
||||
<StyledEditInput value={inputValue} onChange={changeValue} />
|
||||
<StyledEditButton icon={okIcon} onClick={saveEdit} />
|
||||
<StyledEditButton icon={cancelIcon} onClick={cancelEdit} />
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Avatar
|
||||
size="min"
|
||||
role={type}
|
||||
source={source}
|
||||
isGroup={isGroup}
|
||||
userName={groupName}
|
||||
/>
|
||||
{edit ? editBody : displayBody}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Item;
|
||||
|
@ -24,8 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useState, useEffect, useRef, memo, useCallback } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { useState, useEffect, useRef, memo, useCallback } from "react";
|
||||
import { FixedSizeList as List } from "react-window";
|
||||
import { CustomScrollbarsVirtualList } from "@docspace/shared/components/scrollbar";
|
||||
import useResizeObserver from "use-resize-observer";
|
||||
@ -38,18 +37,7 @@ const FOOTER_HEIGHT = 73;
|
||||
const USER_ITEM_HEIGHT = 48;
|
||||
|
||||
const Row = memo(({ data, index, style }) => {
|
||||
const {
|
||||
inviteItems,
|
||||
setInviteItems,
|
||||
changeInviteItem,
|
||||
t,
|
||||
setHasErrors,
|
||||
roomType,
|
||||
isOwner,
|
||||
setIsOpenItemAccess,
|
||||
isMobileView,
|
||||
standalone,
|
||||
} = data;
|
||||
const { inviteItems, setInviteItems, t, isDisabled } = data;
|
||||
|
||||
if (inviteItems === undefined) return;
|
||||
|
||||
@ -66,14 +54,8 @@ const Row = memo(({ data, index, style }) => {
|
||||
t={t}
|
||||
item={item}
|
||||
setInviteItems={setInviteItems}
|
||||
changeInviteItem={changeInviteItem}
|
||||
inviteItems={inviteItems}
|
||||
setHasErrors={setHasErrors}
|
||||
roomType={roomType}
|
||||
isOwner={isOwner}
|
||||
setIsOpenItemAccess={setIsOpenItemAccess}
|
||||
isMobileView={isMobileView}
|
||||
standalone={standalone}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
</StyledRow>
|
||||
);
|
||||
@ -83,20 +65,13 @@ const ItemsList = ({
|
||||
t,
|
||||
setInviteItems,
|
||||
inviteItems,
|
||||
changeInviteItem,
|
||||
setHasErrors,
|
||||
roomType,
|
||||
isOwner,
|
||||
externalLinksVisible,
|
||||
scrollAllPanelContent,
|
||||
invitePanelBodyRef,
|
||||
isMobileView,
|
||||
standalone,
|
||||
isDisabled,
|
||||
}) => {
|
||||
const [bodyHeight, setBodyHeight] = useState(0);
|
||||
const [offsetTop, setOffsetTop] = useState(0);
|
||||
const [isTotalListHeight, setIsTotalListHeight] = useState(false);
|
||||
const [isOpenItemAccess, setIsOpenItemAccess] = useState(false);
|
||||
const bodyRef = useRef();
|
||||
const { height } = useResizeObserver({ ref: bodyRef });
|
||||
const { interfaceDirection } = useTheme();
|
||||
@ -106,22 +81,13 @@ const ItemsList = ({
|
||||
const heightList = height ? height : bodyRef.current.offsetHeight;
|
||||
const totalHeightItems = inviteItems.length * USER_ITEM_HEIGHT;
|
||||
const listAreaHeight = heightList;
|
||||
const heightBody = invitePanelBodyRef?.current?.clientHeight;
|
||||
const fullHeightList = heightBody - bodyRef.current.offsetTop;
|
||||
const heightWitchOpenItemAccess = Math.max(scrollHeight, fullHeightList);
|
||||
|
||||
const calculatedHeight = scrollAllPanelContent
|
||||
? Math.max(
|
||||
totalHeightItems,
|
||||
listAreaHeight,
|
||||
isOpenItemAccess ? heightWitchOpenItemAccess : 0,
|
||||
)
|
||||
? Math.max(totalHeightItems, listAreaHeight, 0)
|
||||
: heightList - FOOTER_HEIGHT;
|
||||
|
||||
const finalHeight = scrollAllPanelContent
|
||||
? isOpenItemAccess
|
||||
? calculatedHeight
|
||||
: totalHeightItems
|
||||
? totalHeightItems
|
||||
: calculatedHeight;
|
||||
|
||||
setBodyHeight(finalHeight);
|
||||
@ -136,7 +102,6 @@ const ItemsList = ({
|
||||
bodyRef?.current?.offsetHeight,
|
||||
inviteItems.length,
|
||||
scrollAllPanelContent,
|
||||
isOpenItemAccess,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -147,14 +112,10 @@ const ItemsList = ({
|
||||
height,
|
||||
inviteItems.length,
|
||||
scrollAllPanelContent,
|
||||
isOpenItemAccess,
|
||||
]);
|
||||
|
||||
const overflowStyle = scrollAllPanelContent ? "hidden" : "scroll";
|
||||
|
||||
const willChangeStyle =
|
||||
isMobileView && isOpenItemAccess ? "auto" : "transform";
|
||||
|
||||
return (
|
||||
<ScrollList
|
||||
offsetTop={offsetTop}
|
||||
@ -163,23 +124,17 @@ const ItemsList = ({
|
||||
isTotalListHeight={isTotalListHeight}
|
||||
>
|
||||
<List
|
||||
style={{ overflow: overflowStyle, willChange: willChangeStyle }}
|
||||
style={{ overflow: overflowStyle, willChange: "transform" }}
|
||||
direction={interfaceDirection}
|
||||
height={bodyHeight}
|
||||
width="auto"
|
||||
itemCount={inviteItems.length}
|
||||
itemSize={USER_ITEM_HEIGHT}
|
||||
itemData={{
|
||||
t,
|
||||
inviteItems,
|
||||
setInviteItems,
|
||||
changeInviteItem,
|
||||
setHasErrors,
|
||||
roomType,
|
||||
isOwner,
|
||||
setIsOpenItemAccess,
|
||||
isMobileView,
|
||||
t,
|
||||
standalone,
|
||||
isDisabled,
|
||||
}}
|
||||
outerElementType={!scrollAllPanelContent && CustomScrollbarsVirtualList}
|
||||
>
|
||||
@ -189,14 +144,4 @@ const ItemsList = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ userStore, dialogsStore, settingsStore }) => {
|
||||
const { changeInviteItem } = dialogsStore;
|
||||
const { isOwner } = userStore.user;
|
||||
const { standalone } = settingsStore;
|
||||
|
||||
return {
|
||||
changeInviteItem,
|
||||
isOwner,
|
||||
standalone,
|
||||
};
|
||||
})(observer(ItemsList));
|
||||
export default ItemsList;
|
||||
|
Loading…
Reference in New Issue
Block a user