diff --git a/packages/client/src/components/dialogs/EditGroupMembersDialog/EditGroupMembersDialog.styled.ts b/packages/client/src/components/dialogs/EditGroupMembersDialog/EditGroupMembersDialog.styled.ts new file mode 100644 index 0000000000..3849b9080b --- /dev/null +++ b/packages/client/src/components/dialogs/EditGroupMembersDialog/EditGroupMembersDialog.styled.ts @@ -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; + } +`; diff --git a/packages/client/src/components/dialogs/EditGroupMembersDialog/index.tsx b/packages/client/src/components/dialogs/EditGroupMembersDialog/index.tsx index e6b07383a0..a49c0581af 100644 --- a/packages/client/src/components/dialogs/EditGroupMembersDialog/index.tsx +++ b/packages/client/src/components/dialogs/EditGroupMembersDialog/index.tsx @@ -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(""); - 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(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 ( - {group.name} - + {!groupMembers ? ( + + ) : ( + <> + -
- - {isSearchListEmpty && } - - {hasMembers && - filteredGroupMembers.map(({ user, ...rest }) => ( - - ))} + {isSearchResultLoading ? ( + + ) : !groupMembers.length ? ( + + ) : ( + + )} + + )} - + ); }; -export default inject(({ infoPanelStore, userStore, dialogsStore }) => ({ +export default inject(({ infoPanelStore, userStore, dialogsStore }: any) => ({ infoPanelSelection: infoPanelStore.infoPanelSelection, selfId: userStore.user.id, group: dialogsStore.editMembersGroup, diff --git a/packages/client/src/components/dialogs/EditGroupMembersDialog/GroupMember/index.styled.ts b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMember/index.styled.ts similarity index 99% rename from packages/client/src/components/dialogs/EditGroupMembersDialog/GroupMember/index.styled.ts rename to packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMember/index.styled.ts index 674176a797..f3e0e01173 100644 --- a/packages/client/src/components/dialogs/EditGroupMembersDialog/GroupMember/index.styled.ts +++ b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMember/index.styled.ts @@ -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; diff --git a/packages/client/src/components/dialogs/EditGroupMembersDialog/GroupMember/index.tsx b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMember/index.tsx similarity index 87% rename from packages/client/src/components/dialogs/EditGroupMembersDialog/GroupMember/index.tsx rename to packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMember/index.tsx index f9f65f4379..081701f4ea 100644 --- a/packages/client/src/components/dialogs/EditGroupMembersDialog/GroupMember/index.tsx +++ b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMember/index.tsx @@ -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) => {
- {user.userAccess && - user.userAccess !== user.groupAccess && + {member.userAccess && + member.userAccess !== member.groupAccess && !user.isOwner && ( { {userRole && userRoleOptions && (
- {user.canEditAccess && !user.isOwner ? ( + {member.canEditAccess && !user.isOwner ? ( { ); }; -export default inject(({ infoPanelStore }) => ({ +export default inject(({ infoPanelStore }: any) => ({ infoPanelSelection: infoPanelStore.infoPanelSelection, }))(observer(GroupMember)); diff --git a/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMembersList/GroupMembersList.tsx b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMembersList/GroupMembersList.tsx new file mode 100644 index 0000000000..eb806612b9 --- /dev/null +++ b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/GroupMembersList/GroupMembersList.tsx @@ -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 ( +
+ {member ? ( + + ) : ( + + )} +
+ ); + }, + 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 ( + + {({ height, width }) => ( + + {({ onItemsRendered, ref }) => ( + + {Row} + + )} + + )} + + ); +}; + +export default GroupMembersList; diff --git a/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/ModalBodyLoader/ModalBodyLoader.tsx b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/ModalBodyLoader/ModalBodyLoader.tsx new file mode 100644 index 0000000000..f755606b67 --- /dev/null +++ b/packages/client/src/components/dialogs/EditGroupMembersDialog/sub-components/ModalBodyLoader/ModalBodyLoader.tsx @@ -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 ( +
+ {withSearch && } +
+ +
+
+ ); +}; diff --git a/packages/client/src/pages/PortalSettings/Layout/Section/Header/index.js b/packages/client/src/pages/PortalSettings/Layout/Section/Header/index.js index ae879f3771..46f0c4bd0c 100644 --- a/packages/client/src/pages/PortalSettings/Layout/Section/Header/index.js +++ b/packages/client/src/pages/PortalSettings/Layout/Section/Header/index.js @@ -74,8 +74,6 @@ const HeaderContainer = styled.div` white-space: nowrap; overflow: hidden; color: ${(props) => props.theme.client.settings.headerTitleColor}; - display: flex; - align-items: center; } } .action-wrapper { @@ -368,20 +366,24 @@ const SectionHeaderContent = (props) => { /> )} - {t(header, { - organizationName: t("Common:OrganizationName"), - })} - {isNeedPaidIcon ? ( - - ) : ( - "" - )} +
+
+ {t(header, { + organizationName: t("Common:OrganizationName"), + })} +
+ {isNeedPaidIcon ? ( + + ) : ( + "" + )} +
diff --git a/packages/client/src/pages/PortalSettings/categories/integration/LDAP/index.js b/packages/client/src/pages/PortalSettings/categories/integration/LDAP/index.js index f8fee436e8..475786e825 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/LDAP/index.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/LDAP/index.js @@ -75,10 +75,7 @@ const LDAP = ({ if (!isLoaded && isLdapAvailable) return ; return ( - + {t("LdapIntro")} (props.isSmallWindow ? "100%" : "700px")}; @@ -222,8 +221,6 @@ const StyledLdapPage = styled(Box)` margin-top: 24px; } } - - ${(props) => !props.isSettingPaid && UnavailableStyles} `; export default StyledLdapPage; diff --git a/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/HideButton.js b/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/HideButton.js index 76c433a5ae..0e4c1b6948 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/HideButton.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/HideButton.js @@ -33,22 +33,14 @@ import { Text } from "@docspace/shared/components/text"; const HideButton = (props) => { const { t } = useTranslation("SingleSignOn"); - const { - text, - label, - isAdditionalParameters, - value, - setIsSettingsShown, - isDisabled, - } = props; + const { text, label, isAdditionalParameters, value, setIsSettingsShown } = + props; const marginProp = isAdditionalParameters ? null : "24px 0"; const onClick = () => { setIsSettingsShown(!value); }; - const onClickProp = isDisabled ? {} : { onClick: onClick }; - return ( { {value diff --git a/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/SettingsContainer.js b/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/SettingsContainer.js index 27cc3e2c1a..7836063ae4 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/SettingsContainer.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/LDAP/sub-components/SettingsContainer.js @@ -83,11 +83,7 @@ const SettingsContainer = ({ const renderBody = () => ( <> {!isMobileView && ( - + )} {isMobileView && } diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/SubmitButton.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/SubmitButton.js index dd7f2fa63b..683fbfbbe0 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/SubmitButton.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/SubmitButton.js @@ -45,6 +45,7 @@ const SubmitResetButtons = (props) => { hasChanges, isLoadingXml, enableSso, + isSSOAvailable, } = props; return ( @@ -62,7 +63,9 @@ const SubmitResetButtons = (props) => { saveButtonDisabled={ !enableSso || hasErrors || !hasChanges || isLoadingXml } - cancelEnable={!(isSubmitLoading || isLoadingXml)} + disableRestoreToDefault={ + isSubmitLoading || isLoadingXml || !isSSOAvailable + } additionalClassSaveButton="save-button" additionalClassCancelButton="restore-button" /> @@ -71,7 +74,7 @@ const SubmitResetButtons = (props) => { ); }; -export default inject(({ ssoStore }) => { +export default inject(({ ssoStore, currentQuotaStore }) => { const { saveSsoSettings, isSsoEnabled, @@ -84,6 +87,7 @@ export default inject(({ ssoStore }) => { isLoadingXml, enableSso, } = ssoStore; + const { isSSOAvailable } = currentQuotaStore; return { saveSsoSettings, @@ -96,5 +100,6 @@ export default inject(({ ssoStore }) => { hasChanges, isLoadingXml, enableSso, + isSSOAvailable, }; })(observer(SubmitResetButtons)); diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js index 0258c3fafc..a1c76126e1 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/index.js @@ -69,7 +69,6 @@ const SingleSignOn = (props) => { {t("SsoIntro")} @@ -88,7 +87,7 @@ const SingleSignOn = (props) => { })} label={SERVICE_PROVIDER_SETTINGS} value={serviceProviderSettings} - isDisabled={!isSSOAvailable} + //isDisabled={!isSSOAvailable} /> @@ -101,7 +100,7 @@ const SingleSignOn = (props) => { })} label={SP_METADATA} value={spMetadata} - isDisabled={!isSSOAvailable} + //isDisabled={!isSSOAvailable} /> diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/styled-containers/StyledSsoPageContainer.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/styled-containers/StyledSsoPageContainer.js index ca26278a8a..f37c6e5d73 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/styled-containers/StyledSsoPageContainer.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/styled-containers/StyledSsoPageContainer.js @@ -25,7 +25,6 @@ // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode import styled, { css } from "styled-components"; -import { UnavailableStyles } from "../../../../utils/commonSettingsStyles"; const StyledSsoPage = styled.div` max-width: 100%; @@ -147,8 +146,6 @@ const StyledSsoPage = styled.div` `} } } - - ${(props) => !props.isSettingPaid && UnavailableStyles} `; export default StyledSsoPage; diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/HideButton.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/HideButton.js index 0b7f14380d..49f57524cf 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/HideButton.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/HideButton.js @@ -52,22 +52,13 @@ const StyledWrapper = styled.div` const HideButton = (props) => { const { t } = useTranslation("SingleSignOn"); - const { - text, - label, - isAdditionalParameters, - value, - setHideLabel, - isDisabled, - id, - } = props; + const { text, label, isAdditionalParameters, value, setHideLabel, id } = + props; const onClick = () => { setHideLabel(label); }; - const onClickProp = isDisabled ? {} : { onClick: onClick }; - return ( {!isAdditionalParameters && ( @@ -86,7 +77,7 @@ const HideButton = (props) => { id={id} className="hide-button settings_unavailable" isHovered - {...onClickProp} + onClick={onClick} type="action" > {value diff --git a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/ToggleSSO.js b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/ToggleSSO.js index 2ee3eff74c..3935eb8240 100644 --- a/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/ToggleSSO.js +++ b/packages/client/src/pages/PortalSettings/categories/integration/SingleSignOn/sub-components/ToggleSSO.js @@ -32,6 +32,7 @@ import { Text } from "@docspace/shared/components/text"; import { ToggleButton } from "@docspace/shared/components/toggle-button"; import { Badge } from "@docspace/shared/components/badge"; import { mobile } from "@docspace/shared/utils"; +import { UnavailableStyles } from "../../../../utils/commonSettingsStyles"; const StyledWrapper = styled.div` display: flex; @@ -69,6 +70,8 @@ const StyledWrapper = styled.div` } } } + + ${(props) => !props.isSSOAvailable && UnavailableStyles} `; const ToggleSSO = ({ enableSso, ssoToggle, isSSOAvailable }) => { @@ -76,7 +79,7 @@ const ToggleSSO = ({ enableSso, ssoToggle, isSSOAvailable }) => { const theme = useTheme(); return ( - + { const { openOnNewPage } = this.filesSettingsStore; - const foundIndex = this.files.findIndex((x) => x.id === id); - const file = foundIndex !== -1 ? this.files[foundIndex] : undefined; - if ( - file && - !preview && - file.rootFolderType !== FolderType.Archive && - file.fileExst !== ".oform" - ) { - const newStatus = file.fileStatus | FileStatus.IsEditing; - - this.updateSelectionStatus(id, newStatus, true); - this.updateFileStatus(foundIndex, newStatus); - } const share = shareKey ? shareKey : this.publicRoomStore.publicRoomKey; diff --git a/packages/shared/api/groups/index.ts b/packages/shared/api/groups/index.ts index d8e475c42a..e9f642f9cf 100644 --- a/packages/shared/api/groups/index.ts +++ b/packages/shared/api/groups/index.ts @@ -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; }; // * Update diff --git a/packages/shared/api/groups/types.ts b/packages/shared/api/groups/types.ts index 7b8a0b5e50..1669911d06 100644 --- a/packages/shared/api/groups/types.ts +++ b/packages/shared/api/groups/types.ts @@ -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; +}; diff --git a/packages/shared/components/table/TableHeader.tsx b/packages/shared/components/table/TableHeader.tsx index 799de41dfc..c49ab493be 100644 --- a/packages/shared/components/table/TableHeader.tsx +++ b/packages/shared/components/table/TableHeader.tsx @@ -616,7 +616,7 @@ class TableHeader extends React.Component< } } else { let overWidth = 0; - if (!hideColumns) { + if (!hideColumns && !hideColumnsConst) { // eslint-disable-next-line guard-for-in, no-restricted-syntax for (const index in tableContainer) { const item = tableContainer[index]; diff --git a/packages/shared/skeletons/info-panel/body/views/MembersLoader.tsx b/packages/shared/skeletons/info-panel/body/views/MembersLoader.tsx index a010a71c26..c23584ae5f 100644 --- a/packages/shared/skeletons/info-panel/body/views/MembersLoader.tsx +++ b/packages/shared/skeletons/info-panel/body/views/MembersLoader.tsx @@ -33,6 +33,30 @@ import { StyledMembersLoader, } from "../body.styled"; +export const MemberLoader = ({ count = 1 }: { count?: number }) => { + return ( + <> + {[...Array(count).keys()].map((i) => ( + + + + + + ))} + + ); +}; + const MembersLoader = () => { return ( @@ -41,46 +65,14 @@ const MembersLoader = () => { - {[...Array(4).keys()].map((i) => ( - - - - - - ))} + - {[...Array(4).keys()].map((i) => ( - - - - - - ))} + ); };