Merge branch 'release/v2.6.0' of https://github.com/ONLYOFFICE/DocSpace-client into release/v2.6.0
This commit is contained in:
commit
4d059d3067
@ -0,0 +1,38 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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 styled from "styled-components";
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
|
||||
export const StyledModalDialog = styled(ModalDialog)`
|
||||
.modal-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
margin: 16px 16px 12px;
|
||||
}
|
||||
`;
|
@ -24,23 +24,32 @@
|
||||
// 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 { inject, observer } from "mobx-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
ModalDialog,
|
||||
ModalDialogType,
|
||||
} from "@docspace/shared/components/modal-dialog";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { useState, useEffect, useTransition } from "react";
|
||||
import { getGroupMembersInRoom } from "@docspace/shared/api/groups";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { InputSize } from "@docspace/shared/components/text-input";
|
||||
import { SearchInput } from "@docspace/shared/components/search-input";
|
||||
import GroupMember from "./GroupMember";
|
||||
import {
|
||||
TGroup,
|
||||
TGroupMemberInvitedInRoom,
|
||||
} from "@docspace/shared/api/groups/types";
|
||||
|
||||
import EmptyContainer from "./EmptyContainer";
|
||||
import GroupMembersList from "./sub-components/GroupMembersList/GroupMembersList";
|
||||
import { StyledModalDialog } from "./EditGroupMembersDialog.styled";
|
||||
import { ModalBodyLoader } from "./sub-components/ModalBodyLoader/ModalBodyLoader";
|
||||
import { MIN_LOADER_TIMER } from "@docspace/shared/selectors/Files/FilesSelector.constants";
|
||||
|
||||
interface EditGroupMembersProps {
|
||||
visible: boolean;
|
||||
setVisible: (visible: boolean) => void;
|
||||
group: any;
|
||||
group: TGroup;
|
||||
infoPanelSelection: any;
|
||||
}
|
||||
|
||||
@ -53,33 +62,63 @@ const EditGroupMembers = ({
|
||||
const { t } = useTranslation(["Common"]);
|
||||
|
||||
const [searchValue, setSearchValue] = useState<string>("");
|
||||
const onChangeSearchValue = (newValue: string) => {
|
||||
setSearchValue(newValue);
|
||||
};
|
||||
const onClearSearch = () => onChangeSearchValue("");
|
||||
const [total, setTotal] = useState(0);
|
||||
const [groupMembers, setGroupMembers] = useState<
|
||||
TGroupMemberInvitedInRoom[] | null
|
||||
>(null);
|
||||
const [isSearchResultLoading, setIsSearchResultLoading] = useState(false);
|
||||
const [isNextPageLoading, setIsNextPageLoading] = useState(false);
|
||||
|
||||
const [groupMembers, setGroupMembers] = useState<any[] | null>(null);
|
||||
const filteredGroupMembers = groupMembers?.filter((groupMember) =>
|
||||
groupMember.user.displayName.includes(searchValue),
|
||||
);
|
||||
const [, startTransition] = useTransition();
|
||||
const onChangeSearchValue = (value: string) => {
|
||||
setIsSearchResultLoading(true);
|
||||
setSearchValue(value.trim());
|
||||
};
|
||||
|
||||
const onClearSearch = () => onChangeSearchValue("");
|
||||
|
||||
const onClose = () => setVisible(false);
|
||||
|
||||
const isSearchListEmpty =
|
||||
filteredGroupMembers && !filteredGroupMembers.length;
|
||||
const hasMembers = filteredGroupMembers && filteredGroupMembers.length !== 0;
|
||||
const loadNextPage = async (startIndex: number) => {
|
||||
const startLoadingTime = new Date();
|
||||
|
||||
try {
|
||||
setIsNextPageLoading(true);
|
||||
const filter = { startIndex, count: 100, filterValue: searchValue };
|
||||
|
||||
const data = await getGroupMembersInRoom(
|
||||
infoPanelSelection.id,
|
||||
group.id,
|
||||
filter,
|
||||
);
|
||||
|
||||
setTotal(data.total);
|
||||
if (startIndex === 0 || !groupMembers) {
|
||||
setGroupMembers(data.items);
|
||||
} else {
|
||||
setGroupMembers([...groupMembers, ...data.items]);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
const nowDate = new Date();
|
||||
const diff = Math.abs(nowDate.getTime() - startLoadingTime.getTime());
|
||||
|
||||
if (diff < MIN_LOADER_TIMER) {
|
||||
setTimeout(() => {
|
||||
setIsSearchResultLoading(false);
|
||||
}, MIN_LOADER_TIMER - diff);
|
||||
} else {
|
||||
setIsSearchResultLoading(false);
|
||||
}
|
||||
setIsNextPageLoading(false);
|
||||
// setIsSearchResultLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const fetchGroup = async () => {
|
||||
if (!group) return;
|
||||
|
||||
getGroupMembersInRoom(infoPanelSelection.id, group.id)!
|
||||
.then((data: any) => startTransition(() => setGroupMembers(data.items)))
|
||||
.catch((err: any) => console.error(err));
|
||||
};
|
||||
fetchGroup();
|
||||
}, [group, infoPanelSelection.id]);
|
||||
loadNextPage(0);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [searchValue]);
|
||||
|
||||
if (!infoPanelSelection?.isRoom) {
|
||||
onClose();
|
||||
@ -87,7 +126,7 @@ const EditGroupMembers = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<ModalDialog
|
||||
<StyledModalDialog
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
displayType={ModalDialogType.aside}
|
||||
@ -95,6 +134,10 @@ const EditGroupMembers = ({
|
||||
<ModalDialog.Header>{group.name}</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
{!groupMembers ? (
|
||||
<ModalBodyLoader withSearch />
|
||||
) : (
|
||||
<>
|
||||
<SearchInput
|
||||
className="search-input"
|
||||
placeholder={t("PeopleTranslations:SearchByGroupMembers")}
|
||||
@ -104,20 +147,27 @@ const EditGroupMembers = ({
|
||||
size={InputSize.base}
|
||||
/>
|
||||
|
||||
<div style={{ height: "12px", width: "100%" }} />
|
||||
|
||||
{isSearchListEmpty && <EmptyContainer />}
|
||||
|
||||
{hasMembers &&
|
||||
filteredGroupMembers.map(({ user, ...rest }) => (
|
||||
<GroupMember t={t} key={user.id} user={{ ...user, ...rest }} />
|
||||
))}
|
||||
{isSearchResultLoading ? (
|
||||
<ModalBodyLoader withSearch={false} />
|
||||
) : !groupMembers.length ? (
|
||||
<EmptyContainer />
|
||||
) : (
|
||||
<GroupMembersList
|
||||
members={groupMembers}
|
||||
loadNextPage={loadNextPage}
|
||||
hasNextPage={groupMembers.length < total}
|
||||
total={total}
|
||||
isNextPageLoading={isNextPageLoading}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
</StyledModalDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ infoPanelStore, userStore, dialogsStore }) => ({
|
||||
export default inject(({ infoPanelStore, userStore, dialogsStore }: any) => ({
|
||||
infoPanelSelection: infoPanelStore.infoPanelSelection,
|
||||
selfId: userStore.user.id,
|
||||
group: dialogsStore.editMembersGroup,
|
||||
|
@ -31,7 +31,7 @@ export const GroupMember = styled.div<{ isExpect: boolean }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
padding: 8px 16px;
|
||||
|
||||
.avatar {
|
||||
min-width: 32px;
|
@ -24,39 +24,47 @@
|
||||
// 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 { useState } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { isMobile, isMobileOnly } from "react-device-detect";
|
||||
|
||||
import AtReactSvgUrl from "PUBLIC_DIR/images/@.react.svg?url";
|
||||
// import { StyledUser } from "../../styles/members";
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import DefaultUserPhotoUrl from "PUBLIC_DIR/images/default_user_photo_size_82-82.png";
|
||||
import { isMobileOnly, isMobile } from "react-device-detect";
|
||||
import { decode } from "he";
|
||||
import { filterUserRoleOptions } from "SRC_DIR/helpers";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import * as Styled from "./index.styled";
|
||||
import { getUserRoleOptionsByUserAccess } from "@docspace/shared/utils/room-members/getUserRoleOptionsByUserAccess";
|
||||
import { getUserRoleOptionsByRoomType } from "@docspace/shared/utils/room-members/getUserRoleOptionsByRoomType";
|
||||
import { updateRoomMemberRole } from "@docspace/shared/api/rooms";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { useState } from "react";
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { getUserRoleOptions } from "@docspace/shared/utils/room-members/getUserRoleOptions";
|
||||
import { ShareAccessRights } from "@docspace/shared/enums";
|
||||
import { getUserRole, getUserTypeLabel } from "@docspace/shared/utils/common";
|
||||
import { getUserRole } from "@docspace/shared/utils/common";
|
||||
import { TGroupMemberInvitedInRoom } from "@docspace/shared/api/groups/types";
|
||||
|
||||
import * as Styled from "./index.styled";
|
||||
|
||||
interface GroupMemberProps {
|
||||
t: any;
|
||||
user: any;
|
||||
member: TGroupMemberInvitedInRoom;
|
||||
infoPanelSelection: any;
|
||||
}
|
||||
|
||||
const GroupMember = ({ t, user, infoPanelSelection }: GroupMemberProps) => {
|
||||
const GroupMember = ({ member, infoPanelSelection }: GroupMemberProps) => {
|
||||
const { user } = member;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const { t } = useTranslation("Common");
|
||||
|
||||
const userRole = user.isOwner
|
||||
? getUserRoleOptions(t).portalAdmin
|
||||
: getUserRoleOptionsByUserAccess(t, user.userAccess || user.groupAccess);
|
||||
: getUserRoleOptionsByUserAccess(
|
||||
t,
|
||||
member.userAccess || member.groupAccess,
|
||||
);
|
||||
|
||||
const fullRoomRoleOptions = getUserRoleOptionsByRoomType(
|
||||
t,
|
||||
@ -86,7 +94,7 @@ const GroupMember = ({ t, user, infoPanelSelection }: GroupMemberProps) => {
|
||||
else
|
||||
selectedUserRoleCBOption = getUserRoleOptionsByUserAccess(
|
||||
t,
|
||||
user.userAccess || user.groupAccess,
|
||||
member.userAccess || member.groupAccess,
|
||||
);
|
||||
|
||||
const availableUserRoleCBOptions = filterUserRoleOptions(
|
||||
@ -101,7 +109,7 @@ const GroupMember = ({ t, user, infoPanelSelection }: GroupMemberProps) => {
|
||||
notify: false,
|
||||
sharingMessage: "",
|
||||
})
|
||||
.then(() => (user.userAccess = userRoleOption.access))
|
||||
.then(() => (member.userAccess = userRoleOption.access))
|
||||
.catch((err) => toastr.error(err))
|
||||
.finally(() => setIsLoading(false));
|
||||
};
|
||||
@ -134,8 +142,8 @@ const GroupMember = ({ t, user, infoPanelSelection }: GroupMemberProps) => {
|
||||
</div>
|
||||
|
||||
<div className="individual-rights-tooltip">
|
||||
{user.userAccess &&
|
||||
user.userAccess !== user.groupAccess &&
|
||||
{member.userAccess &&
|
||||
member.userAccess !== member.groupAccess &&
|
||||
!user.isOwner && (
|
||||
<HelpButton
|
||||
place="left"
|
||||
@ -152,7 +160,7 @@ const GroupMember = ({ t, user, infoPanelSelection }: GroupMemberProps) => {
|
||||
|
||||
{userRole && userRoleOptions && (
|
||||
<div className="role-wrapper">
|
||||
{user.canEditAccess && !user.isOwner ? (
|
||||
{member.canEditAccess && !user.isOwner ? (
|
||||
<ComboBox
|
||||
className="role-combobox"
|
||||
selectedOption={userRole}
|
||||
@ -180,6 +188,6 @@ const GroupMember = ({ t, user, infoPanelSelection }: GroupMemberProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ infoPanelStore }) => ({
|
||||
export default inject(({ infoPanelStore }: any) => ({
|
||||
infoPanelSelection: infoPanelStore.infoPanelSelection,
|
||||
}))(observer(GroupMember));
|
@ -0,0 +1,126 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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, { memo, useCallback } from "react";
|
||||
import { useTheme } from "styled-components";
|
||||
import { areEqual, FixedSizeList as List } from "react-window";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import InfiniteLoader from "react-window-infinite-loader";
|
||||
|
||||
import { Scrollbar } from "@docspace/shared/components/scrollbar";
|
||||
import { RowLoader } from "@docspace/shared/skeletons/selector";
|
||||
import { TGroupMemberInvitedInRoom } from "@docspace/shared/api/groups/types";
|
||||
|
||||
import GroupMember from "../GroupMember";
|
||||
|
||||
const ROW_HEIGHT = 48;
|
||||
const SEARCH_WITH_PADDING_HEIGHT = 60;
|
||||
|
||||
const Row = memo(
|
||||
({
|
||||
data,
|
||||
index,
|
||||
style,
|
||||
}: {
|
||||
data: TGroupMemberInvitedInRoom[];
|
||||
index: number;
|
||||
style: React.CSSProperties;
|
||||
}) => {
|
||||
const member = data[index];
|
||||
|
||||
return (
|
||||
<div style={style}>
|
||||
{member ? (
|
||||
<GroupMember member={member} />
|
||||
) : (
|
||||
<RowLoader isMultiSelect={false} isContainer isUser />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
areEqual,
|
||||
);
|
||||
|
||||
Row.displayName = "Row";
|
||||
|
||||
interface GroupMembersListProps {
|
||||
members: TGroupMemberInvitedInRoom[];
|
||||
loadNextPage: (startIndex: number) => void;
|
||||
hasNextPage: boolean;
|
||||
total: number;
|
||||
isNextPageLoading: boolean;
|
||||
}
|
||||
|
||||
const GroupMembersList = ({
|
||||
members,
|
||||
loadNextPage,
|
||||
hasNextPage,
|
||||
total,
|
||||
isNextPageLoading,
|
||||
}: GroupMembersListProps) => {
|
||||
const { interfaceDirection } = useTheme();
|
||||
|
||||
const itemCount = hasNextPage ? members.length + 1 : members.length;
|
||||
|
||||
const isItemLoaded = useCallback(
|
||||
(index: number) => {
|
||||
return !hasNextPage || index < itemCount - 1;
|
||||
},
|
||||
[hasNextPage, itemCount],
|
||||
);
|
||||
|
||||
const loadMoreItems = isNextPageLoading ? () => {} : loadNextPage;
|
||||
|
||||
return (
|
||||
<AutoSizer>
|
||||
{({ height, width }) => (
|
||||
<InfiniteLoader
|
||||
isItemLoaded={isItemLoaded}
|
||||
itemCount={total}
|
||||
loadMoreItems={loadMoreItems}
|
||||
>
|
||||
{({ onItemsRendered, ref }) => (
|
||||
<List
|
||||
ref={ref}
|
||||
direction={interfaceDirection}
|
||||
height={height - SEARCH_WITH_PADDING_HEIGHT}
|
||||
width={width}
|
||||
itemCount={itemCount}
|
||||
itemSize={ROW_HEIGHT}
|
||||
itemData={members}
|
||||
outerElementType={Scrollbar}
|
||||
onItemsRendered={onItemsRendered}
|
||||
>
|
||||
{Row}
|
||||
</List>
|
||||
)}
|
||||
</InfiniteLoader>
|
||||
)}
|
||||
</AutoSizer>
|
||||
);
|
||||
};
|
||||
|
||||
export default GroupMembersList;
|
@ -0,0 +1,44 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// 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 { SearchLoader } from "@docspace/shared/skeletons/selector";
|
||||
import React from "react";
|
||||
import { MemberLoader } from "@docspace/shared/skeletons/info-panel/body/views/MembersLoader";
|
||||
|
||||
interface ModalBodyLoaderProps {
|
||||
withSearch: boolean;
|
||||
}
|
||||
|
||||
export const ModalBodyLoader = ({ withSearch }: ModalBodyLoaderProps) => {
|
||||
return (
|
||||
<div style={{ paddingTop: withSearch ? "16px" : "0" }}>
|
||||
{withSearch && <SearchLoader />}
|
||||
<div style={{ paddingInline: "16px" }}>
|
||||
<MemberLoader count={25} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -27,8 +27,12 @@
|
||||
import Filter from "./filter";
|
||||
|
||||
import { request } from "../client";
|
||||
import { checkFilterInstance } from "../../utils/common";
|
||||
import { TGroup } from "./types";
|
||||
import { checkFilterInstance, toUrlParams } from "../../utils/common";
|
||||
import {
|
||||
TGetGroupMembersInRoom,
|
||||
TGetGroupMembersInRoomFilter,
|
||||
TGroup,
|
||||
} from "./types";
|
||||
|
||||
// * Create
|
||||
|
||||
@ -104,11 +108,14 @@ export const getGroupsByUserId = (userId: string) => {
|
||||
export const getGroupMembersInRoom = (
|
||||
folderId: string | number,
|
||||
groupId: string,
|
||||
filter: TGetGroupMembersInRoomFilter,
|
||||
) => {
|
||||
const url = `/files/folder/${folderId}/group/${groupId}/share?${toUrlParams(filter, false)}`;
|
||||
|
||||
return request({
|
||||
method: "get",
|
||||
url: `/files/folder/${folderId}/group/${groupId}/share`,
|
||||
});
|
||||
url,
|
||||
}) as Promise<TGetGroupMembersInRoom>;
|
||||
};
|
||||
|
||||
// * Update
|
||||
|
@ -25,6 +25,7 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { TUser } from "../people/types";
|
||||
import { ShareAccessRights } from "../../enums";
|
||||
|
||||
export type TGroup = {
|
||||
category: string;
|
||||
@ -37,3 +38,23 @@ export type TGroup = {
|
||||
shared?: boolean;
|
||||
isLDAP: boolean;
|
||||
};
|
||||
|
||||
export type TGroupMemberInvitedInRoom = {
|
||||
user: TUser;
|
||||
canEditAccess: boolean;
|
||||
overridden: boolean;
|
||||
owner: boolean;
|
||||
groupAccess: number;
|
||||
userAccess: ShareAccessRights;
|
||||
};
|
||||
|
||||
export type TGetGroupMembersInRoom = {
|
||||
items: TGroupMemberInvitedInRoom[];
|
||||
total: number;
|
||||
};
|
||||
|
||||
export type TGetGroupMembersInRoomFilter = {
|
||||
startIndex?: number;
|
||||
count?: number;
|
||||
filterValue?: string;
|
||||
};
|
||||
|
@ -33,6 +33,30 @@ import {
|
||||
StyledMembersLoader,
|
||||
} from "../body.styled";
|
||||
|
||||
export const MemberLoader = ({ count = 1 }: { count?: number }) => {
|
||||
return (
|
||||
<>
|
||||
{[...Array(count).keys()].map((i) => (
|
||||
<StyledMemberLoader key={i}>
|
||||
<RectangleSkeleton
|
||||
className="avatar"
|
||||
width="32px"
|
||||
height="32px"
|
||||
borderRadius="50%"
|
||||
/>
|
||||
<RectangleSkeleton width="212px" height="16px" borderRadius="3px" />
|
||||
<RectangleSkeleton
|
||||
className="role-selector"
|
||||
width="64px"
|
||||
height="20px"
|
||||
borderRadius="3px"
|
||||
/>
|
||||
</StyledMemberLoader>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const MembersLoader = () => {
|
||||
return (
|
||||
<StyledMembersLoader>
|
||||
@ -41,46 +65,14 @@ const MembersLoader = () => {
|
||||
<RectangleSkeleton width="16px" height="16px" borderRadius="3px" />
|
||||
</StyledMemberSubtitleLoader>
|
||||
|
||||
{[...Array(4).keys()].map((i) => (
|
||||
<StyledMemberLoader key={i}>
|
||||
<RectangleSkeleton
|
||||
className="avatar"
|
||||
width="32px"
|
||||
height="32px"
|
||||
borderRadius="50%"
|
||||
/>
|
||||
<RectangleSkeleton width="212px" height="16px" borderRadius="3px" />
|
||||
<RectangleSkeleton
|
||||
className="role-selector"
|
||||
width="64px"
|
||||
height="20px"
|
||||
borderRadius="3px"
|
||||
/>
|
||||
</StyledMemberLoader>
|
||||
))}
|
||||
<MemberLoader count={4} />
|
||||
|
||||
<StyledMemberSubtitleLoader className="pending_users">
|
||||
<RectangleSkeleton width="111px" height="16px" borderRadius="3px" />
|
||||
<RectangleSkeleton width="16px" height="16px" borderRadius="3px" />
|
||||
</StyledMemberSubtitleLoader>
|
||||
|
||||
{[...Array(4).keys()].map((i) => (
|
||||
<StyledMemberLoader key={i}>
|
||||
<RectangleSkeleton
|
||||
className="avatar"
|
||||
width="32px"
|
||||
height="32px"
|
||||
borderRadius="50%"
|
||||
/>
|
||||
<RectangleSkeleton width="212px" height="16px" borderRadius="3px" />
|
||||
<RectangleSkeleton
|
||||
className="role-selector"
|
||||
width="64px"
|
||||
height="20px"
|
||||
borderRadius="3px"
|
||||
/>
|
||||
</StyledMemberLoader>
|
||||
))}
|
||||
<MemberLoader count={4} />
|
||||
</StyledMembersLoader>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user