Web: Client: Add showing groups in members panel. Add members search/

This commit is contained in:
Aleksandr Lushkin 2024-02-13 18:50:56 +01:00
parent eaf83a10d4
commit 9b9b20a493
10 changed files with 361 additions and 78 deletions

View File

@ -3,6 +3,7 @@ import { inject, observer } from "mobx-react";
import ViewHelper from "./helpers/ViewHelper";
import ItemTitle from "./sub-components/ItemTitle";
import Search from "./sub-components/Search";
import { StyledInfoPanelBody } from "./styles/common";
@ -18,6 +19,8 @@ const InfoPanelBodyContent = ({
getIsGallery,
gallerySelected,
isRootFolder,
showSearchBlock,
setShowSearchBlock,
...props
}) => {
const [selectedItems, setSelectedItems] = useState(props.selectedItems);
@ -103,7 +106,7 @@ const InfoPanelBodyContent = ({
useEffect(() => {
const selectedFolderChanged = isItemChanged(
selectedFolder,
props.selectedFolder
props.selectedFolder,
);
if (selectedFolderChanged) setSelectedFolder(props.selectedFolder);
}, [props.selectedFolder]);
@ -118,6 +121,8 @@ const InfoPanelBodyContent = ({
return (
<StyledInfoPanelBody>
{showSearchBlock && <Search />}
{!isNoItem && (
<ItemTitle
{...defaultProps}
@ -144,6 +149,8 @@ export default inject(
getIsGallery,
infoPanelSelectedItems,
getInfoPanelSelectedFolder,
showSearchBlock,
setShowSearchBlock,
} = infoPanelStore;
const { gallerySelected } = oformsStore;
@ -166,6 +173,9 @@ export default inject(
isRootFolder,
gallerySelected,
showSearchBlock,
setShowSearchBlock,
};
}
},
)(observer(InfoPanelBodyContent));

View File

@ -181,6 +181,23 @@ const StyledTitle = styled.div`
}
`;
const StyledSearchContainer = styled.div`
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
gap: 8px;
height: 68px;
width: 100%;
padding: 0 16px;
border-radius: 0 0 6px 6px;
background-color: ${(props) => props.theme.infoPanel.backgroundColor};
z-index: 101;
box-shadow: 0px 5px 20px 0px rgba(4, 15, 27, 0.07);
`;
const StyledLink = styled.div`
display: flex;
padding: 8px 0;
@ -309,6 +326,7 @@ StyledTitle.defaultProps = { theme: Base };
export {
StyledInfoPanelBody,
StyledTitle,
StyledSearchContainer,
StyledSubtitle,
StyledProperties,
StyledLink,

View File

@ -5,6 +5,7 @@ import { Text } from "@docspace/shared/components/text";
import { inject, observer } from "mobx-react";
import PersonPlusReactSvgUrl from "PUBLIC_DIR/images/person+.react.svg?url";
import Planet12ReactSvgUrl from "PUBLIC_DIR/images/icons/12/planet.react.svg?url";
import SearchIconReactSvgUrl from "PUBLIC_DIR/images/search.react.svg?url";
import { IconButton } from "@docspace/shared/components/icon-button";
import { StyledTitle } from "../../../styles/common";
import { RoomIcon } from "@docspace/shared/components/room-icon";
@ -29,6 +30,7 @@ const RoomsItemHeader = ({
setBufferSelection,
isArchive,
hasLinks,
setShowSearchBlock,
}) => {
const itemTitleRef = useRef();
@ -39,13 +41,13 @@ const RoomsItemHeader = ({
const showDefaultRoomIcon = !isLoadedRoomIcon && selection.isRoom;
const security = infoPanelSelection ? infoPanelSelection.security : {};
const canInviteUserInRoomAbility = security?.EditAccess;
const showInviteUserIcon = selection?.isRoom && roomsView === "info_members";
const showPlanetIcon =
(selection.roomType === RoomsType.PublicRoom ||
selection.roomType === RoomsType.CustomRoom) &&
hasLinks;
const badgeUrl = showPlanetIcon ? Planet12ReactSvgUrl : null;
const isRoomMembersPanel = selection?.isRoom && roomsView === "info_members";
const onSelectItem = () => {
setSelected("none");
@ -71,6 +73,8 @@ const RoomsItemHeader = ({
});
};
const onSearchClick = () => setShowSearchBlock(true);
return (
<StyledTitle ref={itemTitleRef}>
<div className="item-icon">
@ -88,7 +92,18 @@ const RoomsItemHeader = ({
<Text className="text">{selection.title}</Text>
<div className="info_title-icons">
{canInviteUserInRoomAbility && showInviteUserIcon && (
{isRoomMembersPanel && (
<IconButton
id="info_search"
className="icon"
title={t("Common:Search")}
iconName={SearchIconReactSvgUrl}
onClick={onSearchClick}
size={16}
/>
)}
{canInviteUserInRoomAbility && isRoomMembersPanel && (
<IconButton
id="info_add-user"
className={"icon"}
@ -119,7 +134,12 @@ export default inject(
infoPanelStore,
publicRoomStore,
}) => {
const { infoPanelSelection, roomsView, setIsMobileHidden } = infoPanelStore;
const {
infoPanelSelection,
roomsView,
setIsMobileHidden,
setShowSearchBlock,
} = infoPanelStore;
const { externalLinks } = publicRoomStore;
const selection = infoPanelSelection.length > 1 ? null : infoPanelSelection;
@ -130,6 +150,7 @@ export default inject(
roomsView,
infoPanelSelection,
setIsMobileHidden,
setShowSearchBlock,
isGracePeriod: currentTariffStatusStore.isGracePeriod,
@ -146,7 +167,7 @@ export default inject(
isArchive,
hasLinks: externalLinks.length,
};
}
},
)(
withTranslation([
"Files",
@ -154,5 +175,5 @@ export default inject(
"Translations",
"InfoPanel",
"SharingPanel",
])(observer(RoomsItemHeader))
])(observer(RoomsItemHeader)),
);

View File

@ -0,0 +1,77 @@
import { ChangeEvent, useCallback, useEffect, useState } from "react";
import debounce from "lodash.debounce";
import { inject } from "mobx-react";
import XIconReactSvgUrl from "PUBLIC_DIR/images/x.react.svg?url";
import {
InputSize,
InputType,
TextInput,
} from "@docspace/shared/components/text-input";
import { IconButton } from "@docspace/shared/components/icon-button";
import { StyledSearchContainer } from "../styles/common";
interface SearchProps {
setSearchValue: (value: string) => void;
resetSearch: () => void;
}
const Search = ({ setSearchValue, resetSearch }: SearchProps) => {
const [value, setValue] = useState("");
const onClose = () => {
resetSearch();
};
const onEscapeUp = (e: KeyboardEvent) => {
if (e.key === "Esc" || e.key === "Escape") {
e.stopPropagation();
onClose();
}
};
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
const newValue = e.currentTarget.value;
setValue(newValue);
debouncedSearch(newValue.trim());
};
const debouncedSearch = useCallback(
debounce((value: string) => setSearchValue(value), 300),
[],
);
useEffect(() => {
window.addEventListener("keyup", onEscapeUp);
return () => window.removeEventListener("keyup", onEscapeUp);
}, []);
return (
<StyledSearchContainer>
<TextInput
id="info_panel_search_input"
type={InputType.text}
size={InputSize.base}
scale={true}
onChange={onChange}
value={value}
isAutoFocussed
/>
<IconButton
id="search_close"
iconName={XIconReactSvgUrl}
size={16}
onClick={onClose}
isClickable
/>
</StyledSearchContainer>
);
};
export default inject(({ infoPanelStore }) => ({
resetSearch: infoPanelStore.resetSearch,
setSearchValue: infoPanelStore.setSearchValue,
}))(Search);

View File

@ -8,7 +8,7 @@ import DefaultUserPhotoUrl from "PUBLIC_DIR/images/default_user_photo_size_82-82
import { toastr } from "@docspace/shared/components/toast";
import { isMobileOnly, isMobile } from "react-device-detect";
import { decode } from "he";
import { filterUserRoleOptions } from "SRC_DIR/helpers";
import { filterGroupRoleOptions, filterUserRoleOptions } from "SRC_DIR/helpers";
import { getUserRole, getUserTypeLabel } from "@docspace/shared/utils/common";
import { Text } from "@docspace/shared/components/text";
@ -16,6 +16,7 @@ import EmailPlusReactSvgUrl from "PUBLIC_DIR/images/e-mail+.react.svg?url";
import { StyledUserTypeHeader } from "../../styles/members";
import { IconButton } from "@docspace/shared/components/icon-button";
import { Tooltip } from "@docspace/shared/components/tooltip";
import { Link } from "@docspace/shared/components/link";
const User = ({
t,
@ -33,15 +34,17 @@ const User = ({
showTooltip,
infoPanelMembers,
setInfoPanelMembers,
searchValue,
}) => {
if (!infoPanelSelection) return null;
if (!user.displayName && !user.email) return null;
if (!user.displayName && !user.name && !user.email) return null;
const security = infoPanelSelection ? infoPanelSelection.security : {};
const isExpect = user.isExpect;
const canInviteUserInRoomAbility = security?.EditAccess;
const showInviteIcon = canInviteUserInRoomAbility && isExpect;
const canChangeUserRole = user.canEditAccess;
const withoutTitles = !!searchValue;
const [isLoading, setIsLoading] = useState(false);
@ -51,7 +54,9 @@ const User = ({
);
const userRole = membersHelper.getOptionByUserAccess(user.access, user);
const userRoleOptions = filterUserRoleOptions(fullRoomRoleOptions, user);
const userRoleOptions = user.isGroup
? filterGroupRoleOptions(fullRoomRoleOptions)
: filterUserRoleOptions(fullRoomRoleOptions, user);
const onRepeatInvitation = async () => {
resendEmailInvitations(infoPanelSelection.id, true)
@ -81,22 +86,30 @@ const User = ({
expected: infoPanelMembers.expected?.filter(
(m) => m.id !== user.id,
),
groups: infoPanelMembers.groups?.filter((m) => m.id !== user.id),
};
const roomId = infoPanelSelection.id;
const newUsers = newMembers.users.length > 1 ? newMembers?.users : [];
const minItemsCount = withoutTitles ? 0 : 1;
const newUsers =
newMembers.users.length > minItemsCount ? newMembers?.users : [];
const newAdministrators =
newMembers.administrators.length > 1
newMembers.administrators.length > minItemsCount
? newMembers?.administrators
: [];
const newExpected =
newMembers.expected.length > 1 ? newMembers?.expected : [];
newMembers.expected.length > minItemsCount
? newMembers?.expected
: [];
const newGroups =
newMembers.groups.length > minItemsCount ? newMembers?.groups : [];
setInfoPanelMembers({
roomId,
users: newUsers,
administrators: newAdministrators,
expected: newExpected,
groups: newGroups,
});
newMembersFilter.total -= 1;
@ -115,6 +128,7 @@ const User = ({
],
users: [...newUsers, ...fetchedMembers.users],
expected: [...newExpected, ...fetchedMembers.expected],
groups: [...newGroups, ...fetchedMembers.groups],
};
setInfoPanelMembers({
@ -136,6 +150,9 @@ const User = ({
expected: infoPanelMembers.expected?.map((m) =>
m.id === user.id ? { ...m, access: option.access } : m,
),
groups: infoPanelMembers.groups?.map((m) =>
m.id === user.id ? { ...m, access: option.access } : m,
),
});
}
})
@ -203,7 +220,15 @@ const User = ({
</div>
);
const userAvatar = user.hasAvatar ? user.avatar : DefaultUserPhotoUrl;
const onOpenGroup = () => {
console.log("Open group: ", user.name);
};
const userAvatar = user.hasAvatar
? user.avatar
: user.isGroup
? ""
: DefaultUserPhotoUrl;
const withTooltip = user.isOwner || user.isAdmin;
@ -235,16 +260,23 @@ const User = ({
className="avatar"
size="min"
source={isExpect ? AtReactSvgUrl : userAvatar || ""}
userName={isExpect ? "" : user.displayName}
userName={isExpect ? "" : user.displayName || user.name}
withTooltip={withTooltip}
tooltipContent={tooltipContent}
hideRoleIcon={!withTooltip}
isGroup={user.isGroup}
/>
<div className="user_body-wrapper">
<div className="name-wrapper">
<Text className="name" data-tooltip-id={uniqueTooltipId}>
{decode(user.displayName)}
</Text>
{user.isGroup ? (
<Link className="name" type="action" onClick={onOpenGroup}>
{decode(user.name)}
</Link>
) : (
<Text className="name" data-tooltip-id={uniqueTooltipId}>
{decode(user.displayName)}
</Text>
)}
{/* TODO: uncomment when information about online statuses appears */}
{/* {showTooltip && (
<Tooltip
@ -258,19 +290,21 @@ const User = ({
<div className="me-label">&nbsp;{`(${t("Common:MeLabel")})`}</div>
)}
</div>
<div className="role-email" style={{ display: "flex" }}>
<Text
className="label"
fontWeight={400}
fontSize="12px"
noSelect
truncate
color="#A3A9AE"
dir="auto"
>
{`${typeLabel} | ${user.email}`}
</Text>
</div>
{!user.isGroup && (
<div className="role-email" style={{ display: "flex" }}>
<Text
className="label"
fontWeight={400}
fontSize="12px"
noSelect
truncate
color="#A3A9AE"
dir="auto"
>
{`${typeLabel} | ${user.email}`}
</Text>
</div>
)}
</div>
{userRole && userRoleOptions && (
@ -311,6 +345,7 @@ export default inject(({ infoPanelStore, filesStore, peopleStore }) => {
infoPanelMembers,
setInfoPanelMembers,
fetchMembers,
searchValue,
} = infoPanelStore;
const {
updateRoomMemberRole,
@ -332,5 +367,6 @@ export default inject(({ infoPanelStore, filesStore, peopleStore }) => {
infoPanelMembers,
setInfoPanelMembers,
fetchMembers,
searchValue,
};
})(observer(User));

View File

@ -11,6 +11,7 @@ import MembersList from "./sub-components/MembersList";
import User from "./User";
import PublicRoomBar from "./sub-components/PublicRoomBar";
import { LinksBlock, StyledLinkRow } from "./sub-components/StyledPublicRoom";
import EmptyContainer from "./sub-components/EmptyContainer";
import { Text } from "@docspace/shared/components/text";
import { Link } from "@docspace/shared/components/link";
@ -44,29 +45,33 @@ const Members = ({
withPublicRoomBlock,
fetchMembers,
membersIsLoading,
searchValue,
searchResultIsLoading,
}) => {
const withoutTitlesAndLinks = !!searchValue;
const membersHelper = new MembersHelper({ t });
const updateInfoPanelMembers = async () => {
if (!infoPanelSelection) return;
const fetchedMembers = await fetchMembers(t);
const fetchedMembers = await fetchMembers(t, true, withoutTitlesAndLinks);
setInfoPanelMembers(fetchedMembers);
};
useEffect(() => {
updateInfoPanelMembers();
}, [infoPanelSelection]);
}, [infoPanelSelection, searchValue]);
const loadNextPage = async () => {
const roomId = infoPanelSelection.id;
const fetchedMembers = await fetchMembers(t, false);
const { users, administrators, expected } = fetchedMembers;
const fetchedMembers = await fetchMembers(t, false, withoutTitlesAndLinks);
const { users, administrators, expected, groups } = fetchedMembers;
const newMembers = {
roomId: roomId,
administrators: [...infoPanelMembers.administrators, ...administrators],
users: [...infoPanelMembers.users, ...users],
expected: [...infoPanelMembers.expected, ...expected],
groups: [...infoPanelMembers.groups, ...groups],
};
setInfoPanelMembers(newMembers);
@ -76,18 +81,24 @@ const Members = ({
else if (!infoPanelMembers) return <></>;
const [currentMember] = infoPanelMembers.administrators.filter(
(member) => member.id === selfId
(member) => member.id === selfId,
);
const { administrators, users, expected } = infoPanelMembers;
const { administrators, users, expected, groups } = infoPanelMembers;
const membersList = [...administrators, ...users, ...expected];
const membersList = [...administrators, ...groups, ...users, ...expected];
const adminsTitleCount = administrators.length ? 1 : 0;
const usersTitleCount = users.length ? 1 : 0;
const expectedTitleCount = expected.length ? 1 : 0;
const groupsTitleCount = groups.length ? 1 : 0;
const headersCount = adminsTitleCount + usersTitleCount + expectedTitleCount;
const headersCount = withoutTitlesAndLinks
? 0
: adminsTitleCount +
usersTitleCount +
expectedTitleCount +
groupsTitleCount;
const onAddNewLink = async () => {
if (isPublicRoom || primaryLink) {
@ -104,7 +115,7 @@ const Members = ({
const publicRoomItems = [];
if (isPublicRoomType && withPublicRoomBlock) {
if (isPublicRoomType && withPublicRoomBlock && !withoutTitlesAndLinks) {
if (!isArchiveFolder || primaryLink) {
publicRoomItems.push(
<LinksBlock key="general-link_header">
@ -116,7 +127,7 @@ const Members = ({
<div
data-tooltip-id="emailTooltip"
data-tooltip-content={t(
"Files:MaximumNumberOfExternalLinksCreated"
"Files:MaximumNumberOfExternalLinksCreated",
)}
>
<IconButton
@ -140,31 +151,31 @@ const Members = ({
)}
</div>
)}
</LinksBlock>
</LinksBlock>,
);
}
if (primaryLink) {
if (primaryLink && !withoutTitlesAndLinks) {
publicRoomItems.push(
<LinkRow
key="general-link"
link={primaryLink}
setIsScrollLocked={setIsScrollLocked}
/>
/>,
);
}
if (additionalLinks.length) {
if (additionalLinks.length && !withoutTitlesAndLinks) {
additionalLinks.map((link) => {
publicRoomItems.push(
<LinkRow
link={link}
key={link?.sharedTo?.id}
setIsScrollLocked={setIsScrollLocked}
/>
/>,
);
});
} else if (!isArchiveFolder && !primaryLink) {
} else if (!isArchiveFolder && !primaryLink && !withoutTitlesAndLinks) {
publicRoomItems.push(
<StyledLinkRow
key="create-additional-link"
@ -182,15 +193,21 @@ const Members = ({
>
{t("Files:CreateNewLink")}
</Link>
</StyledLinkRow>
</StyledLinkRow>,
);
}
}
const showPublicRoomBar =
((primaryLink && !isArchiveFolder) || isPublicRoom) && withPublicRoomBlock;
((primaryLink && !isArchiveFolder) || isPublicRoom) &&
withPublicRoomBlock &&
!withoutTitlesAndLinks;
const publicRoomItemsLength = publicRoomItems.length;
if (!membersList.length) {
return <EmptyContainer />;
}
return (
<>
{showPublicRoomBar && (
@ -202,7 +219,10 @@ const Members = ({
<MembersList
loadNextPage={loadNextPage}
hasNextPage={membersList.length - headersCount < membersFilter.total}
hasNextPage={
membersList.length - headersCount < membersFilter.total &&
!searchResultIsLoading
}
itemCount={membersFilter.total + headersCount + publicRoomItemsLength}
showPublicRoomBar={showPublicRoomBar}
linksBlockLength={publicRoomItemsLength}
@ -247,6 +267,8 @@ export default inject(
fetchMembers,
membersIsLoading,
withPublicRoomBlock,
searchValue,
searchResultIsLoading,
} = infoPanelStore;
const { membersFilter } = filesStore;
const { id: selfId, isAdmin } = userStore.user;
@ -280,17 +302,17 @@ export default inject(
isArchiveFolder: isArchiveFolderRoot,
isPublicRoom,
additionalLinks: additionalLinks,
isArchiveFolder: isArchiveFolderRoot,
setLinkParams,
setEditLinkPanelIsVisible,
primaryLink,
getPrimaryLink: filesStore.getPrimaryLink,
setExternalLink,
withPublicRoomBlock,
fetchMembers,
membersIsLoading,
searchValue,
searchResultIsLoading,
};
}
},
)(
withTranslation([
"InfoPanel",
@ -300,5 +322,5 @@ export default inject(
"PeopleTranslations",
"Settings",
"CreateEditRoomDialog",
])(observer(Members))
])(observer(Members)),
);

View File

@ -0,0 +1,32 @@
import { useTranslation } from "react-i18next";
import styled, { useTheme } from "styled-components";
import { EmptyScreenContainer } from "@docspace/shared/components/empty-screen-container";
import EmptyScreenPersonSvgUrl from "PUBLIC_DIR/images/empty_screen_persons.svg?url";
import EmptyScreenPersonSvgDarkUrl from "PUBLIC_DIR/images/empty_screen_persons_dark.svg?url";
const StyledEmptyScreen = styled(EmptyScreenContainer)`
box-sizing: border-box;
width: 100%;
padding: 45px 3px 0;
`;
const EmptyContainer = () => {
const { t } = useTranslation("People");
const theme = useTheme();
const imageSrc = theme.isBase
? EmptyScreenPersonSvgUrl
: EmptyScreenPersonSvgDarkUrl;
return (
<StyledEmptyScreen
imageSrc={imageSrc}
imageAlt="Empty screen image"
headerText={t("NotFoundUsers")}
descriptionText={t("NotFoundUsersDescription")}
/>
);
};
export default EmptyContainer;

View File

@ -91,7 +91,12 @@ class FilesStore {
filter = FilesFilter.getDefault();
roomsFilter = RoomsFilter.getDefault();
membersFilter = { page: 0, pageCount: 100, total: 0, startIndex: 0 };
membersFilter = {
page: 0,
pageCount: 100,
total: 0,
startIndex: 0,
};
categoryType = getCategoryType(window.location);
@ -2534,7 +2539,12 @@ class FilesStore {
}
getDefaultMembersFilter = () => {
return { page: 0, pageCount: 100, total: 0, startIndex: 0 };
return {
page: 0,
pageCount: 100,
total: 0,
startIndex: 0,
};
};
setRoomMembersFilter = (roomMembersFilter) => {
@ -2557,6 +2567,7 @@ class FilesStore {
startIndex: newFilter.startIndex,
count: newFilter.pageCount,
filterType: 0, // 0 (Members)
filterValue: this.infoPanelStore.searchValue,
};
return api.rooms.getRoomMembers(id, membersFilters).then((res) => {

View File

@ -62,9 +62,13 @@ class InfoPanelStore {
infoPanelSelection = null;
infoPanelRoom = null;
membersIsLoading = false;
searchResultIsLoading = false;
shareChanged = false;
showSearchBlock = false;
searchValue = "";
constructor(userStore) {
this.userStore = userStore;
@ -81,6 +85,22 @@ class InfoPanelStore {
setIsMobileHidden = (bool) => (this.isMobileHidden = bool);
setShowSearchBlock = (bool) => (this.showSearchBlock = bool);
setSearchResultIsLoading = (isLoading) => {
this.searchResultIsLoading = isLoading;
};
setSearchValue = (value) => {
this.setSearchResultIsLoading(true);
this.searchValue = value;
};
resetSearch = () => {
this.setShowSearchBlock(false);
this.setSearchValue("");
};
setSelectionHistory = (obj) => (this.selectionHistory = obj);
setSelectionHistory = (obj) => {
@ -184,13 +204,14 @@ class InfoPanelStore {
newInfoPanelSelection = this.normalizeSelection(selectedFolder);
} else if (selectedItems.length === 1) {
newInfoPanelSelection = this.normalizeSelection(
this.getViewItem() ?? newInfoPanelSelection
this.getViewItem() ?? newInfoPanelSelection,
);
} else {
newInfoPanelSelection = [...Array(selectedItems.length).keys()];
}
this.setInfoPanelSelection(newInfoPanelSelection);
this.resetSearch();
};
normalizeSelection = (infoPanelSelection) => {
@ -238,7 +259,7 @@ class InfoPanelStore {
const newInfoPanelSelection = await getRoomInfo(currentFolderRoomId);
const roomIndex = this.selectedFolderStore.navigationPath.findIndex(
(f) => f.id === currentFolderRoomId
(f) => f.id === currentFolderRoomId,
);
if (roomIndex > -1) {
this.selectedFolderStore.navigationPath[roomIndex].title =
@ -268,7 +289,7 @@ class InfoPanelStore {
null,
null,
item.roomType,
true
true,
)
? item.logo?.medium
: item.icon
@ -278,7 +299,7 @@ class InfoPanelStore {
null,
null,
null,
item.roomType
item.roomType,
)
: item.isFolder && item.folderType
? this.filesSettingsStore.getIconByFolderType(item.folderType, size)
@ -330,7 +351,7 @@ class InfoPanelStore {
false,
fetchedUser.isOwner,
fetchedUser.statusType,
fetchedUser.status
fetchedUser.status,
);
return fetchedUser;
@ -420,10 +441,10 @@ class InfoPanelStore {
: false;
};
addMembersTitle = (t, administrators, users, expectedMembers) => {
addMembersTitle = (t, administrators, users, expectedMembers, groups) => {
let hasPrevAdminsTitle = this.getHasPrevTitle(
administrators,
"administration"
"administration",
);
if (administrators.length && !hasPrevAdminsTitle) {
@ -434,6 +455,16 @@ class InfoPanelStore {
});
}
let hasPrevGroupsTitle = this.getHasPrevTitle(groups, "groups");
if (groups.length && !hasPrevGroupsTitle) {
groups.unshift({
id: "groups",
displayName: t("Common:Groups"),
isTitle: true,
});
}
let hasPrevUsersTitle = this.getHasPrevTitle(users, "user");
if (users.length && !hasPrevUsersTitle) {
@ -442,7 +473,7 @@ class InfoPanelStore {
let hasPrevExpectedTitle = this.getHasPrevTitle(
expectedMembers,
"expected"
"expected",
);
if (expectedMembers.length && !hasPrevExpectedTitle) {
@ -455,10 +486,11 @@ class InfoPanelStore {
}
};
convertMembers = (t, members, clearFilter) => {
convertMembers = (t, members, clearFilter, withoutTitles) => {
const users = [];
const administrators = [];
const expectedMembers = [];
const groups = [];
members?.map((fetchedMember) => {
const member = {
@ -475,19 +507,25 @@ class InfoPanelStore {
member.access === ShareAccessRights.RoomManager
) {
administrators.push(member);
} else if (member.isGroup) {
groups.push(member);
} else {
users.push(member);
}
});
if (clearFilter) {
this.addMembersTitle(t, administrators, users, expectedMembers);
if (clearFilter && !withoutTitles) {
this.addMembersTitle(t, administrators, users, expectedMembers, groups);
}
return { administrators, users, expectedMembers };
return { administrators, users, expectedMembers, groups };
};
fetchMembers = async (t, clearFilter = true) => {
fetchMembers = async (
t,
clearFilter = true,
withoutTitlesAndLinks = false,
) => {
if (this.membersIsLoading) return;
const isPublic =
this.infoPanelSelection?.roomType ?? this.infoPanelSelection?.roomType;
@ -495,7 +533,12 @@ class InfoPanelStore {
const requests = [this.filesStore.getRoomMembers(roomId, clearFilter)];
if (isPublic && clearFilter && this.withPublicRoomBlock) {
if (
isPublic &&
clearFilter &&
this.withPublicRoomBlock &&
!withoutTitlesAndLinks
) {
requests.push(this.filesStore.getRoomLinks(roomId));
}
@ -506,19 +549,18 @@ class InfoPanelStore {
const [data, links] = await Promise.all(requests);
clearFilter && this.setMembersIsLoading(false);
clearTimeout(timerId);
this.setSearchResultIsLoading(false);
links && this.publicRoomStore.setExternalLinks(links);
const { administrators, users, expectedMembers } = this.convertMembers(
t,
data,
clearFilter
);
const { administrators, users, expectedMembers, groups } =
this.convertMembers(t, data, clearFilter, withoutTitlesAndLinks);
return {
users,
administrators,
expected: expectedMembers,
groups,
roomId,
};
};
@ -527,13 +569,15 @@ class InfoPanelStore {
const newMembers = this.convertMembers(t, members, clearFilter);
if (this.infoPanelMembers) {
const { roomId, administrators, users, expected } = this.infoPanelMembers;
const { roomId, administrators, users, expected, groups } =
this.infoPanelMembers;
this.setInfoPanelMembers({
roomId: roomId,
administrators: [...administrators, ...newMembers.administrators],
users: [...users, ...newMembers.users],
expected: [...expected, ...newMembers.expectedMembers],
groups: [...groups, ...newMembers.groups],
});
}
};
@ -562,7 +606,7 @@ class InfoPanelStore {
access,
primary,
internal,
expirationDate
expirationDate,
) => {
const { getFileInfo } = this.filesStore;
@ -573,7 +617,7 @@ class InfoPanelStore {
access,
primary,
internal,
expDate
expDate,
);
await getFileInfo(fileId);
return res;

View File

@ -64,6 +64,12 @@ export function getRoomMembers(id, filter) {
};
return request(options).then((res) => {
res.items.forEach((item) => {
if (item.sharedTo.manager) {
item.sharedTo.isGroup = true;
}
});
return res;
});
}
@ -339,6 +345,12 @@ export const setRoomSecurity = async (id, data) => {
const res = await request(options);
res.members.forEach((item) => {
if (item.sharedTo.manager) {
item.sharedTo.isGroup = true;
}
});
return res;
};