Merge branch 'release/v2.5.0' of github.com:ONLYOFFICE/DocSpace-client into release/v2.5.0
This commit is contained in:
commit
ceb24f07fe
@ -14,5 +14,9 @@
|
||||
"MoveToTrashTitle": "Move to Trash?",
|
||||
"UnsubscribeButton": "Unsubscribe",
|
||||
"UnsubscribeNote": "Are you sure you want to unsubscribe from the selected items from the list?",
|
||||
"UnsubscribeTitle": "Unsubscribe confirmation"
|
||||
"UnsubscribeTitle": "Unsubscribe confirmation",
|
||||
"DeleteGroupTitle": "Delete group",
|
||||
"DeleteAllGroupsTitle": "Delete groups",
|
||||
"DeleteGroupDescription": "Group {{groupName}} will be deleted. Users in the group will not be removed from DocSpace. Are you sure you want to continue?",
|
||||
"DeleteAllGroupDescription": "The selected groups will be deleted. Users in the groups will not be removed from DocSpace. Are you sure you want to continue?"
|
||||
}
|
||||
|
@ -122,6 +122,7 @@
|
||||
"EnterTime": "Enter time",
|
||||
"EnterTitle": "Enter title",
|
||||
"ErrorMessageBruteForceProtection": "Specified argument was out of the range of valid values.",
|
||||
"ErrorOccuredDownloadLog": "Errors occurred during data import. Download the log to check them.",
|
||||
"ErrorsWereFound": "{{errors}} errors were found",
|
||||
"ExistingAccount": "Existing account",
|
||||
"ForcePathStyle": "Force Path Style",
|
||||
@ -171,6 +172,7 @@
|
||||
"NewColorScheme": "New color scheme",
|
||||
"NextStep": "Next step",
|
||||
"NoEmail": "NO EMAIL",
|
||||
"NoUsersInBackup": "No users found. Try again or upload other backup files.",
|
||||
"NumberOfActiveEmployees": "Number of active employees: {{count}}",
|
||||
"NumberOfAttempts": "Number of attempts",
|
||||
"PasswordMinLenght": "Minimal password length",
|
||||
@ -304,4 +306,4 @@
|
||||
"WithoutEmailHint": "You don’t have users without emails. Please proceed to the next step.",
|
||||
"YouHaveUnsavedChanges": "You have unsaved changes",
|
||||
"YourCurrentDomain": "Your current domain"
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
"AccessRightsChangeOwnerConfirmText": "Изменения будут применены после подтверждения по электронной почте.",
|
||||
"AccessRightsProductUsersCan": "В модуле {{category}} участники портала со статусом Пользователи могут",
|
||||
"AccessRightsUsersFromList": "Участников со статусом {{users}} из списка",
|
||||
"AccountsWithoutEmails": "Мы нашли <1>{{users}} пользователей</1> без электронной почты. На следующем шаге вы можете добавить необходимые данные в их учетные записи.",
|
||||
"AccountsWithoutEmails": "Мы нашли <1>{{users}} пользователей</1> без электронной почты. Вы можете заполнить их электронные почты или продолжить без этого действия.",
|
||||
"AddAllowedIP": "Добавить разрешенный IP-адрес",
|
||||
"AddEmails": "Добавьте адреса электронной почты в незавершенные аккаунты",
|
||||
"AdditionalResources": "Дополнительные ресурсы",
|
||||
@ -279,4 +279,4 @@
|
||||
"WhiteLabelTooltip": "Размеры указаны для дисплеев Retina. Для дисплеев со стандартным разрешением ширина и высота логотипа будут соответственно изменены при загрузке.",
|
||||
"YouHaveUnsavedChanges": "Имеются несохраненные изменения",
|
||||
"YourCurrentDomain": "Ваш текущий домен"
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
|
||||
import Badges from "../components/Badges";
|
||||
import config from "PACKAGE_FILE";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { copyShareLink } from "@docspace/shared/utils/copy";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
|
||||
@ -119,7 +119,7 @@ export default function withBadges(WrappedComponent) {
|
||||
const { t, item, getPrimaryLink } = this.props;
|
||||
const primaryLink = await getPrimaryLink(item.id);
|
||||
if (primaryLink) {
|
||||
copy(primaryLink.sharedTo.shareLink);
|
||||
copyShareLink(primaryLink.sharedTo.shareLink);
|
||||
toastr.success(t("Common:LinkSuccessfullyCopied"));
|
||||
}
|
||||
};
|
||||
|
@ -27,8 +27,8 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { copyShareLink } from "@docspace/shared/utils/copy";
|
||||
import QuickButtons from "../components/QuickButtons";
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
export default function withQuickButtons(WrappedComponent) {
|
||||
class WithQuickButtons extends React.Component {
|
||||
@ -83,7 +83,7 @@ export default function withQuickButtons(WrappedComponent) {
|
||||
const { t, item, getPrimaryFileLink, setShareChanged } = this.props;
|
||||
const primaryLink = await getPrimaryFileLink(item.id);
|
||||
if (primaryLink) {
|
||||
copy(primaryLink.sharedTo.shareLink);
|
||||
copyShareLink(primaryLink.sharedTo.shareLink);
|
||||
item.shared
|
||||
? toastr.success(t("Common:LinkSuccessfullyCopied"))
|
||||
: toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
|
||||
@ -95,7 +95,7 @@ export default function withQuickButtons(WrappedComponent) {
|
||||
const { t, item, getPrimaryLink } = this.props;
|
||||
const primaryLink = await getPrimaryLink(item.id);
|
||||
if (primaryLink) {
|
||||
copy(primaryLink.sharedTo.shareLink);
|
||||
copyShareLink(primaryLink.sharedTo.shareLink);
|
||||
toastr.success(t("Common:LinkSuccessfullyCopied"));
|
||||
}
|
||||
};
|
||||
|
@ -402,10 +402,14 @@ const ArticleMainButtonContent = (props) => {
|
||||
action: EmployeeType.Guest,
|
||||
key: "user",
|
||||
},
|
||||
{
|
||||
isSeparator: true,
|
||||
key: "invite-users-separator",
|
||||
},
|
||||
...(!isMobileArticle
|
||||
? [
|
||||
{
|
||||
isSeparator: true,
|
||||
key: "invite-users-separator",
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
id: "invite_again",
|
||||
className: "main-button_drop-down",
|
||||
@ -541,6 +545,7 @@ const ArticleMainButtonContent = (props) => {
|
||||
onShowSelectFileDialog,
|
||||
onUploadFileClick,
|
||||
onUploadFolderClick,
|
||||
isMobileArticle,
|
||||
]);
|
||||
|
||||
const mainButtonText = t("Common:Actions");
|
||||
|
@ -38,6 +38,12 @@ const StyledBody = styled.div`
|
||||
max-height: 32px;
|
||||
}
|
||||
|
||||
.quota_checkbox {
|
||||
svg {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.quota_value {
|
||||
max-width: fit-content;
|
||||
padding: 0;
|
||||
|
@ -225,6 +225,7 @@ const QuotaForm = ({
|
||||
<Checkbox
|
||||
label={checkboxLabel}
|
||||
isChecked={isChecked}
|
||||
className="quota_checkbox"
|
||||
onChange={onChangeCheckbox}
|
||||
isDisabled={isLoading || isDisabled}
|
||||
/>
|
||||
|
@ -60,7 +60,7 @@ const PureConnectDialogContainer = (props) => {
|
||||
setIsConnectDialogReconnect,
|
||||
saveAfterReconnectOAuth,
|
||||
setSaveAfterReconnectOAuth,
|
||||
setSelectedThirdPartyAccount,
|
||||
setThirdPartyAccountsInfo,
|
||||
} = props;
|
||||
const { title, link, token, provider_id, provider_key, key } = item;
|
||||
|
||||
@ -169,9 +169,8 @@ const PureConnectDialogContainer = (props) => {
|
||||
provider_key,
|
||||
provider_id,
|
||||
)
|
||||
.then(() => {
|
||||
onClose();
|
||||
setSelectedThirdPartyAccount(null);
|
||||
.then(async () => {
|
||||
await setThirdPartyAccountsInfo();
|
||||
})
|
||||
.catch((err) => {
|
||||
toastr.error(err);
|
||||
@ -424,7 +423,7 @@ export default inject(
|
||||
const { id, folders } = selectedFolderStore;
|
||||
const {
|
||||
selectedThirdPartyAccount: backupConnectionItem,
|
||||
setSelectedThirdPartyAccount,
|
||||
setThirdPartyAccountsInfo,
|
||||
} = backup;
|
||||
const {
|
||||
connectDialogVisible: visible,
|
||||
@ -455,12 +454,12 @@ export default inject(
|
||||
openConnectWindow,
|
||||
fetchThirdPartyProviders,
|
||||
setConnectDialogVisible,
|
||||
setSelectedThirdPartyAccount,
|
||||
personal,
|
||||
isConnectDialogReconnect,
|
||||
saveAfterReconnectOAuth,
|
||||
setSaveAfterReconnectOAuth,
|
||||
setIsConnectDialogReconnect,
|
||||
setThirdPartyAccountsInfo,
|
||||
};
|
||||
},
|
||||
)(observer(ConnectDialog));
|
||||
|
@ -116,6 +116,9 @@ const CreateRoomDialog = ({
|
||||
setRoomParams((prev) => ({
|
||||
...prev,
|
||||
type: newRoomType,
|
||||
storageLocation: {
|
||||
isThirdparty: false,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,7 @@ const DialogHeader = ({ t, isEdit, isChooseRoomType, onArrowClick }) => {
|
||||
) : (
|
||||
<div className="header-with-button">
|
||||
<IconButton
|
||||
size="15px"
|
||||
size={17}
|
||||
iconName={ArrowPathReactSvgUrl}
|
||||
className="sharing_panel-arrow"
|
||||
onClick={onArrowClick}
|
||||
|
@ -52,22 +52,30 @@ const StyledDropdownMobile = styled.div`
|
||||
|
||||
StyledDropdownMobile.defaultProps = { theme: Base };
|
||||
|
||||
const DropdownMobile = ({ t, open, onClose, chooseRoomType }) => {
|
||||
const DropdownMobile = ({
|
||||
t,
|
||||
open,
|
||||
onClose,
|
||||
chooseRoomType,
|
||||
forсeHideDropdown,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Backdrop visible={open} onClick={onClose} zIndex={450} />
|
||||
<StyledDropdownMobile className="dropdown-mobile" isOpen={open}>
|
||||
{RoomsTypeValues.map((roomType) => (
|
||||
<RoomType
|
||||
id={roomType}
|
||||
t={t}
|
||||
key={roomType}
|
||||
roomType={roomType}
|
||||
type="dropdownItem"
|
||||
onClick={() => chooseRoomType(roomType)}
|
||||
/>
|
||||
))}
|
||||
</StyledDropdownMobile>
|
||||
{!forсeHideDropdown && (
|
||||
<StyledDropdownMobile className="dropdown-mobile" isOpen={open}>
|
||||
{RoomsTypeValues.map((roomType) => (
|
||||
<RoomType
|
||||
id={roomType}
|
||||
t={t}
|
||||
key={roomType}
|
||||
roomType={roomType}
|
||||
type="dropdownItem"
|
||||
onClick={() => chooseRoomType(roomType)}
|
||||
/>
|
||||
))}
|
||||
</StyledDropdownMobile>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -25,7 +25,7 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { isMobile } from "@docspace/shared/utils";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
import RoomType from "../RoomType";
|
||||
import DropdownDesktop from "./DropdownDesktop";
|
||||
@ -49,6 +49,7 @@ const RoomTypeDropdown = ({
|
||||
setRoomType,
|
||||
setIsScrollLocked,
|
||||
isDisabled,
|
||||
forсeHideDropdown,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
@ -68,6 +69,14 @@ const RoomTypeDropdown = ({
|
||||
setRoomType(roomType);
|
||||
toggleDropdown();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (forсeHideDropdown) {
|
||||
setIsScrollLocked(false);
|
||||
setIsOpen(false);
|
||||
}
|
||||
}, [forсeHideDropdown]);
|
||||
|
||||
return (
|
||||
<StyledRoomTypeDropdown isOpen={isOpen}>
|
||||
<RoomType
|
||||
@ -85,6 +94,7 @@ const RoomTypeDropdown = ({
|
||||
open={isOpen}
|
||||
onClose={toggleDropdown}
|
||||
chooseRoomType={chooseRoomType}
|
||||
forсeHideDropdown={forсeHideDropdown}
|
||||
/>
|
||||
) : (
|
||||
<DropdownDesktop t={t} open={isOpen} chooseRoomType={chooseRoomType} />
|
||||
|
@ -103,6 +103,9 @@ const SetRoomParams = ({
|
||||
useState(true);
|
||||
const [disableImageRescaling, setDisableImageRescaling] = useState(isEdit);
|
||||
|
||||
const [forceHideRoomTypeDropdown, setForceHideRoomTypeDropdown] =
|
||||
useState(false);
|
||||
|
||||
const isFormRoom = roomParams.type === RoomsType.FormRoom;
|
||||
const isPublicRoom = roomParams.type === RoomsType.PublicRoom;
|
||||
|
||||
@ -155,6 +158,7 @@ const SetRoomParams = ({
|
||||
setRoomType={setRoomType}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
isDisabled={isDisabled}
|
||||
forсeHideDropdown={forceHideRoomTypeDropdown}
|
||||
/>
|
||||
)}
|
||||
{isEdit && (
|
||||
@ -176,6 +180,8 @@ const SetRoomParams = ({
|
||||
isDisabled={isDisabled}
|
||||
isValidTitle={isValidTitle}
|
||||
isWrongTitle={isWrongTitle}
|
||||
onFocus={() => setForceHideRoomTypeDropdown(true)}
|
||||
onBlur={() => setForceHideRoomTypeDropdown(false)}
|
||||
errorMessage={
|
||||
isWrongTitle
|
||||
? t("Files:ContainsSpecCharacter")
|
||||
@ -184,11 +190,14 @@ const SetRoomParams = ({
|
||||
onKeyUp={onKeyUp}
|
||||
isAutoFocussed={true}
|
||||
/>
|
||||
|
||||
<TagInput
|
||||
t={t}
|
||||
tagHandler={tagHandler}
|
||||
setIsScrollLocked={setIsScrollLocked}
|
||||
isDisabled={isDisabled}
|
||||
onFocus={() => setForceHideRoomTypeDropdown(true)}
|
||||
onBlur={() => setForceHideRoomTypeDropdown(false)}
|
||||
/>
|
||||
|
||||
{/* //TODO: Uncomment when private rooms are done
|
||||
|
@ -52,7 +52,14 @@ const StyledTagInput = styled.div`
|
||||
${({ hasTags }) => !hasTags && "margin-bottom: -8px"}
|
||||
`;
|
||||
|
||||
const TagInput = ({ t, tagHandler, setIsScrollLocked, isDisabled }) => {
|
||||
const TagInput = ({
|
||||
t,
|
||||
tagHandler,
|
||||
setIsScrollLocked,
|
||||
isDisabled,
|
||||
onFocus,
|
||||
onBlur,
|
||||
}) => {
|
||||
const inputRef = useRef();
|
||||
const [tagInput, setTagInput] = useState("");
|
||||
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
||||
@ -69,13 +76,6 @@ const TagInput = ({ t, tagHandler, setIsScrollLocked, isDisabled }) => {
|
||||
setTagInput(text);
|
||||
};
|
||||
|
||||
const handleFocus = (event) => {
|
||||
const text = event.target.value;
|
||||
if (text.trim().length > 0) {
|
||||
openDropdown();
|
||||
}
|
||||
};
|
||||
|
||||
const openDropdown = () => {
|
||||
if (isDisabled) return;
|
||||
setIsScrollLocked(true);
|
||||
@ -87,6 +87,19 @@ const TagInput = ({ t, tagHandler, setIsScrollLocked, isDisabled }) => {
|
||||
setIsDropdownOpen(false);
|
||||
};
|
||||
|
||||
const handleFocus = (event) => {
|
||||
const text = event.target.value;
|
||||
if (text.trim().length > 0) {
|
||||
openDropdown();
|
||||
}
|
||||
onFocus();
|
||||
};
|
||||
|
||||
const handleBlur = () => {
|
||||
closeDropdown();
|
||||
onBlur();
|
||||
};
|
||||
|
||||
const handleKeyDown = (event) => {
|
||||
const keyCode = event.code;
|
||||
|
||||
@ -110,8 +123,8 @@ const TagInput = ({ t, tagHandler, setIsScrollLocked, isDisabled }) => {
|
||||
placeholder={t("TagsPlaceholder")}
|
||||
value={tagInput}
|
||||
onChange={onTagInputChange}
|
||||
onBlur={closeDropdown}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
isDisabled={isDisabled}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
|
@ -92,6 +92,7 @@ const StyledStorageLocation = styled.div`
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 6.35px;
|
||||
margin-top: -4px;
|
||||
svg {
|
||||
transform: ${(props) =>
|
||||
props.isOpen ? "rotate(180deg)" : "rotate(0)"};
|
||||
|
@ -0,0 +1,137 @@
|
||||
// (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 { useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
|
||||
const DeleteGroupDialog = (props) => {
|
||||
const {
|
||||
t,
|
||||
visible,
|
||||
onClose,
|
||||
selection,
|
||||
bufferSelection,
|
||||
groupName,
|
||||
onDeleteGroup,
|
||||
onDeleteAllGroups,
|
||||
isLoading,
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("keyup", onKeyUp, false);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("keyup", onKeyUp, false);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onKeyUp = (e) => {
|
||||
if (e.keyCode === 27) onClose();
|
||||
if (e.keyCode === 13 || e.which === 13) onDeleteAction();
|
||||
};
|
||||
|
||||
const hasMoreGroups = selection.length > 1;
|
||||
|
||||
const onDeleteAction = () => {
|
||||
try {
|
||||
if (hasMoreGroups) {
|
||||
onDeleteAllGroups(t);
|
||||
} else {
|
||||
onDeleteGroup(t, bufferSelection?.id || selection[0].id);
|
||||
}
|
||||
} catch (err) {
|
||||
toastr.error(err.message);
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialogContainer
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
displayType="modal"
|
||||
>
|
||||
<ModalDialog.Header>
|
||||
{hasMoreGroups
|
||||
? t("DeleteDialog:DeleteAllGroupsTitle")
|
||||
: t("DeleteDialog:DeleteGroupTitle")}
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text>
|
||||
{hasMoreGroups
|
||||
? t("DeleteDialog:DeleteAllGroupDescription")
|
||||
: t("DeleteDialog:DeleteGroupDescription", { groupName })}
|
||||
</Text>
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="group-modal_delete"
|
||||
key="Delete"
|
||||
label={t("Common:Delete")}
|
||||
size="normal"
|
||||
primary
|
||||
scale
|
||||
onClick={onDeleteAction}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
id="group-modal_cancel"
|
||||
key="CancelButton"
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
scale
|
||||
onClick={onClose}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ peopleStore }) => {
|
||||
const {
|
||||
selection,
|
||||
bufferSelection,
|
||||
groupName,
|
||||
onDeleteGroup,
|
||||
onDeleteAllGroups,
|
||||
isLoading,
|
||||
} = peopleStore.groupsStore;
|
||||
|
||||
return {
|
||||
selection,
|
||||
bufferSelection,
|
||||
groupName,
|
||||
onDeleteGroup,
|
||||
onDeleteAllGroups,
|
||||
isLoading,
|
||||
};
|
||||
})(withTranslation(["Common", "DeleteDialog"])(observer(DeleteGroupDialog)));
|
@ -50,6 +50,7 @@ const DeleteThirdPartyDialog = (props) => {
|
||||
setDeleteThirdPartyDialogVisible,
|
||||
isConnectionViaBackupModule,
|
||||
updateInfo,
|
||||
setConnectedThirdPartyAccount,
|
||||
} = props;
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -60,10 +61,13 @@ const DeleteThirdPartyDialog = (props) => {
|
||||
const onClose = () => setDeleteThirdPartyDialogVisible(false);
|
||||
|
||||
const onDeleteThirdParty = () => {
|
||||
setIsLoading(true);
|
||||
|
||||
if (isConnectionViaBackupModule) {
|
||||
deleteThirdParty(+removeItem.provider_id)
|
||||
.catch((err) => toastr.error(err))
|
||||
.finally(() => {
|
||||
setConnectedThirdPartyAccount(null);
|
||||
updateInfo && updateInfo();
|
||||
setIsLoading(false);
|
||||
onClose();
|
||||
@ -76,7 +80,6 @@ const DeleteThirdPartyDialog = (props) => {
|
||||
(x) => x.provider_id !== removeItem.id,
|
||||
);
|
||||
|
||||
setIsLoading(true);
|
||||
deleteThirdParty(+removeItem.id)
|
||||
.then(() => {
|
||||
setThirdPartyProviders(newProviders);
|
||||
@ -145,7 +148,10 @@ export default inject(
|
||||
const { providers, setThirdPartyProviders, deleteThirdParty } =
|
||||
filesSettingsStore.thirdPartyStore;
|
||||
const { setIsLoading } = filesStore;
|
||||
const { selectedThirdPartyAccount: backupConnectionItem } = backup;
|
||||
const {
|
||||
selectedThirdPartyAccount: backupConnectionItem,
|
||||
setConnectedThirdPartyAccount,
|
||||
} = backup;
|
||||
const {
|
||||
deleteThirdPartyDialogVisible: visible,
|
||||
setDeleteThirdPartyDialogVisible,
|
||||
@ -168,6 +174,7 @@ export default inject(
|
||||
setThirdPartyProviders,
|
||||
deleteThirdParty,
|
||||
setDeleteThirdPartyDialogVisible,
|
||||
setConnectedThirdPartyAccount,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -68,6 +68,7 @@ import DeletePluginDialog from "./DeletePluginDialog";
|
||||
import ShareFolderDialog from "./ShareFolderDialog";
|
||||
import EditGroupMembersDialog from "./EditGroupMembersDialog";
|
||||
import ChangeStorageQuotaDialog from "./ChangeStorageQuotaDialog";
|
||||
import DeleteGroupDialog from "./DeleteGroupDialog";
|
||||
|
||||
export {
|
||||
EmptyTrashDialog,
|
||||
@ -114,4 +115,5 @@ export {
|
||||
EditGroupMembersDialog,
|
||||
ChangeQuotaDialog,
|
||||
ChangeStorageQuotaDialog,
|
||||
DeleteGroupDialog,
|
||||
};
|
||||
|
@ -393,7 +393,13 @@ const AddUsersPanel = ({
|
||||
isGroup?: boolean,
|
||||
) => {
|
||||
return (
|
||||
<div style={{ width: "100%" }}>
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
marginInlineEnd: "16px",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
className="label"
|
||||
fontWeight={600}
|
||||
|
@ -315,6 +315,8 @@ const InvitePanel = ({
|
||||
addInfoPanelMembers(t, result.members);
|
||||
}
|
||||
|
||||
console.log(result);
|
||||
|
||||
onClose();
|
||||
toastr.success(t("Common:UsersInvited"));
|
||||
|
||||
|
@ -66,7 +66,8 @@ export const GroupsContent = styled.div<{}>`
|
||||
.email {
|
||||
max-width: 180px;
|
||||
color: #a3a9ae;
|
||||
font-size: ${({ theme }) => theme.getCorrectFontSize("10px")};
|
||||
font-size: ${({ theme }) => theme.getCorrectFontSize("12px")};
|
||||
line-height: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
overflow: hidden;
|
||||
|
@ -30,7 +30,7 @@ import { withTranslation } from "react-i18next";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import DefaultUserPhoto from "PUBLIC_DIR/images/default_user_photo_size_82-82.png";
|
||||
import { ContextMenuButton } from "@docspace/shared/components/context-menu-button";
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
import { Avatar, AvatarSize } from "@docspace/shared/components/avatar";
|
||||
import { Badge } from "@docspace/shared/components/badge";
|
||||
import Badges from "@docspace/client/src/pages/Home/Section/AccountsBody/Badges";
|
||||
import { StyledAccountsItemTitle } from "../../styles/accounts";
|
||||
@ -79,7 +79,7 @@ const AccountsItemTitle = ({
|
||||
<Avatar
|
||||
className="avatar"
|
||||
role={infoPanelSelection.role ? infoPanelSelection.role : "user"}
|
||||
size={"big"}
|
||||
size={AvatarSize.max}
|
||||
source={userAvatar}
|
||||
/>
|
||||
<div className="info-panel__info-text">
|
||||
|
@ -30,7 +30,7 @@ import { withTranslation } from "react-i18next";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import DefaultUserPhoto from "PUBLIC_DIR/images/default_user_photo_size_82-82.png";
|
||||
import { ContextMenuButton } from "@docspace/shared/components/context-menu-button";
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
import { Avatar, AvatarSize } from "@docspace/shared/components/avatar";
|
||||
import { StyledAccountsItemTitle } from "../../styles/accounts";
|
||||
|
||||
import { decode } from "he";
|
||||
@ -56,7 +56,7 @@ const GroupsItemTitle = ({
|
||||
<StyledAccountsItemTitle ref={itemTitleRef}>
|
||||
<Avatar
|
||||
className="avatar"
|
||||
size={"big"}
|
||||
size={AvatarSize.max}
|
||||
userName={infoPanelSelection.name}
|
||||
isGroup={true}
|
||||
/>
|
||||
|
@ -43,11 +43,12 @@ import { Text } from "@docspace/shared/components/text";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { Tooltip } from "@docspace/shared/components/tooltip";
|
||||
import { isDesktop } from "@docspace/shared/utils";
|
||||
import LinksToViewingIconUrl from "PUBLIC_DIR/images/links-to-viewing.react.svg?url";
|
||||
import PlusReactSvgUrl from "PUBLIC_DIR/images/actions.button.plus.react.svg?url";
|
||||
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { copyShareLink } from "@docspace/shared/utils/copy";
|
||||
import LinkRow from "./sub-components/LinkRow";
|
||||
|
||||
const Members = ({
|
||||
@ -140,7 +141,7 @@ const Members = ({
|
||||
} else {
|
||||
getPrimaryLink(infoPanelSelection.id).then((link) => {
|
||||
setExternalLink(link);
|
||||
copy(link.sharedTo.shareLink);
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
|
||||
});
|
||||
}
|
||||
@ -174,7 +175,7 @@ const Members = ({
|
||||
|
||||
{additionalLinks.length >= LINKS_LIMIT_COUNT && (
|
||||
<Tooltip
|
||||
float
|
||||
float={isDesktop()}
|
||||
id="emailTooltip"
|
||||
getContent={({ content }) => (
|
||||
<Text fontSize="12px">{content}</Text>
|
||||
|
@ -174,12 +174,13 @@ const LinkRow = (props) => {
|
||||
// onClick: onEmbeddingClick,
|
||||
// },
|
||||
|
||||
!disabled && {
|
||||
key: "copy-link-settings-key",
|
||||
label: t("Files:CopySharedLink"),
|
||||
icon: CopyToReactSvgUrl,
|
||||
onClick: onCopyExternalLink,
|
||||
},
|
||||
!disabled &&
|
||||
!isExpired && {
|
||||
key: "copy-link-settings-key",
|
||||
label: t("Files:CopySharedLink"),
|
||||
icon: CopyToReactSvgUrl,
|
||||
onClick: onCopyExternalLink,
|
||||
},
|
||||
|
||||
// disabled
|
||||
// ? {
|
||||
@ -245,7 +246,7 @@ const LinkRow = (props) => {
|
||||
{disabled && <Text color={textColor}>{t("Settings:Disabled")}</Text>}
|
||||
|
||||
<div className="external-row-icons">
|
||||
{!disabled && !isArchiveFolder && (
|
||||
{!disabled && !isExpired && !isArchiveFolder && (
|
||||
<>
|
||||
{isLocked && (
|
||||
<IconButton
|
||||
|
@ -100,6 +100,9 @@ const StyledLinkRow = styled.div`
|
||||
.avatar_role-wrapper {
|
||||
${({ isExpired, theme }) => css`
|
||||
svg {
|
||||
border: ${(props) => `1px solid ${props.theme.backgroundColor}`};
|
||||
border-radius: 50%;
|
||||
|
||||
path {
|
||||
fill: ${isExpired
|
||||
? theme.infoPanel.links.iconErrorColor
|
||||
|
@ -41,6 +41,7 @@ import {
|
||||
ChangeNameDialog,
|
||||
ResetApplicationDialog,
|
||||
DataReassignmentDialog,
|
||||
DeleteGroupDialog,
|
||||
} from "SRC_DIR/components/dialogs";
|
||||
|
||||
const Dialogs = ({
|
||||
@ -66,6 +67,7 @@ const Dialogs = ({
|
||||
profile,
|
||||
|
||||
dataReassignmentDialogVisible,
|
||||
deleteGroupDialogVisible,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
@ -146,6 +148,13 @@ const Dialogs = ({
|
||||
user={data}
|
||||
/>
|
||||
)}
|
||||
|
||||
{deleteGroupDialogVisible && (
|
||||
<DeleteGroupDialog
|
||||
visible={deleteGroupDialogVisible}
|
||||
onClose={closeDialogs}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -166,6 +175,7 @@ export default inject(({ peopleStore, userStore }) => {
|
||||
sendInviteDialogVisible,
|
||||
resetAuthDialogVisible,
|
||||
dataReassignmentDialogVisible,
|
||||
deleteGroupDialogVisible,
|
||||
} = peopleStore.dialogStore;
|
||||
|
||||
const { user: profile } = userStore;
|
||||
@ -202,5 +212,6 @@ export default inject(({ peopleStore, userStore }) => {
|
||||
profile,
|
||||
|
||||
dataReassignmentDialogVisible,
|
||||
deleteGroupDialogVisible,
|
||||
};
|
||||
})(observer(Dialogs));
|
||||
|
@ -30,6 +30,7 @@ import { withTranslation } from "react-i18next";
|
||||
|
||||
import { TableHeader } from "@docspace/shared/components/table";
|
||||
import { Events } from "@docspace/shared/enums";
|
||||
import { SortByFieldName } from "SRC_DIR/helpers/constants";
|
||||
|
||||
const TABLE_VERSION = "6";
|
||||
const TABLE_COLUMNS = `insideGroupTableColumns_ver-${TABLE_VERSION}`;
|
||||
@ -87,6 +88,19 @@ class InsideGroupTableHeader extends React.Component {
|
||||
},
|
||||
];
|
||||
|
||||
props.showStorageInfo &&
|
||||
defaultColumns.push({
|
||||
key: "Storage",
|
||||
title: props.isDefaultUsersQuotaSet
|
||||
? t("Common:StorageAndQuota")
|
||||
: t("Common:Storage"),
|
||||
enable: props.storageAccountsColumnIsEnabled,
|
||||
sortBy: SortByFieldName.UsedSpace,
|
||||
resizable: true,
|
||||
onChange: this.onColumnChange,
|
||||
onClick: this.onFilter,
|
||||
});
|
||||
|
||||
const columns = props.getColumns(defaultColumns);
|
||||
|
||||
this.state = { columns };
|
||||
@ -188,6 +202,7 @@ export default inject(
|
||||
settingsStore,
|
||||
userStore,
|
||||
tableStore,
|
||||
currentQuotaStore,
|
||||
}) => {
|
||||
const { groupsStore } = peopleStore;
|
||||
|
||||
@ -203,8 +218,11 @@ export default inject(
|
||||
typeAccountsInsideGroupColumnIsEnabled,
|
||||
groupAccountsInsideGroupColumnIsEnabled,
|
||||
emailAccountsInsideGroupColumnIsEnabled,
|
||||
storageAccountsColumnIsEnabled,
|
||||
} = tableStore;
|
||||
|
||||
const { showStorageInfo, isDefaultUsersQuotaSet } = currentQuotaStore;
|
||||
|
||||
return {
|
||||
filter,
|
||||
setFilter,
|
||||
@ -219,6 +237,9 @@ export default inject(
|
||||
typeAccountsInsideGroupColumnIsEnabled,
|
||||
groupAccountsInsideGroupColumnIsEnabled,
|
||||
emailAccountsInsideGroupColumnIsEnabled,
|
||||
storageAccountsColumnIsEnabled,
|
||||
showStorageInfo,
|
||||
isDefaultUsersQuotaSet,
|
||||
};
|
||||
},
|
||||
)(
|
||||
|
@ -25,6 +25,7 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { TableRow } from "@docspace/shared/components/table";
|
||||
@ -38,6 +39,8 @@ import Badges from "../../Badges";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import SpaceQuota from "SRC_DIR/components/SpaceQuota";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
display: contents;
|
||||
`;
|
||||
@ -119,6 +122,7 @@ const StyledPeopleRow = styled(TableRow)`
|
||||
opacity: ${(props) => (props.hideColumns ? 0 : 1)};
|
||||
|
||||
& > div {
|
||||
width: auto;
|
||||
max-width: fit-content;
|
||||
}
|
||||
}
|
||||
@ -220,6 +224,8 @@ const InsideGroupTableRow = (props) => {
|
||||
typeAccountsInsideGroupColumnIsEnabled,
|
||||
groupAccountsInsideGroupColumnIsEnabled,
|
||||
emailAccountsInsideGroupColumnIsEnabled,
|
||||
showStorageInfo,
|
||||
storageAccountsColumnIsEnabled,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
@ -373,7 +379,7 @@ const InsideGroupTableRow = (props) => {
|
||||
plusBadgeValue={groups.length - 1}
|
||||
onSelect={onOpenGroup}
|
||||
options={groupItems}
|
||||
scaled
|
||||
scaled={false}
|
||||
directionY="both"
|
||||
size="content"
|
||||
modernView
|
||||
@ -413,7 +419,7 @@ const InsideGroupTableRow = (props) => {
|
||||
}
|
||||
options={typesOptions}
|
||||
onSelect={onTypeChange}
|
||||
scaled
|
||||
scaled={false}
|
||||
directionY="both"
|
||||
size="content"
|
||||
displaySelectedOption
|
||||
@ -461,6 +467,7 @@ const InsideGroupTableRow = (props) => {
|
||||
e.target.closest(".checkbox") ||
|
||||
e.target.closest(".table-container_row-checkbox") ||
|
||||
e.target.closest(".type-combobox") ||
|
||||
e.target.closest(".groups-combobox") ||
|
||||
e.target.closest(".paid-badge") ||
|
||||
e.target.closest(".pending-badge") ||
|
||||
e.target.closest(".disabled-badge") ||
|
||||
@ -533,10 +540,7 @@ const InsideGroupTableRow = (props) => {
|
||||
)}
|
||||
|
||||
{groupAccountsInsideGroupColumnIsEnabled ? (
|
||||
<TableCell
|
||||
className={"table-cell_groups"}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<TableCell className={"table-cell_groups"}>
|
||||
{renderGroupsCell()}
|
||||
</TableCell>
|
||||
) : (
|
||||
@ -602,11 +606,32 @@ const InsideGroupTableRow = (props) => {
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
|
||||
{showStorageInfo &&
|
||||
(storageAccountsColumnIsEnabled ? (
|
||||
<TableCell className={"table-cell_Storage/Quota"}>
|
||||
<SpaceQuota hideColumns={hideColumns} item={item} type="user" />
|
||||
</TableCell>
|
||||
) : (
|
||||
<div />
|
||||
))}
|
||||
</StyledPeopleRow>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation(["People", "Common", "Settings"])(
|
||||
withContent(InsideGroupTableRow),
|
||||
export default inject(({ currentQuotaStore, tableStore }) => {
|
||||
const { showStorageInfo } = currentQuotaStore;
|
||||
const { storageAccountsColumnIsEnabled } = tableStore;
|
||||
|
||||
return {
|
||||
showStorageInfo,
|
||||
storageAccountsColumnIsEnabled,
|
||||
};
|
||||
})(
|
||||
withContent(
|
||||
withTranslation(["People", "Common", "Settings"])(
|
||||
observer(InsideGroupTableRow),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -127,6 +127,7 @@ const StyledPeopleRow = styled(TableRow)`
|
||||
opacity: ${(props) => (props.hideColumns ? 0 : 1)};
|
||||
|
||||
& > div {
|
||||
width: auto;
|
||||
max-width: fit-content;
|
||||
}
|
||||
}
|
||||
@ -382,7 +383,7 @@ const PeopleTableRow = (props) => {
|
||||
plusBadgeValue={groups.length - 1}
|
||||
onSelect={onOpenGroup}
|
||||
options={groupItems}
|
||||
scaled
|
||||
scaled={false}
|
||||
directionY="both"
|
||||
size="content"
|
||||
modernView
|
||||
@ -421,7 +422,7 @@ const PeopleTableRow = (props) => {
|
||||
}
|
||||
options={typesOptions}
|
||||
onSelect={onTypeChange}
|
||||
scaled
|
||||
scaled={false}
|
||||
directionY="both"
|
||||
size="content"
|
||||
displaySelectedOption
|
||||
@ -469,6 +470,7 @@ const PeopleTableRow = (props) => {
|
||||
e.target.closest(".checkbox") ||
|
||||
e.target.closest(".table-container_row-checkbox") ||
|
||||
e.target.closest(".type-combobox") ||
|
||||
e.target.closest(".groups-combobox") ||
|
||||
e.target.closest(".paid-badge") ||
|
||||
e.target.closest(".pending-badge") ||
|
||||
e.target.closest(".disabled-badge") ||
|
||||
@ -541,10 +543,7 @@ const PeopleTableRow = (props) => {
|
||||
)}
|
||||
|
||||
{groupAccountsColumnIsEnabled ? (
|
||||
<TableCell
|
||||
className={"table-cell_groups"}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<TableCell className={"table-cell_groups"}>
|
||||
{renderGroupsCell()}
|
||||
</TableCell>
|
||||
) : (
|
||||
|
@ -179,7 +179,7 @@ const StyledTableRow = styled(TableRow)`
|
||||
|
||||
.table-container_element-wrapper,
|
||||
.table-container_row-loader {
|
||||
min-width: ${(props) => (props.isRoom ? "40px" : "36px")};
|
||||
min-width: 40px;
|
||||
border-bottom: unset;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
@ -194,7 +194,7 @@ const StyledTableRow = styled(TableRow)`
|
||||
}
|
||||
|
||||
.table-container_element-container {
|
||||
width: 32px;
|
||||
width: 36px;
|
||||
height: 32px;
|
||||
|
||||
display: flex;
|
||||
@ -207,10 +207,10 @@ const StyledTableRow = styled(TableRow)`
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 4px;
|
||||
margin-right: 8px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 4px;
|
||||
margin-left: 8px;
|
||||
`}
|
||||
}
|
||||
}
|
||||
|
@ -225,8 +225,6 @@ const Table = ({
|
||||
isTrashFolder,
|
||||
]);
|
||||
|
||||
console.log("Table log TableContainer columnStorageName", columnStorageName);
|
||||
|
||||
return (
|
||||
<StyledTableContainer useReactWindow={!withPaging} forwardedRef={ref}>
|
||||
<TableHeader
|
||||
|
@ -563,8 +563,6 @@ class FilesTableHeader extends React.Component {
|
||||
const sortBy = isRooms ? roomsFilter.sortBy : filter.sortBy;
|
||||
const sortOrder = isRooms ? roomsFilter.sortOrder : filter.sortOrder;
|
||||
|
||||
console.log("Table log TableHeader columnStorageName", columnStorageName);
|
||||
|
||||
return (
|
||||
<TableHeader
|
||||
isLengthenHeader={firstElemChecked || isHeaderChecked}
|
||||
|
@ -86,13 +86,14 @@ import {
|
||||
FolderType,
|
||||
ShareAccessRights,
|
||||
} from "@docspace/shared/enums";
|
||||
import { getLogoFromPath } from "@docspace/shared/utils";
|
||||
import { copyShareLink } from "@docspace/shared/utils/copy";
|
||||
|
||||
import { CategoryType } from "SRC_DIR/helpers/constants";
|
||||
import {
|
||||
getCategoryTypeByFolderType,
|
||||
getCategoryUrl,
|
||||
} from "SRC_DIR/helpers/utils";
|
||||
import { getLogoFromPath } from "@docspace/shared/utils";
|
||||
import TariffBar from "SRC_DIR/components/TariffBar";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -182,6 +183,17 @@ const StyledContainer = styled.div`
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.title-icon {
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.backgroundColor};
|
||||
}
|
||||
rect {
|
||||
stroke: ${(props) => props.theme.backgroundColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@ -816,12 +828,12 @@ const SectionHeaderContent = (props) => {
|
||||
icon: CopyToReactSvgUrl,
|
||||
onClick: async () => {
|
||||
if (primaryLink) {
|
||||
copy(primaryLink.sharedTo.shareLink);
|
||||
copyShareLink(primaryLink.sharedTo.shareLink);
|
||||
toastr.success(t("Translations:LinkCopySuccess"));
|
||||
} else {
|
||||
const link = await getPrimaryLink(currentFolderId);
|
||||
if (link) {
|
||||
copy(link.sharedTo.shareLink);
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
|
||||
setExternalLink(link);
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ const DNSSettings = (props) => {
|
||||
isError && setIsError(false);
|
||||
setErrorText("");
|
||||
|
||||
const { value } = e.target;
|
||||
const value = e.target.value.trim();
|
||||
|
||||
const isValidDomain = parseDomain(value || "", setErrorText, t);
|
||||
|
||||
@ -202,7 +202,7 @@ const DNSSettings = (props) => {
|
||||
<TextInput
|
||||
{...textInputProps}
|
||||
isDisabled={isLoading || !enable}
|
||||
value={dnsName?.trim()}
|
||||
value={dnsName}
|
||||
onChange={onChangeTextInput}
|
||||
hasError={isError}
|
||||
/>
|
||||
|
@ -36,7 +36,7 @@ import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
margin: 0 0 16px;
|
||||
margin: 16px 0 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -47,7 +47,7 @@ const Wrapper = styled.div`
|
||||
|
||||
const InfoText = styled(Text)`
|
||||
margin-top: -8px;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 12px;
|
||||
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
|
||||
`;
|
||||
@ -55,7 +55,7 @@ const InfoText = styled(Text)`
|
||||
const ErrorText = styled(Text)`
|
||||
font-size: 12px;
|
||||
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 8px;
|
||||
`;
|
||||
|
||||
const ImportCompleteStep = ({
|
||||
@ -70,9 +70,12 @@ const ImportCompleteStep = ({
|
||||
const [importResult, setImportResult] = useState({
|
||||
succeedUsers: 0,
|
||||
failedUsers: 0,
|
||||
errors: [],
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
const onDownloadLog = async () => {
|
||||
try {
|
||||
await getMigrationLog()
|
||||
@ -101,7 +104,11 @@ const ImportCompleteStep = ({
|
||||
}
|
||||
clearCheckedAccounts();
|
||||
clearMigration();
|
||||
setTimeout(() => navigate(-1), 1000);
|
||||
setIsSaving(true);
|
||||
setTimeout(() => {
|
||||
setIsSaving(false);
|
||||
navigate(-1);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -110,6 +117,7 @@ const ImportCompleteStep = ({
|
||||
setImportResult({
|
||||
succeedUsers: res.parseResult.successedUsers,
|
||||
failedUsers: res.parseResult.failedUsers,
|
||||
errors: res.parseResult.errors,
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
@ -134,6 +142,10 @@ const ImportCompleteStep = ({
|
||||
</ErrorText>
|
||||
)}
|
||||
|
||||
{importResult.errors.length > 0 && (
|
||||
<ErrorText>{t("Settings:ErrorOccuredDownloadLog")}</ErrorText>
|
||||
)}
|
||||
|
||||
<Wrapper>
|
||||
<Checkbox
|
||||
label={t("Settings:SendWelcomeLetter")}
|
||||
@ -158,6 +170,7 @@ const ImportCompleteStep = ({
|
||||
cancelButtonLabel={t("Settings:DownloadLog")}
|
||||
displaySettings
|
||||
showReminder
|
||||
isSaving={isSaving}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
@ -111,6 +111,7 @@ const SelectFileStep = ({
|
||||
const [showErrorText, setShowErrorText] = useState(false);
|
||||
const [isFileError, setIsFileError] = useState(false);
|
||||
const [fileName, setFileName] = useState(null);
|
||||
const [isBackupEmpty, setIsBackupEmpty] = useState(false);
|
||||
const [searchParams] = useSearchParams();
|
||||
const isAbort = useRef(false);
|
||||
const uploadInterval = useRef(null);
|
||||
@ -140,7 +141,7 @@ const SelectFileStep = ({
|
||||
setIsFileError(false);
|
||||
setShowReminder(true);
|
||||
|
||||
if (res.parseResult.files.length > 0) {
|
||||
if (res.parseResult.files?.length > 0) {
|
||||
setFileName(res.parseResult.files.join(", "));
|
||||
}
|
||||
|
||||
@ -150,9 +151,16 @@ const SelectFileStep = ({
|
||||
setFileName(null);
|
||||
clearInterval(uploadInterval.current);
|
||||
} else if (res.isCompleted || res.progress === 100) {
|
||||
setUsers(res.parseResult);
|
||||
setShowReminder(true);
|
||||
onNextStep && onNextStep();
|
||||
if (
|
||||
res.parseResult.users.length +
|
||||
res.parseResult.existUsers.length +
|
||||
res.parseResult.withoutEmailUsers.length >
|
||||
0
|
||||
) {
|
||||
setUsers(res.parseResult);
|
||||
setShowReminder(true);
|
||||
onNextStep && onNextStep();
|
||||
}
|
||||
clearInterval(uploadInterval.current);
|
||||
}
|
||||
} catch (error) {
|
||||
@ -216,8 +224,19 @@ const SelectFileStep = ({
|
||||
setIsFileLoading(false);
|
||||
setIsVisible(false);
|
||||
setProgress(100);
|
||||
setUsers(res.parseResult);
|
||||
setShowReminder(true);
|
||||
|
||||
if (
|
||||
res.parseResult.users.length +
|
||||
res.parseResult.existUsers.length +
|
||||
res.parseResult.withoutEmailUsers.length >
|
||||
0
|
||||
) {
|
||||
setUsers(res.parseResult);
|
||||
setShowReminder(true);
|
||||
} else {
|
||||
setIsBackupEmpty(true);
|
||||
cancelMigration();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
toastr.error(error || t("Common:SomethingWentWrong"));
|
||||
@ -339,6 +358,19 @@ const SelectFileStep = ({
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{isBackupEmpty && (
|
||||
<Box>
|
||||
<ProgressBar
|
||||
percent={100}
|
||||
className="complete-progress-bar"
|
||||
label={t("Common:LoadingIsComplete")}
|
||||
/>
|
||||
<Text className="error-text">
|
||||
{t("Settings:NoUsersInBackup")}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{isError ? (
|
||||
<SaveCancelButtons
|
||||
className="save-cancel-buttons"
|
||||
|
@ -47,18 +47,21 @@ const StyledRowContainer = styled(RowContainer)`
|
||||
|
||||
.table-group-menu {
|
||||
height: 61px;
|
||||
position: absolute;
|
||||
position: sticky;
|
||||
z-index: 201;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: -16px;
|
||||
margin-right: -16px;
|
||||
`
|
||||
: css`
|
||||
left: -16px;
|
||||
margin-left: -16px;
|
||||
`}
|
||||
width: 100%;
|
||||
margin-top: -35.5px;
|
||||
|
||||
margin-top: 20px;
|
||||
top: 61px;
|
||||
margin-bottom: -29.5px;
|
||||
|
||||
.table-container_group-menu {
|
||||
padding: 0px 16px;
|
||||
|
@ -48,12 +48,14 @@ const StyledTableContainer = styled(TableContainer)`
|
||||
|
||||
.table-group-menu {
|
||||
height: 69px;
|
||||
position: absolute;
|
||||
position: sticky;
|
||||
z-index: 201;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
width: calc(100% + 40px);
|
||||
margin-top: 20px;
|
||||
margin-left: -20px;
|
||||
top: 0;
|
||||
|
||||
margin-top: -35.5px;
|
||||
margin-bottom: -37.5px;
|
||||
|
||||
.table-container_group-menu {
|
||||
border-image-slice: 0;
|
||||
|
@ -31,28 +31,40 @@ import { Consumer } from "@docspace/shared/utils/context";
|
||||
import TableView from "./TableView";
|
||||
import RowView from "./RowView";
|
||||
|
||||
const checkedAccountType = "result";
|
||||
|
||||
const AccountsTable = ({
|
||||
t,
|
||||
viewAs,
|
||||
accountsData,
|
||||
changeGroupType,
|
||||
UserTypes,
|
||||
toggleAllAccounts,
|
||||
}) => {
|
||||
const typeOptions = [
|
||||
{
|
||||
key: UserTypes.DocSpaceAdmin,
|
||||
label: t("Common:DocSpaceAdmin"),
|
||||
onClick: () => changeGroupType(UserTypes.DocSpaceAdmin),
|
||||
onClick: () => {
|
||||
changeGroupType(UserTypes.DocSpaceAdmin);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: UserTypes.RoomAdmin,
|
||||
label: t("Common:RoomAdmin"),
|
||||
onClick: () => changeGroupType(UserTypes.RoomAdmin),
|
||||
onClick: () => {
|
||||
changeGroupType(UserTypes.RoomAdmin);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: UserTypes.User,
|
||||
label: t("Common:PowerUser"),
|
||||
onClick: () => changeGroupType(UserTypes.User),
|
||||
onClick: () => {
|
||||
changeGroupType(UserTypes.User);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@ -81,12 +93,13 @@ const AccountsTable = ({
|
||||
|
||||
export default inject(({ setup, importAccountsStore }) => {
|
||||
const { viewAs } = setup;
|
||||
const { changeGroupType, UserTypes } = importAccountsStore;
|
||||
const { changeGroupType, UserTypes, toggleAllAccounts } = importAccountsStore;
|
||||
|
||||
return {
|
||||
viewAs,
|
||||
changeGroupType,
|
||||
UserTypes,
|
||||
toggleAllAccounts,
|
||||
};
|
||||
})(
|
||||
withTranslation(["ChangeUserTypeDialog", "People"])(observer(AccountsTable)),
|
||||
|
@ -88,14 +88,16 @@ const SelectUsersTypeStep = ({
|
||||
displaySettings
|
||||
/>
|
||||
|
||||
<StyledSearchInput
|
||||
id="search-users-type-input"
|
||||
placeholder={t("Common:Search")}
|
||||
value={searchValue}
|
||||
onChange={onChangeInput}
|
||||
refreshTimeout={100}
|
||||
onClearSearch={onClearSearchInput}
|
||||
/>
|
||||
{!checkedUsers.result.length > 0 && (
|
||||
<StyledSearchInput
|
||||
id="search-users-type-input"
|
||||
placeholder={t("Common:Search")}
|
||||
value={searchValue}
|
||||
onChange={onChangeInput}
|
||||
refreshTimeout={100}
|
||||
onClearSearch={onClearSearchInput}
|
||||
/>
|
||||
)}
|
||||
|
||||
<AccountsTable t={t} accountsData={filteredAccounts} />
|
||||
|
||||
|
@ -43,7 +43,7 @@ const UsersRow = (props) => {
|
||||
const emailTextRef = useRef();
|
||||
|
||||
const [isPrevEmailValid, setIsPrevEmailValid] = useState(
|
||||
data.email.length > 0,
|
||||
data.email?.length > 0,
|
||||
);
|
||||
|
||||
const handleAccountToggle = (e) => {
|
||||
@ -68,7 +68,7 @@ const UsersRow = (props) => {
|
||||
id={data.key}
|
||||
sectionWidth={sectionWidth}
|
||||
displayName={data.displayName}
|
||||
email={data.email}
|
||||
email={data.email || ""}
|
||||
emailInputRef={emailInputRef}
|
||||
emailTextRef={emailTextRef}
|
||||
isChecked={isChecked}
|
||||
|
@ -171,6 +171,7 @@ const UsersRowContent = ({
|
||||
onValidateInput={onValidateEmail}
|
||||
hasError={hasError}
|
||||
onBlur={checkEmailValidity}
|
||||
isAutoFocussed
|
||||
/>
|
||||
|
||||
<DecisionButton icon={<CheckSvg />} onClick={handleSaveClick} />
|
||||
|
@ -187,6 +187,7 @@ const UsersTableRow = ({
|
||||
onKeyDown={handleKeyDown}
|
||||
hasError={hasError}
|
||||
onBlur={checkEmailValidity}
|
||||
isAutoFocussed
|
||||
/>
|
||||
|
||||
<DecisionButton icon={<CheckSvg />} onClick={handleSaveClick} />
|
||||
|
@ -42,6 +42,11 @@ const ErrorText = styled(Text)`
|
||||
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
|
||||
margin-bottom: 16px;
|
||||
`;
|
||||
const InfoText = styled(Text)`
|
||||
margin-bottom: 8px;
|
||||
font-size: 12px;
|
||||
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
|
||||
`;
|
||||
|
||||
const ImportCompleteStep = ({
|
||||
t,
|
||||
@ -55,9 +60,12 @@ const ImportCompleteStep = ({
|
||||
const [importResult, setImportResult] = useState({
|
||||
succeedUsers: 0,
|
||||
failedUsers: 0,
|
||||
errors: [],
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
const onDownloadLog = async () => {
|
||||
try {
|
||||
await getMigrationLog()
|
||||
@ -85,7 +93,11 @@ const ImportCompleteStep = ({
|
||||
}
|
||||
clearCheckedAccounts();
|
||||
clearMigration();
|
||||
setTimeout(() => navigate(-1), 1000);
|
||||
setIsSaving(true);
|
||||
setTimeout(() => {
|
||||
setIsSaving(false);
|
||||
navigate(-1);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -94,6 +106,7 @@ const ImportCompleteStep = ({
|
||||
setImportResult({
|
||||
succeedUsers: res.parseResult.successedUsers,
|
||||
failedUsers: res.parseResult.failedUsers,
|
||||
errors: res.parseResult.errors,
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
@ -103,18 +116,22 @@ const ImportCompleteStep = ({
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Text fontSize="12px">
|
||||
<InfoText>
|
||||
{t("Settings:ImportedUsers", {
|
||||
selectedUsers: importResult.succeedUsers,
|
||||
importedUsers: importResult.succeedUsers + importResult.failedUsers,
|
||||
})}
|
||||
</Text>
|
||||
</InfoText>
|
||||
|
||||
{importResult.failedUsers > 0 && (
|
||||
<ErrorText>
|
||||
{t("Settings:ErrorsWereFound", { errors: importResult.failedUsers })}
|
||||
</ErrorText>
|
||||
)}
|
||||
|
||||
{importResult.errors.length > 0 && (
|
||||
<ErrorText>{t("Settings:ErrorOccuredDownloadLog")}</ErrorText>
|
||||
)}
|
||||
|
||||
<div className="sendLetterBlockWrapper">
|
||||
<Checkbox
|
||||
@ -140,6 +157,7 @@ const ImportCompleteStep = ({
|
||||
cancelButtonLabel={t("Settings:DownloadLog")}
|
||||
displaySettings
|
||||
showReminder
|
||||
isSaving={isSaving}
|
||||
/>
|
||||
</Wrapper>
|
||||
);
|
||||
|
@ -114,7 +114,7 @@ const SelectFileStep = ({
|
||||
setIsFileLoading,
|
||||
cancelMigration,
|
||||
}) => {
|
||||
const [isSaveDisabled, setIsSaveDisabled] = useState(false);
|
||||
const [isSaveDisabled, setIsSaveDisabled] = useState(true);
|
||||
const [progress, setProgress] = useState(0);
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const [isError, setIsError] = useState(false);
|
||||
@ -147,15 +147,16 @@ const SelectFileStep = ({
|
||||
}
|
||||
|
||||
setIsFileError(false);
|
||||
setIsSaveDisabled(true);
|
||||
setIsSaveDisabled(false);
|
||||
|
||||
if (res.parseResult.files.length > 0) {
|
||||
if (res.parseResult.files?.length > 0) {
|
||||
setFileName(res.parseResult.files.join(", "));
|
||||
}
|
||||
|
||||
if (!res || res.parseResult.failedArchives.length > 0 || res.error) {
|
||||
toastr.error(res.error);
|
||||
setIsFileError(true);
|
||||
setIsSaveDisabled(false);
|
||||
clearInterval(uploadInterval.current);
|
||||
} else if (res.isCompleted || res.progress === 100) {
|
||||
setUsers(res.parseResult);
|
||||
|
@ -36,7 +36,6 @@ import AccountsPaging from "../../../sub-components/AccountsPaging";
|
||||
|
||||
// import UsersInfoBlock from "../../../sub-components/UsersInfoBlock";
|
||||
import { Wrapper } from "../StyledStepper";
|
||||
import { NoEmailUsersBlock } from "../../../sub-components/NoEmailUsersBlock";
|
||||
|
||||
// const LICENSE_LIMIT = 100;
|
||||
|
||||
@ -45,12 +44,10 @@ const SelectUsersStep = (props) => {
|
||||
t,
|
||||
incrementStep,
|
||||
decrementStep,
|
||||
users,
|
||||
withEmailUsers,
|
||||
searchValue,
|
||||
setSearchValue,
|
||||
cancelMigration,
|
||||
areCheckedUsersEmpty,
|
||||
} = props;
|
||||
|
||||
const [dataPortion, setDataPortion] = useState(withEmailUsers.slice(0, 25));
|
||||
@ -84,10 +81,6 @@ const SelectUsersStep = (props) => {
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
{withEmailUsers.length > 0 && (
|
||||
<NoEmailUsersBlock users={users.withoutEmail.length} t={t} />
|
||||
)}
|
||||
|
||||
{withEmailUsers.length > 0 ? (
|
||||
<>
|
||||
<SaveCancelButtons
|
||||
@ -98,7 +91,6 @@ const SelectUsersStep = (props) => {
|
||||
cancelButtonLabel={t("Common:Back")}
|
||||
showReminder
|
||||
displaySettings
|
||||
saveButtonDisabled={areCheckedUsersEmpty}
|
||||
/>
|
||||
|
||||
{/* <UsersInfoBlock
|
||||
@ -142,7 +134,6 @@ const SelectUsersStep = (props) => {
|
||||
cancelButtonLabel={t("Common:Back")}
|
||||
showReminder
|
||||
displaySettings
|
||||
saveButtonDisabled={areCheckedUsersEmpty}
|
||||
/>
|
||||
)}
|
||||
</Wrapper>
|
||||
@ -156,7 +147,6 @@ export default inject(({ importAccountsStore }) => {
|
||||
searchValue,
|
||||
setSearchValue,
|
||||
cancelMigration,
|
||||
areCheckedUsersEmpty,
|
||||
} = importAccountsStore;
|
||||
|
||||
return {
|
||||
@ -165,6 +155,5 @@ export default inject(({ importAccountsStore }) => {
|
||||
searchValue,
|
||||
setSearchValue,
|
||||
cancelMigration,
|
||||
areCheckedUsersEmpty,
|
||||
};
|
||||
})(observer(SelectUsersStep));
|
||||
|
@ -47,19 +47,21 @@ const StyledRowContainer = styled(RowContainer)`
|
||||
|
||||
.table-group-menu {
|
||||
height: 61px;
|
||||
position: absolute;
|
||||
position: sticky;
|
||||
z-index: 201;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: -16px;
|
||||
margin-right: -16px;
|
||||
`
|
||||
: css`
|
||||
left: -16px;
|
||||
margin-left: -16px;
|
||||
`}
|
||||
width: 100%;
|
||||
|
||||
margin-top: -35.5px;
|
||||
margin-top: 20px;
|
||||
top: 61px;
|
||||
margin-bottom: -29.5px;
|
||||
|
||||
.table-container_group-menu {
|
||||
padding: 0px 16px;
|
||||
|
@ -46,12 +46,14 @@ import ClearEmptyFilterSvgUrl from "PUBLIC_DIR/images/clear.empty.filter.svg?url
|
||||
const UserSelectTableContainer = styled(StyledTableContainer)`
|
||||
.table-group-menu {
|
||||
height: 69px;
|
||||
position: absolute;
|
||||
position: sticky;
|
||||
z-index: 201;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
width: calc(100% + 40px);
|
||||
margin-top: 20px;
|
||||
margin-left: -20px;
|
||||
top: 0;
|
||||
|
||||
margin-top: -35.5px;
|
||||
margin-bottom: -37.5px;
|
||||
|
||||
.table-container_group-menu {
|
||||
border-image-slice: 0;
|
||||
|
@ -31,12 +31,30 @@ import { Consumer } from "@docspace/shared/utils/context";
|
||||
import TableView from "./TableView";
|
||||
import RowView from "./RowView";
|
||||
|
||||
const AccountsTable = (props) => {
|
||||
const { t, viewAs, accountsData, changeGroupType, UserTypes } = props;
|
||||
const checkedAccountType = "result";
|
||||
|
||||
const setTypeDocspaceAdmin = () => changeGroupType(UserTypes.DocSpaceAdmin);
|
||||
const setTypeRoomAdmin = () => changeGroupType(UserTypes.RoomAdmin);
|
||||
const setTypeUser = () => changeGroupType(UserTypes.User);
|
||||
const AccountsTable = (props) => {
|
||||
const {
|
||||
t,
|
||||
viewAs,
|
||||
accountsData,
|
||||
changeGroupType,
|
||||
UserTypes,
|
||||
toggleAllAccounts,
|
||||
} = props;
|
||||
|
||||
const setTypeDocspaceAdmin = () => {
|
||||
changeGroupType(UserTypes.DocSpaceAdmin);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
};
|
||||
const setTypeRoomAdmin = () => {
|
||||
changeGroupType(UserTypes.RoomAdmin);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
};
|
||||
const setTypeUser = () => {
|
||||
changeGroupType(UserTypes.User);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
};
|
||||
|
||||
const typeOptions = [
|
||||
{
|
||||
@ -80,12 +98,13 @@ const AccountsTable = (props) => {
|
||||
};
|
||||
export default inject(({ setup, importAccountsStore }) => {
|
||||
const { viewAs } = setup;
|
||||
const { changeGroupType, UserTypes } = importAccountsStore;
|
||||
const { changeGroupType, UserTypes, toggleAllAccounts } = importAccountsStore;
|
||||
|
||||
return {
|
||||
viewAs,
|
||||
changeGroupType,
|
||||
UserTypes,
|
||||
toggleAllAccounts,
|
||||
};
|
||||
})(
|
||||
withTranslation(["ChangeUserTypeDialog", "People"])(observer(AccountsTable)),
|
||||
|
@ -85,15 +85,17 @@ const SelectUsersTypeStep = (props) => {
|
||||
displaySettings
|
||||
/>
|
||||
|
||||
<SearchInput
|
||||
id="search-checkedUsers-type-input"
|
||||
className="importUsersSearch"
|
||||
placeholder={t("Common:Search")}
|
||||
value={searchValue}
|
||||
onChange={onChangeInput}
|
||||
refreshTimeout={100}
|
||||
onClearSearch={onClearSearchInput}
|
||||
/>
|
||||
{!checkedUsers.result.length > 0 && (
|
||||
<SearchInput
|
||||
id="search-checkedUsers-type-input"
|
||||
className="importUsersSearch"
|
||||
placeholder={t("Common:Search")}
|
||||
value={searchValue}
|
||||
onChange={onChangeInput}
|
||||
refreshTimeout={100}
|
||||
onClearSearch={onClearSearchInput}
|
||||
/>
|
||||
)}
|
||||
|
||||
<AccountsTable t={t} accountsData={filteredAccounts} />
|
||||
|
||||
|
@ -36,7 +36,7 @@ import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
margin: 0 0 16px;
|
||||
margin: 16px 0 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@ -47,7 +47,7 @@ const Wrapper = styled.div`
|
||||
|
||||
const InfoText = styled(Text)`
|
||||
margin-top: -8px;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 12px;
|
||||
color: ${(props) => props.theme.client.settings.migration.subtitleColor};
|
||||
`;
|
||||
@ -55,7 +55,7 @@ const InfoText = styled(Text)`
|
||||
const ErrorText = styled(Text)`
|
||||
font-size: 12px;
|
||||
color: ${(props) => props.theme.client.settings.migration.errorTextColor};
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 8px;
|
||||
`;
|
||||
|
||||
const ImportCompleteStep = ({
|
||||
@ -70,9 +70,12 @@ const ImportCompleteStep = ({
|
||||
const [importResult, setImportResult] = useState({
|
||||
succeedUsers: 0,
|
||||
failedUsers: 0,
|
||||
errors: [],
|
||||
});
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
const onDownloadLog = async () => {
|
||||
try {
|
||||
await getMigrationLog()
|
||||
@ -101,7 +104,11 @@ const ImportCompleteStep = ({
|
||||
}
|
||||
clearMigration();
|
||||
clearCheckedAccounts();
|
||||
setTimeout(() => navigate(-1), 1000);
|
||||
setIsSaving(true);
|
||||
setTimeout(() => {
|
||||
setIsSaving(false);
|
||||
navigate(-1);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -110,6 +117,7 @@ const ImportCompleteStep = ({
|
||||
setImportResult({
|
||||
succeedUsers: res.parseResult.successedUsers,
|
||||
failedUsers: res.parseResult.failedUsers,
|
||||
errors: res.parseResult.errors,
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
@ -134,6 +142,10 @@ const ImportCompleteStep = ({
|
||||
</ErrorText>
|
||||
)}
|
||||
|
||||
{importResult.errors.length > 0 && (
|
||||
<ErrorText>{t("Settings:ErrorOccuredDownloadLog")}</ErrorText>
|
||||
)}
|
||||
|
||||
<Wrapper>
|
||||
<Checkbox
|
||||
label={t("Settings:SendWelcomeLetter")}
|
||||
@ -158,6 +170,7 @@ const ImportCompleteStep = ({
|
||||
cancelButtonLabel={t("Settings:DownloadLog")}
|
||||
displaySettings
|
||||
showReminder
|
||||
isSaving={isSaving}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
@ -139,7 +139,7 @@ const SelectFileStep = ({
|
||||
setIsFileError(false);
|
||||
setShowReminder(true);
|
||||
|
||||
if (res.parseResult.files.length > 0) {
|
||||
if (res.parseResult.files?.length > 0) {
|
||||
setFileName(res.parseResult.files.join(", "));
|
||||
}
|
||||
|
||||
|
@ -47,19 +47,21 @@ const StyledRowContainer = styled(RowContainer)`
|
||||
|
||||
.table-group-menu {
|
||||
height: 61px;
|
||||
position: absolute;
|
||||
position: sticky;
|
||||
z-index: 201;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: -16px;
|
||||
margin-right: -16px;
|
||||
`
|
||||
: css`
|
||||
left: -16px;
|
||||
margin-left: -16px;
|
||||
`}
|
||||
width: 100%;
|
||||
|
||||
margin-top: -35.5px;
|
||||
margin-top: 20px;
|
||||
top: 61px;
|
||||
margin-bottom: -29.5px;
|
||||
|
||||
.table-container_group-menu {
|
||||
padding: 0px 16px;
|
||||
|
@ -48,12 +48,14 @@ const StyledTableContainer = styled(TableContainer)`
|
||||
|
||||
.table-group-menu {
|
||||
height: 69px;
|
||||
position: absolute;
|
||||
position: sticky;
|
||||
z-index: 201;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
width: calc(100% + 40px);
|
||||
margin-top: 20px;
|
||||
margin-left: -20px;
|
||||
top: 0;
|
||||
|
||||
margin-top: -35.5px;
|
||||
margin-bottom: -37.5px;
|
||||
|
||||
.table-container_group-menu {
|
||||
border-image-slice: 0;
|
||||
|
@ -31,28 +31,40 @@ import { Consumer } from "@docspace/shared/utils/context";
|
||||
import TableView from "./TableView";
|
||||
import RowView from "./RowView";
|
||||
|
||||
const checkedAccountType = "result";
|
||||
|
||||
const AccountsTable = ({
|
||||
t,
|
||||
viewAs,
|
||||
accountsData,
|
||||
changeGroupType,
|
||||
UserTypes,
|
||||
toggleAllAccounts,
|
||||
}) => {
|
||||
const typeOptions = [
|
||||
{
|
||||
key: UserTypes.DocSpaceAdmin,
|
||||
label: t("Common:DocSpaceAdmin"),
|
||||
onClick: () => changeGroupType(UserTypes.DocSpaceAdmin),
|
||||
onClick: () => {
|
||||
changeGroupType(UserTypes.DocSpaceAdmin);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: UserTypes.RoomAdmin,
|
||||
label: t("Common:RoomAdmin"),
|
||||
onClick: () => changeGroupType(UserTypes.RoomAdmin),
|
||||
onClick: () => {
|
||||
changeGroupType(UserTypes.RoomAdmin);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: UserTypes.User,
|
||||
label: t("Common:PowerUser"),
|
||||
onClick: () => changeGroupType(UserTypes.User),
|
||||
onClick: () => {
|
||||
changeGroupType(UserTypes.User);
|
||||
toggleAllAccounts(false, [], checkedAccountType);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@ -80,12 +92,13 @@ const AccountsTable = ({
|
||||
};
|
||||
export default inject(({ setup, importAccountsStore }) => {
|
||||
const { viewAs } = setup;
|
||||
const { changeGroupType, UserTypes } = importAccountsStore;
|
||||
const { changeGroupType, UserTypes, toggleAllAccounts } = importAccountsStore;
|
||||
|
||||
return {
|
||||
viewAs,
|
||||
changeGroupType,
|
||||
UserTypes,
|
||||
toggleAllAccounts,
|
||||
};
|
||||
})(
|
||||
withTranslation(["ChangeUserTypeDialog", "People"])(observer(AccountsTable)),
|
||||
|
@ -81,16 +81,17 @@ const SelectUsersTypeStep = ({
|
||||
cancelButtonLabel={t("Common:Back")}
|
||||
displaySettings
|
||||
/>
|
||||
|
||||
<SearchInput
|
||||
id="search-users-type-input"
|
||||
placeholder={t("Common:Search")}
|
||||
style={{ marginTop: "20px" }}
|
||||
value={searchValue}
|
||||
onChange={onChangeInput}
|
||||
refreshTimeout={100}
|
||||
onClearSearch={onClearSearchInput}
|
||||
/>
|
||||
{!checkedUsers.result.length > 0 && (
|
||||
<SearchInput
|
||||
id="search-users-type-input"
|
||||
placeholder={t("Common:Search")}
|
||||
style={{ marginTop: "20px" }}
|
||||
value={searchValue}
|
||||
onChange={onChangeInput}
|
||||
refreshTimeout={100}
|
||||
onClearSearch={onClearSearchInput}
|
||||
/>
|
||||
)}
|
||||
|
||||
<AccountsTable t={t} accountsData={filteredAccounts} />
|
||||
|
||||
|
@ -86,10 +86,9 @@ const DataImport = ({
|
||||
|
||||
if (
|
||||
migrationStatus &&
|
||||
migrationStatus.parseResult.users.length +
|
||||
migrationStatus.parseResult.existUsers.length +
|
||||
migrationStatus.parseResult.withoutEmailUsers.length >
|
||||
0
|
||||
migrationStatus.parseResult?.failedArchives &&
|
||||
migrationStatus.parseResult.failedArchives.length === 0 &&
|
||||
!migrationStatus.error
|
||||
) {
|
||||
const workspacesEnum = {
|
||||
GoogleWorkspace: "google",
|
||||
|
@ -29,11 +29,7 @@ import RefreshReactSvgUrl from "PUBLIC_DIR/images/refresh.react.svg?url";
|
||||
import AccessNoneReactSvgUrl from "PUBLIC_DIR/images/access.none.react.svg?url";
|
||||
import React, { useEffect, useReducer } from "react";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import {
|
||||
getSettingsThirdParty,
|
||||
getThirdPartyCapabilities,
|
||||
saveSettingsThirdParty,
|
||||
} from "@docspace/shared/api/files";
|
||||
import { saveSettingsThirdParty } from "@docspace/shared/api/files";
|
||||
import { StyledBackup } from "../StyledBackup";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
@ -43,8 +39,6 @@ import DeleteThirdPartyDialog from "../../../../../../components/dialogs/DeleteT
|
||||
import { getOAuthToken } from "@docspace/shared/utils/common";
|
||||
import FilesSelectorInput from "SRC_DIR/components/FilesSelectorInput";
|
||||
import { useTranslation } from "react-i18next";
|
||||
let accounts = [],
|
||||
capabilities;
|
||||
|
||||
const initialState = {
|
||||
folderList: {},
|
||||
@ -68,130 +62,46 @@ const DirectThirdPartyConnection = (props) => {
|
||||
setSelectedThirdPartyAccount,
|
||||
connectedThirdPartyAccount,
|
||||
selectedThirdPartyAccount,
|
||||
setConnectedThirdPartyAccount,
|
||||
buttonSize,
|
||||
isTheSameThirdPartyAccount,
|
||||
onSelectFile,
|
||||
filterParam,
|
||||
descriptionText,
|
||||
isMobileScale,
|
||||
accounts,
|
||||
setThirdPartyAccountsInfo,
|
||||
} = props;
|
||||
|
||||
const { t } = useTranslation("Translations");
|
||||
|
||||
useEffect(() => {
|
||||
onSetInitialInfo();
|
||||
|
||||
return () => {
|
||||
setSelectedThirdPartyAccount(null);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onSetInitialInfo = async () => {
|
||||
try {
|
||||
const capabilities = await getThirdPartyCapabilities();
|
||||
onSetThirdPartySettings(connectedThirdPartyAccount, capabilities);
|
||||
} catch (e) {
|
||||
onSetThirdPartySettings();
|
||||
if (!e) return;
|
||||
toastr.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const [state, setState] = useReducer(
|
||||
(state, newState) => ({ ...state, ...newState }),
|
||||
initialState,
|
||||
);
|
||||
|
||||
const isDirectConnection = () => {
|
||||
return state.isUpdatingInfo;
|
||||
};
|
||||
const updateAccountsInfo = async () => {
|
||||
const { t } = useTranslation("Translations");
|
||||
|
||||
const onSetSettings = async () => {
|
||||
try {
|
||||
if (!isDirectConnection()) setState({ isUpdatingInfo: true });
|
||||
|
||||
onSelectFolder && onSelectFolder("");
|
||||
|
||||
let account;
|
||||
[account, capabilities] = await Promise.all([
|
||||
getSettingsThirdParty(),
|
||||
getThirdPartyCapabilities(),
|
||||
]);
|
||||
setConnectedThirdPartyAccount(account);
|
||||
onSetThirdPartySettings(account, capabilities);
|
||||
} catch (e) {
|
||||
onSetThirdPartySettings();
|
||||
|
||||
if (!e) return;
|
||||
toastr.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const onSetThirdPartySettings = async (connectedAccount, capabilities) => {
|
||||
try {
|
||||
accounts = [];
|
||||
let index = 0,
|
||||
selectedAccount = {};
|
||||
const setAccount = (providerKey, serviceTitle) => {
|
||||
const accountIndex =
|
||||
capabilities && capabilities.findIndex((x) => x[0] === providerKey);
|
||||
if (accountIndex === -1) return;
|
||||
const isConnected =
|
||||
connectedAccount?.providerKey === "WebDav"
|
||||
? serviceTitle === connectedAccount?.title
|
||||
: capabilities[accountIndex][0] === connectedAccount?.providerKey;
|
||||
accounts.push({
|
||||
key: index.toString(),
|
||||
label: serviceTitle,
|
||||
title: serviceTitle,
|
||||
provider_key: capabilities[accountIndex][0],
|
||||
...(capabilities[accountIndex][1] && {
|
||||
provider_link: capabilities[accountIndex][1],
|
||||
}),
|
||||
connected: isConnected,
|
||||
...(isConnected && {
|
||||
provider_id: connectedAccount?.providerId,
|
||||
id: connectedAccount.id,
|
||||
}),
|
||||
});
|
||||
if (isConnected) {
|
||||
selectedAccount = { ...accounts[index] };
|
||||
}
|
||||
index++;
|
||||
};
|
||||
setAccount("GoogleDrive", t("Translations:TypeTitleGoogle"));
|
||||
setAccount("Box", t("Translations:TypeTitleBoxNet"));
|
||||
setAccount("DropboxV2", t("Translations:TypeTitleDropBox"));
|
||||
setAccount("SharePoint", t("Translations:TypeTitleSharePoint"));
|
||||
setAccount("OneDrive", t("Translations:TypeTitleSkyDrive"));
|
||||
setAccount("WebDav", "Nextcloud");
|
||||
setAccount("WebDav", "ownCloud");
|
||||
setAccount("kDrive", t("Translations:TypeTitlekDrive"));
|
||||
setAccount("Yandex", t("Translations:TypeTitleYandex"));
|
||||
setAccount("WebDav", t("Translations:TypeTitleWebDav"));
|
||||
setSelectedThirdPartyAccount(
|
||||
Object.keys(selectedAccount).length !== 0
|
||||
? selectedAccount
|
||||
: { ...accounts[0] },
|
||||
);
|
||||
await setThirdPartyAccountsInfo();
|
||||
|
||||
setState({
|
||||
isLoading: false,
|
||||
isUpdatingInfo: false,
|
||||
isInitialLoading: false,
|
||||
folderList: connectedAccount ?? {},
|
||||
});
|
||||
} catch (e) {
|
||||
setState({
|
||||
isLoading: false,
|
||||
isInitialLoading: false,
|
||||
isUpdatingInfo: false,
|
||||
});
|
||||
if (!e) return;
|
||||
toastr.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
onSetSettings();
|
||||
|
||||
return () => {
|
||||
setSelectedThirdPartyAccount(null);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onConnect = () => {
|
||||
clearLocalStorage();
|
||||
onSelectFolder && onSelectFolder("");
|
||||
@ -245,11 +155,12 @@ const DirectThirdPartyConnection = (props) => {
|
||||
provider_id,
|
||||
);
|
||||
|
||||
updateAccountsInfo();
|
||||
await setThirdPartyAccountsInfo();
|
||||
} catch (e) {
|
||||
setState({ isLoading: false, isUpdatingInfo: false });
|
||||
toastr.error(e);
|
||||
}
|
||||
|
||||
setState({ isLoading: false, isUpdatingInfo: false });
|
||||
};
|
||||
|
||||
const onSelectAccount = (options) => {
|
||||
@ -280,13 +191,14 @@ const DirectThirdPartyConnection = (props) => {
|
||||
];
|
||||
};
|
||||
|
||||
const { isLoading, folderList, isInitialLoading } = state;
|
||||
const { isLoading, isInitialLoading } = state;
|
||||
|
||||
const isDisabledComponent =
|
||||
isDisabled || isInitialLoading || isLoading || accounts.length === 0;
|
||||
|
||||
const isDisabledSelector = isLoading || isDisabled;
|
||||
|
||||
const folderList = connectedThirdPartyAccount ?? {};
|
||||
return (
|
||||
<StyledBackup
|
||||
isConnectedAccount={
|
||||
@ -310,17 +222,19 @@ const DirectThirdPartyConnection = (props) => {
|
||||
isDisabled={isDisabledComponent}
|
||||
/>
|
||||
|
||||
{connectedThirdPartyAccount?.id && isTheSameThirdPartyAccount && (
|
||||
<ContextMenuButton
|
||||
zIndex={402}
|
||||
className="backup_third-party-context"
|
||||
iconName={VerticalDotsReactSvgUrl}
|
||||
size={15}
|
||||
getData={getContextOptions}
|
||||
isDisabled={isDisabledComponent}
|
||||
displayIconBorder
|
||||
/>
|
||||
)}
|
||||
{connectedThirdPartyAccount?.id &&
|
||||
selectedThirdPartyAccount &&
|
||||
isTheSameThirdPartyAccount && (
|
||||
<ContextMenuButton
|
||||
zIndex={402}
|
||||
className="backup_third-party-context"
|
||||
iconName={VerticalDotsReactSvgUrl}
|
||||
size={15}
|
||||
getData={getContextOptions}
|
||||
isDisabled={isDisabledComponent}
|
||||
displayIconBorder
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!connectedThirdPartyAccount?.id || !isTheSameThirdPartyAccount ? (
|
||||
@ -330,10 +244,11 @@ const DirectThirdPartyConnection = (props) => {
|
||||
label={t("Common:Connect")}
|
||||
onClick={onConnect}
|
||||
size={buttonSize}
|
||||
isDisabled={isDisabledComponent}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
{folderList.id && (
|
||||
{folderList.id && selectedThirdPartyAccount && (
|
||||
<FilesSelectorInput
|
||||
className={"restore-backup_input"}
|
||||
descriptionText={descriptionText}
|
||||
@ -352,7 +267,7 @@ const DirectThirdPartyConnection = (props) => {
|
||||
)}
|
||||
{deleteThirdPartyDialogVisible && (
|
||||
<DeleteThirdPartyDialog
|
||||
updateInfo={updateAccountsInfo}
|
||||
updateInfo={setThirdPartyAccountsInfo}
|
||||
key="thirdparty-delete-dialog"
|
||||
isConnectionViaBackupModule
|
||||
/>
|
||||
@ -367,8 +282,10 @@ export default inject(({ backup, dialogsStore, filesSettingsStore }) => {
|
||||
setSelectedThirdPartyAccount,
|
||||
selectedThirdPartyAccount,
|
||||
connectedThirdPartyAccount,
|
||||
setConnectedThirdPartyAccount,
|
||||
isTheSameThirdPartyAccount,
|
||||
|
||||
accounts,
|
||||
setThirdPartyAccountsInfo,
|
||||
} = backup;
|
||||
const { openConnectWindow } = filesSettingsStore.thirdPartyStore;
|
||||
|
||||
@ -390,6 +307,8 @@ export default inject(({ backup, dialogsStore, filesSettingsStore }) => {
|
||||
setSelectedThirdPartyAccount,
|
||||
selectedThirdPartyAccount,
|
||||
connectedThirdPartyAccount,
|
||||
setConnectedThirdPartyAccount,
|
||||
|
||||
accounts,
|
||||
setThirdPartyAccountsInfo,
|
||||
};
|
||||
})(observer(DirectThirdPartyConnection));
|
||||
|
@ -204,7 +204,7 @@ export const TableDataCell = styled.td`
|
||||
}
|
||||
|
||||
:last-child {
|
||||
text-align: center;
|
||||
text-align: end;
|
||||
}
|
||||
.remove-icon {
|
||||
svg {
|
||||
|
@ -35,8 +35,12 @@ import { toastr } from "@docspace/shared/components/toast";
|
||||
import { AutoBackupPeriod } from "@docspace/shared/enums";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import config from "PACKAGE_FILE";
|
||||
import { uploadBackup } from "@docspace/shared/api/files";
|
||||
|
||||
import {
|
||||
getSettingsThirdParty,
|
||||
getThirdPartyCapabilities,
|
||||
uploadBackup,
|
||||
} from "@docspace/shared/api/files";
|
||||
import i18n from "../i18n";
|
||||
const { EveryDayType, EveryWeekType } = AutoBackupPeriod;
|
||||
|
||||
class BackupStore {
|
||||
@ -95,6 +99,9 @@ class BackupStore {
|
||||
storageRegions = [];
|
||||
selectedThirdPartyAccount = null;
|
||||
connectedThirdPartyAccount = null;
|
||||
accounts = [];
|
||||
capabilities = [];
|
||||
connectedAccount = [];
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
@ -188,14 +195,101 @@ class BackupStore {
|
||||
return false;
|
||||
}
|
||||
|
||||
setThirdPartyAccountsInfo = async () => {
|
||||
const [connectedAccount, capabilities] = await Promise.all([
|
||||
getSettingsThirdParty(),
|
||||
getThirdPartyCapabilities(),
|
||||
]);
|
||||
|
||||
this.setCapabilities(capabilities);
|
||||
this.setConnectedThirdPartyAccount(connectedAccount);
|
||||
|
||||
const providerNames = [
|
||||
["GoogleDrive", i18n.t("Translations:TypeTitleGoogle")],
|
||||
["Box", i18n.t("Translations:TypeTitleBoxNet")],
|
||||
["DropboxV2", i18n.t("Translations:TypeTitleDropBox")],
|
||||
["SharePoint", i18n.t("Translations:TypeTitleSharePoint")],
|
||||
["OneDrive", i18n.t("Translations:TypeTitleSkyDrive")],
|
||||
["WebDav", "Nextcloud"],
|
||||
["WebDav", "ownCloud"],
|
||||
["kDrive", i18n.t("Translations:TypeTitlekDrive")],
|
||||
["Yandex", i18n.t("Translations:TypeTitleYandex")],
|
||||
["WebDav", i18n.t("Translations:TypeTitleWebDav")],
|
||||
];
|
||||
|
||||
let accounts = [],
|
||||
selectedAccount = {};
|
||||
let index = 0;
|
||||
providerNames.map((item) => {
|
||||
const { account, isConnected } = this.getThirdPartyAccount(
|
||||
item[0],
|
||||
item[1],
|
||||
index,
|
||||
);
|
||||
|
||||
if (!account) return;
|
||||
|
||||
accounts.push(account);
|
||||
|
||||
if (isConnected) {
|
||||
selectedAccount = { ...accounts[index] };
|
||||
}
|
||||
index++;
|
||||
});
|
||||
|
||||
this.setThirdPartyAccounts(accounts);
|
||||
|
||||
console.log(selectedAccount, accounts);
|
||||
|
||||
this.setSelectedThirdPartyAccount(
|
||||
Object.keys(selectedAccount).length !== 0
|
||||
? selectedAccount
|
||||
: { ...accounts[0] },
|
||||
);
|
||||
};
|
||||
|
||||
getThirdPartyAccount = (providerKey, serviceTitle, index) => {
|
||||
const accountIndex =
|
||||
this.capabilities &&
|
||||
this.capabilities.findIndex((x) => x[0] === providerKey);
|
||||
|
||||
if (accountIndex === -1) return { account: null, isConnected: false };
|
||||
|
||||
const isConnected =
|
||||
this.connectedThirdPartyAccount?.providerKey === "WebDav"
|
||||
? serviceTitle === this.connectedThirdPartyAccount?.title
|
||||
: this.capabilities[accountIndex][0] ===
|
||||
this.connectedThirdPartyAccount?.providerKey;
|
||||
|
||||
const account = {
|
||||
key: index.toString(),
|
||||
label: serviceTitle,
|
||||
title: serviceTitle,
|
||||
provider_key: this.capabilities[accountIndex][0],
|
||||
...(this.capabilities[accountIndex][1] && {
|
||||
provider_link: this.capabilities[accountIndex][1],
|
||||
}),
|
||||
connected: isConnected,
|
||||
...(isConnected && {
|
||||
provider_id: this.connectedThirdPartyAccount?.providerId,
|
||||
id: this.connectedThirdPartyAccount.id,
|
||||
}),
|
||||
};
|
||||
|
||||
return { account, isConnected };
|
||||
};
|
||||
|
||||
setCapabilities = (capabilities) => {
|
||||
this.capabilities = capabilities;
|
||||
};
|
||||
setThirdPartyAccounts = (accounts) => {
|
||||
this.accounts = accounts;
|
||||
};
|
||||
|
||||
setSelectedThirdPartyAccount = (elem) => {
|
||||
this.selectedThirdPartyAccount = elem;
|
||||
};
|
||||
|
||||
get selectedThirdPartyAccount() {
|
||||
return this.selectedThirdPartyAccount;
|
||||
}
|
||||
|
||||
toDefault = () => {
|
||||
this.selectedMonthlySchedule = this.defaultMonthlySchedule;
|
||||
this.selectedWeeklySchedule = this.defaultWeeklySchedule;
|
||||
|
@ -76,6 +76,7 @@ import { ShareAccessRights, RoomsType } from "@docspace/shared/enums";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { isDesktop } from "@docspace/shared/utils";
|
||||
import { Events } from "@docspace/shared/enums";
|
||||
import { copyShareLink } from "@docspace/shared/utils/copy";
|
||||
|
||||
import { connectedCloudsTypeTitleTranslation } from "@docspace/client/src/helpers/filesUtils";
|
||||
import { getOAuthToken } from "@docspace/shared/utils/common";
|
||||
@ -367,7 +368,7 @@ class ContextOptionsStore {
|
||||
|
||||
if (isShared && !item.isFolder && !isArchive) {
|
||||
const fileLinkData = await getFileLink(item.id);
|
||||
copy(fileLinkData.sharedTo.shareLink);
|
||||
copyShareLink(fileLinkData.sharedTo.shareLink);
|
||||
return toastr.success(t("Translations:LinkCopySuccess"));
|
||||
}
|
||||
|
||||
@ -407,7 +408,7 @@ class ContextOptionsStore {
|
||||
const primaryLink = await this.filesStore.getPrimaryLink(item.id);
|
||||
|
||||
if (primaryLink) {
|
||||
copy(primaryLink.sharedTo.shareLink);
|
||||
copyShareLink(primaryLink.sharedTo.shareLink);
|
||||
item.shared
|
||||
? toastr.success(t("Common:LinkSuccessfullyCopied"))
|
||||
: toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
|
||||
@ -1311,7 +1312,7 @@ class ContextOptionsStore {
|
||||
|
||||
const primaryLink = await getPrimaryFileLink(item.id);
|
||||
if (primaryLink) {
|
||||
copy(primaryLink.sharedTo.shareLink);
|
||||
copyShareLink(primaryLink.sharedTo.shareLink);
|
||||
item.shared
|
||||
? toastr.success(t("Files:LinkSuccessfullyCopied"))
|
||||
: toastr.success(t("Files:LinkSuccessfullyCreatedAndCopied"));
|
||||
@ -1556,17 +1557,7 @@ class ContextOptionsStore {
|
||||
const pluginItems = this.onLoadPlugins(item);
|
||||
|
||||
if (pluginItems.length > 0) {
|
||||
if (isDesktop()) {
|
||||
options.splice(1, 0, {
|
||||
id: "option_plugin-actions",
|
||||
key: "plugin_actions",
|
||||
label: t("Common:Actions"),
|
||||
icon: PluginActionsSvgUrl,
|
||||
disabled: false,
|
||||
|
||||
onLoad: () => this.onLoadPlugins(item),
|
||||
});
|
||||
} else {
|
||||
if (!isDesktop() || pluginItems.length === 1) {
|
||||
pluginItems.forEach((plugin) => {
|
||||
options.splice(1, 0, {
|
||||
id: `option_${plugin.key}`,
|
||||
@ -1577,6 +1568,16 @@ class ContextOptionsStore {
|
||||
onClick: plugin.onClick,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
options.splice(1, 0, {
|
||||
id: "option_plugin-actions",
|
||||
key: "plugin_actions",
|
||||
label: t("Common:Actions"),
|
||||
icon: PluginActionsSvgUrl,
|
||||
disabled: false,
|
||||
|
||||
onLoad: () => this.onLoadPlugins(item),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ class DialogStore {
|
||||
dataReassignmentDeleteProfile = false;
|
||||
isDeletingUserWithReassignment = false;
|
||||
changeEmailVisible = false;
|
||||
deleteGroupDialogVisible = false;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
@ -95,6 +96,10 @@ class DialogStore {
|
||||
this.changeEmailVisible = visible;
|
||||
};
|
||||
|
||||
setDeleteGroupDialogVisible = (visible) => {
|
||||
this.deleteGroupDialogVisible = visible;
|
||||
};
|
||||
|
||||
closeDialogs = () => {
|
||||
this.setChangeOwnerDialogVisible(false);
|
||||
this.setDeleteSelfProfileDialogVisible(false);
|
||||
@ -108,6 +113,8 @@ class DialogStore {
|
||||
this.setResetAuthDialogVisible(false);
|
||||
|
||||
this.setChangeEmailVisible(false);
|
||||
|
||||
this.setDeleteGroupDialogVisible(false);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -55,10 +55,14 @@ class GroupsStore {
|
||||
|
||||
bufferSelection = null;
|
||||
|
||||
groupName = "";
|
||||
|
||||
selected = "none";
|
||||
|
||||
groupsFilter = GroupsFilter.getDefault();
|
||||
|
||||
isLoading = false;
|
||||
|
||||
groupsIsIsLoading = false;
|
||||
|
||||
insideGroupIsLoading = false;
|
||||
@ -120,6 +124,14 @@ class GroupsStore {
|
||||
window.DocSpace.navigate(`accounts/groups/filter?${filter.toUrlParams()}`);
|
||||
};
|
||||
|
||||
setGroupName = (name: string) => {
|
||||
this.groupName = name;
|
||||
};
|
||||
|
||||
setIsLoading = (isLoading: boolean) => {
|
||||
this.isLoading = isLoading;
|
||||
};
|
||||
|
||||
get groupsFilterTotal() {
|
||||
return this.groupsFilter.total;
|
||||
}
|
||||
@ -396,6 +408,56 @@ class GroupsStore {
|
||||
this.setSelection(newSelections);
|
||||
};
|
||||
|
||||
onDeleteClick = (name: string) => {
|
||||
this.setGroupName(name);
|
||||
this.peopleStore.dialogStore.setDeleteGroupDialogVisible(true);
|
||||
};
|
||||
|
||||
onDeleteGroup = async (t, groupId) => {
|
||||
this.setIsLoading(true);
|
||||
|
||||
if (!groupId) {
|
||||
this.setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await groupsApi.deleteGroup(groupId);
|
||||
toastr.success(t("PeopleTranslations:SuccessDeleteGroup"));
|
||||
this.setSelection([]);
|
||||
this.getGroups(this.groupsFilter, true);
|
||||
this.infoPanelStore.setInfoPanelSelection(null);
|
||||
this.setIsLoading(false);
|
||||
this.peopleStore.dialogStore.setDeleteGroupDialogVisible(false);
|
||||
} catch (err) {
|
||||
toastr.error(err.message);
|
||||
console.error(err);
|
||||
this.setIsLoading(false);
|
||||
this.peopleStore.dialogStore.setDeleteGroupDialogVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
onDeleteAllGroups = (t) => {
|
||||
this.setIsLoading(true);
|
||||
|
||||
try {
|
||||
Promise.all(
|
||||
this.selection.map(async (group) => groupsApi.deleteGroup(group.id)),
|
||||
).then(() => {
|
||||
toastr.success(t("PeopleTranslations:SuccessDeleteGroups"));
|
||||
this.setSelection([]);
|
||||
this.getGroups(this.groupsFilter, true);
|
||||
this.setIsLoading(false);
|
||||
this.peopleStore.dialogStore.setDeleteGroupDialogVisible(false);
|
||||
});
|
||||
} catch (err) {
|
||||
toastr.error(err.message);
|
||||
console.error(err);
|
||||
this.setIsLoading(false);
|
||||
this.peopleStore.dialogStore.setDeleteGroupDialogVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
getGroupContextOptions = (
|
||||
t,
|
||||
item,
|
||||
@ -444,21 +506,24 @@ class GroupsStore {
|
||||
label: t("Common:Delete"),
|
||||
title: t("Common:Delete"),
|
||||
icon: TrashReactSvgUrl,
|
||||
onClick: async () => {
|
||||
const groupId = item.id;
|
||||
groupsApi
|
||||
.deleteGroup(groupId)!
|
||||
.then(() => {
|
||||
toastr.success(t("PeopleTranslations:SuccessDeleteGroup"));
|
||||
this.setSelection([]);
|
||||
this.getGroups(this.groupsFilter, true);
|
||||
this.infoPanelStore.setInfoPanelSelection(null);
|
||||
})
|
||||
.catch((err) => {
|
||||
toastr.error(err.message);
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
onClick: () => this.onDeleteClick(item.name),
|
||||
|
||||
//
|
||||
// onClick: async () => {
|
||||
// const groupId = item.id;
|
||||
// groupsApi
|
||||
// .deleteGroup(groupId)!
|
||||
// .then(() => {
|
||||
// toastr.success(t("PeopleTranslations:SuccessDeleteGroup"));
|
||||
// this.setSelection([]);
|
||||
// this.getGroups(this.groupsFilter, true);
|
||||
// this.infoPanelStore.setInfoPanelSelection(null);
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// toastr.error(err.message);
|
||||
// console.error(err);
|
||||
// });
|
||||
// },
|
||||
},
|
||||
];
|
||||
};
|
||||
|
@ -381,6 +381,14 @@ class PeopleStore {
|
||||
return options;
|
||||
}
|
||||
};
|
||||
|
||||
onDeleteClick = () => {
|
||||
const { setDeleteGroupDialogVisible } = this.dialogStore;
|
||||
const { selection, setGroupName } = this.groupsStore;
|
||||
setGroupName(selection[0].name);
|
||||
setDeleteGroupDialogVisible(true);
|
||||
};
|
||||
|
||||
getHeaderMenu = (t, isGroupsPage = false) => {
|
||||
const {
|
||||
hasUsersToMakeEmployees,
|
||||
@ -394,8 +402,6 @@ class PeopleStore {
|
||||
selection,
|
||||
} = this.selectionStore;
|
||||
|
||||
const { selection: groupsSelection, groupsFilter } = this.groupsStore;
|
||||
|
||||
const { setSendInviteDialogVisible } = this.dialogStore;
|
||||
const { toggleDeleteProfileEverDialog } = this.contextOptionsStore;
|
||||
|
||||
@ -407,20 +413,7 @@ class PeopleStore {
|
||||
id: "menu-delete",
|
||||
key: "delete",
|
||||
label: t("Common:Delete"),
|
||||
onClick: () => {
|
||||
Promise.all(
|
||||
groupsSelection.map(async (group) => deleteGroup(group.id)),
|
||||
)
|
||||
.then(() => {
|
||||
toastr.success(t("PeopleTranslations:SuccessDeleteGroups"));
|
||||
this.groupsStore.setSelection([]);
|
||||
this.groupsStore.getGroups(groupsFilter, true);
|
||||
})
|
||||
.catch((err) => {
|
||||
toastr.error(err.message);
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
onClick: () => this.onDeleteClick(),
|
||||
iconUrl: DeleteReactSvgUrl,
|
||||
},
|
||||
];
|
||||
|
@ -396,23 +396,6 @@ class TableStore {
|
||||
|
||||
if (isFrame) return `${TABLE_SDK_COLUMNS}=${userId}`;
|
||||
|
||||
console.log(
|
||||
"Table log tableStorageName",
|
||||
isRooms
|
||||
? `${TABLE_ROOMS_COLUMNS}=${userId}`
|
||||
: isAccountsPeople
|
||||
? `${TABLE_ACCOUNTS_PEOPLE_COLUMNS}=${userId}`
|
||||
: isAccountsGroups
|
||||
? `${TABLE_ACCOUNTS_GROUPS_COLUMNS}=${userId}`
|
||||
: isAccountsInsideGroup
|
||||
? `${TABLE_ACCOUNTS_INSIDE_GROUP_COLUMNS}=${userId}`
|
||||
: isTrashFolder
|
||||
? `${TABLE_TRASH_COLUMNS}=${userId}`
|
||||
: isRecentTab
|
||||
? `${TABLE_RECENT_COLUMNS}=${userId}`
|
||||
: `${TABLE_COLUMNS}=${userId}`,
|
||||
);
|
||||
|
||||
return isRooms
|
||||
? `${TABLE_ROOMS_COLUMNS}=${userId}`
|
||||
: isAccountsPeople
|
||||
@ -437,17 +420,6 @@ class TableStore {
|
||||
|
||||
if (isFrame) return `${COLUMNS_SDK_SIZE}=${userId}`;
|
||||
|
||||
console.log(
|
||||
"Table log columnStorageName",
|
||||
isRooms
|
||||
? `${COLUMNS_ROOMS_SIZE}=${userId}`
|
||||
: isTrashFolder
|
||||
? `${COLUMNS_TRASH_SIZE}=${userId}`
|
||||
: isRecentTab
|
||||
? `${COLUMNS_RECENT_SIZE}=${userId}`
|
||||
: `${COLUMNS_SIZE}=${userId}`,
|
||||
);
|
||||
|
||||
return isRooms
|
||||
? `${COLUMNS_ROOMS_SIZE}=${userId}`
|
||||
: isTrashFolder
|
||||
|
@ -86,6 +86,7 @@ export const AccessRightSelectPure = ({
|
||||
backgroundColor={item.color}
|
||||
fontSize="9px"
|
||||
isPaidBadge
|
||||
noHover
|
||||
/>
|
||||
)}
|
||||
</StyledItemTitle>
|
||||
|
@ -259,7 +259,7 @@ const StyledArticleItemImg = styled.div<{ isActive?: boolean }>`
|
||||
|
||||
height: ${(props) => props.theme.catalogItem.img.svg.height};
|
||||
|
||||
.icon {
|
||||
.icon > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -124,19 +124,19 @@ const RoleWrapper = styled.div<{
|
||||
props.theme.avatar.roleWrapperContainer.height.max) ||
|
||||
(props.size === AvatarSize.medium &&
|
||||
props.theme.avatar.roleWrapperContainer.height.medium) ||
|
||||
"16px"};
|
||||
"12px"};
|
||||
width: ${(props) =>
|
||||
(props.size === AvatarSize.max &&
|
||||
props.theme.avatar.roleWrapperContainer.width.max) ||
|
||||
(props.size === AvatarSize.medium &&
|
||||
props.theme.avatar.roleWrapperContainer.width.medium) ||
|
||||
"16px"};
|
||||
"12px"};
|
||||
min-width: ${(props) =>
|
||||
(props.size === AvatarSize.max &&
|
||||
props.theme.avatar.roleWrapperContainer.width.max) ||
|
||||
(props.size === AvatarSize.medium &&
|
||||
props.theme.avatar.roleWrapperContainer.width.medium) ||
|
||||
"16px"};
|
||||
"12px"};
|
||||
`;
|
||||
RoleWrapper.defaultProps = { theme: Base };
|
||||
|
||||
|
@ -205,6 +205,7 @@ const AvatarPure = ({
|
||||
id={uniqueTooltipId}
|
||||
getContent={getTooltipContent}
|
||||
place={tooltipPlace}
|
||||
opacity={1}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
@ -34,21 +34,23 @@ const BannerWrapper = styled.div<{
|
||||
}>`
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
min-height: 140px;
|
||||
max-height: 140px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid ${(props) => props.borderColor};
|
||||
min-height: 142px;
|
||||
max-height: 142px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
background-image: url(${(props) => props.background});
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0% 100%;
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1000;
|
||||
inset: 0px;
|
||||
|
||||
border-radius: 4px;
|
||||
border: 1px solid ${(props) => props.borderColor};
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl" &&
|
||||
css`
|
||||
@ -73,12 +75,6 @@ const BannerWrapper = styled.div<{
|
||||
fill: "#A3A9AE";
|
||||
}
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
}
|
||||
`;
|
||||
|
||||
BannerWrapper.defaultProps = { theme: Base };
|
||||
|
@ -73,6 +73,7 @@ const CampaignsBanner = (props: CampaignsBannerProps) => {
|
||||
color={title?.color || "#333"}
|
||||
fontSize={title?.fontSize}
|
||||
fontWeight={title?.fontWeight}
|
||||
lineHeight="12px"
|
||||
>
|
||||
{Header}
|
||||
</TextComponent>
|
||||
@ -111,6 +112,7 @@ const CampaignsBanner = (props: CampaignsBannerProps) => {
|
||||
fontSize={action?.fontSize}
|
||||
fontWeight={action?.fontWeight}
|
||||
onClick={() => onAction(action?.type, Link)}
|
||||
isHovered
|
||||
>
|
||||
{ButtonLabel}
|
||||
</LinkComponent>
|
||||
|
@ -451,6 +451,7 @@ const ContextMenu = React.forwardRef((props: ContextMenuProps, ref) => {
|
||||
imgClassName="drop-down-item_icon"
|
||||
imgSrc={header.icon}
|
||||
badgeUrl={badgeUrl}
|
||||
color={header.color || ""}
|
||||
/>
|
||||
) : (
|
||||
<RoomIcon
|
||||
|
@ -32,7 +32,6 @@ import { useTheme } from "styled-components";
|
||||
|
||||
import ArrowIcon from "PUBLIC_DIR/images/arrow.right.react.svg";
|
||||
import OutsdideIcon from "PUBLIC_DIR/images/arrow.outside.react.svg";
|
||||
import CheckEditIcon from "PUBLIC_DIR/images/check.edit.react.svg";
|
||||
|
||||
import {
|
||||
classNames,
|
||||
@ -294,7 +293,6 @@ const SubMenu = (props: {
|
||||
{icon}
|
||||
{label}
|
||||
{subMenuIcon}
|
||||
{item.checked && <CheckEditIcon className={subMenuIconClassName} />}
|
||||
{item.isOutsideLink && (
|
||||
<OutsdideIcon className={subMenuIconClassName} />
|
||||
)}
|
||||
|
@ -35,6 +35,7 @@ import {
|
||||
StyledIconBlock,
|
||||
} from "./InputBlock.styled";
|
||||
import { InputBlockProps } from "./InputBlock.types";
|
||||
import { isTablet, isIOS } from "react-device-detect";
|
||||
|
||||
const InputBlock = ({
|
||||
onIconClick,
|
||||
@ -59,7 +60,7 @@ const InputBlock = ({
|
||||
tabIndex = -1,
|
||||
maxLength = 255,
|
||||
onBlur,
|
||||
onFocus,
|
||||
onFocus: onFocusAction,
|
||||
isAutoFocussed,
|
||||
autoComplete = "off",
|
||||
onKeyDown,
|
||||
@ -112,6 +113,19 @@ const InputBlock = ({
|
||||
return iconButtonSize;
|
||||
};
|
||||
|
||||
const onFocus = (focusEvent: React.FocusEvent<HTMLInputElement>) => {
|
||||
const scrollEvent = (e: Event) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
window.onscroll = () => {};
|
||||
};
|
||||
window.onscroll = scrollEvent;
|
||||
|
||||
if (onFocusAction) return onFocusAction(focusEvent);
|
||||
};
|
||||
|
||||
const iconButtonSize = getIconSize();
|
||||
|
||||
return (
|
||||
@ -146,7 +160,7 @@ const InputBlock = ({
|
||||
tabIndex={tabIndex}
|
||||
maxLength={maxLength}
|
||||
onBlur={onBlur}
|
||||
onFocus={onFocus}
|
||||
onFocus={isTablet && isIOS ? onFocus : onFocusAction}
|
||||
isReadOnly={isReadOnly}
|
||||
isAutoFocussed={isAutoFocussed}
|
||||
autoComplete={autoComplete}
|
||||
|
@ -89,7 +89,6 @@ export const ViewerPlayer = ({
|
||||
isFullScreen,
|
||||
panelVisible,
|
||||
thumbnailSrc,
|
||||
isThirdParty,
|
||||
mobileDetails,
|
||||
isPreviewFile,
|
||||
isOpenContextMenu,
|
||||
@ -624,8 +623,7 @@ export const ViewerPlayer = ({
|
||||
};
|
||||
}, [onKeyDown]);
|
||||
|
||||
const posterUrl =
|
||||
thumbnailSrc && !isThirdParty ? `${thumbnailSrc}&size=1280x720` : undefined;
|
||||
const posterUrl = thumbnailSrc ? `${thumbnailSrc}&size=1280x720` : undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -130,7 +130,7 @@ type RoomIconColor = {
|
||||
};
|
||||
|
||||
type RoomIconImage = {
|
||||
color?: undefined;
|
||||
color?: string | undefined;
|
||||
imgSrc: string;
|
||||
imgClassName?: string;
|
||||
};
|
||||
|
@ -477,10 +477,7 @@ const tabletProps = css<{ viewAs?: TViewAs }>`
|
||||
width: 100%;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: ${(props) =>
|
||||
props.viewAs === "profile" || props.viewAs === "settings"
|
||||
? props.theme.section.header.backgroundColor
|
||||
: props.theme.section.header.background};
|
||||
background: ${(props) => props.theme.section.header.backgroundColor};
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
|
@ -155,7 +155,7 @@ const StyledSelectAll = styled.div`
|
||||
|
||||
.checkbox {
|
||||
svg {
|
||||
margin-right: 0px;
|
||||
margin-inline-end: 0px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -206,7 +206,7 @@ const StyledItem = styled.div<{
|
||||
|
||||
.checkbox {
|
||||
svg {
|
||||
margin-right: 0px;
|
||||
margin-inline-end: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import copy from "copy-to-clipboard";
|
||||
import moment from "moment";
|
||||
|
||||
import InfoIcon from "PUBLIC_DIR/images/info.outline.react.svg?url";
|
||||
@ -40,6 +39,7 @@ import {
|
||||
getPrimaryLink,
|
||||
} from "../../api/files";
|
||||
import { TAvailableExternalRights, TFileLink } from "../../api/files/types";
|
||||
import { copyShareLink } from "../../utils/copy";
|
||||
import { TOption } from "../combobox";
|
||||
import { Text } from "../text";
|
||||
import { IconButton } from "../icon-button";
|
||||
@ -114,7 +114,7 @@ const Share = (props: ShareProps) => {
|
||||
: await getPrimaryLink(infoPanelSelection.id);
|
||||
|
||||
setFileLinks([link]);
|
||||
copy(link.sharedTo.shareLink);
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
toastr.success(t("Common:GeneralAccessLinkCopied"));
|
||||
} catch (error) {
|
||||
const message = (error as { message: string }).message
|
||||
@ -204,7 +204,7 @@ const Share = (props: ShareProps) => {
|
||||
);
|
||||
updateLink(link, res);
|
||||
|
||||
copy(link.sharedTo.shareLink);
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
toastr.success(t("Common:LinkSuccessfullyCopied"));
|
||||
} catch (e) {
|
||||
toastr.error(e as TData);
|
||||
@ -247,7 +247,7 @@ const Share = (props: ShareProps) => {
|
||||
if (item.access === ShareAccessRights.DenyAccess) {
|
||||
toastr.success(t("Common:LinkAccessDenied"));
|
||||
} else {
|
||||
copy(link.sharedTo.shareLink);
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
toastr.success(t("Common:LinkSuccessfullyCopied"));
|
||||
}
|
||||
}
|
||||
@ -285,7 +285,7 @@ const Share = (props: ShareProps) => {
|
||||
|
||||
updateLink(link, res);
|
||||
|
||||
copy(link.sharedTo.shareLink);
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
toastr.success(t("Common:LinkSuccessfullyCopied"));
|
||||
} catch (e) {
|
||||
toastr.error(e as TData);
|
||||
|
@ -25,7 +25,6 @@
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
import PlusIcon from "PUBLIC_DIR/images/plus.react.svg?url";
|
||||
import UniverseIcon from "PUBLIC_DIR/images/universe.react.svg?url";
|
||||
@ -34,6 +33,7 @@ import CopyIcon from "PUBLIC_DIR/images/copy.react.svg?url";
|
||||
|
||||
import { RowSkeleton } from "../../../skeletons/share";
|
||||
import { TFileLink } from "../../../api/files/types";
|
||||
import { copyShareLink } from "../../../utils/copy";
|
||||
import { Avatar, AvatarRole, AvatarSize } from "../../avatar";
|
||||
import { Link, LinkType } from "../../link";
|
||||
import { ComboBox, ComboBoxSize, TOption } from "../../combobox";
|
||||
@ -62,7 +62,7 @@ const LinkRow = ({
|
||||
const accessOptions = getAccessOptions(t, availableExternalRights);
|
||||
|
||||
const onCopyLink = (link: TFileLink) => {
|
||||
copy(link.sharedTo.shareLink);
|
||||
copyShareLink(link.sharedTo.shareLink);
|
||||
toastr.success(t("Common:LinkSuccessfullyCopied"));
|
||||
};
|
||||
|
||||
|
@ -46,8 +46,6 @@ const TableBody = (props: TableBodyProps) => {
|
||||
infoPanelVisible = false,
|
||||
} = props;
|
||||
|
||||
console.log("Table log TableBody columnStorageName", columnStorageName);
|
||||
|
||||
return useReactWindow ? (
|
||||
<StyledTableBody
|
||||
useReactWindow={useReactWindow}
|
||||
|
@ -45,7 +45,7 @@ const StyledButton = styled(Button)`
|
||||
|
||||
background-color: ${(props) => props.theme.button.backgroundColor.base};
|
||||
|
||||
.combo-button_selected-icon {
|
||||
.combo-button_selected-icon > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
@ -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 { ReactSVG } from "react-svg";
|
||||
|
||||
import { Text } from "../text";
|
||||
|
||||
@ -108,43 +107,10 @@ const StyledTag = styled.div<{
|
||||
|
||||
StyledTag.defaultProps = { theme: Base };
|
||||
|
||||
const StyledDropdownIcon = styled(ReactSVG)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl" &&
|
||||
css`
|
||||
transform: scaleX(-1);
|
||||
`}
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
svg {
|
||||
path:first-child {
|
||||
stroke: ${(props) => props.theme.tag.color};
|
||||
}
|
||||
path:last-child {
|
||||
fill: ${(props) => props.theme.tag.color};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledDropdownText = styled(Text)`
|
||||
line-height: 30px;
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 8px !important;
|
||||
`
|
||||
: css`
|
||||
margin-left: 8px !important;
|
||||
`}
|
||||
|
||||
display: block;
|
||||
|
||||
pointer-events: none;
|
||||
`;
|
||||
|
||||
export { StyledTag, StyledDropdownText, StyledDropdownIcon };
|
||||
export { StyledTag, StyledDropdownText };
|
||||
|
@ -28,18 +28,13 @@ import React from "react";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
import CrossIconReactSvgUrl from "PUBLIC_DIR/images/cross.react.svg?url";
|
||||
import TagIconReactSvgUrl from "PUBLIC_DIR/images/tag.react.svg?url";
|
||||
|
||||
import { DropDown } from "../drop-down";
|
||||
import { DropDownItem } from "../drop-down-item";
|
||||
import { IconButton } from "../icon-button";
|
||||
import { Text } from "../text";
|
||||
|
||||
import {
|
||||
StyledTag,
|
||||
StyledDropdownIcon,
|
||||
StyledDropdownText,
|
||||
} from "./Tag.styled";
|
||||
import { StyledTag, StyledDropdownText } from "./Tag.styled";
|
||||
import { TagProps } from "./Tag.types";
|
||||
|
||||
export const TagPure = ({
|
||||
@ -154,10 +149,6 @@ export const TagPure = ({
|
||||
onClick={onClickAction}
|
||||
data-tag={t}
|
||||
>
|
||||
<StyledDropdownIcon
|
||||
className="tag__dropdown-item-icon"
|
||||
src={TagIconReactSvgUrl}
|
||||
/>
|
||||
<StyledDropdownText
|
||||
className="tag__dropdown-item-text"
|
||||
fontWeight={600}
|
||||
|
@ -1019,7 +1019,6 @@ class SettingsStore {
|
||||
|
||||
if (window.DocSpaceConfig) window.DocSpaceConfig.isFrame = isFrame;
|
||||
|
||||
console.log("Table log isFrame", isFrame);
|
||||
return isFrame;
|
||||
}
|
||||
|
||||
|
@ -1122,16 +1122,16 @@ export const getBaseTheme = () => {
|
||||
|
||||
roleWrapperContainer: {
|
||||
right: {
|
||||
min: "-5px",
|
||||
min: "-2px",
|
||||
small: "-2px",
|
||||
base: "-2px",
|
||||
medium: "-4px",
|
||||
big: "3px",
|
||||
max: "0px",
|
||||
max: "10px",
|
||||
},
|
||||
|
||||
bottom: {
|
||||
min: "-5px",
|
||||
min: "-2px",
|
||||
small: "3px",
|
||||
base: "4px",
|
||||
medium: "6px",
|
||||
@ -1140,13 +1140,15 @@ export const getBaseTheme = () => {
|
||||
},
|
||||
|
||||
width: {
|
||||
min: "12px",
|
||||
medium: "16px",
|
||||
max: "24px",
|
||||
max: "22px",
|
||||
},
|
||||
|
||||
height: {
|
||||
min: "12px",
|
||||
medium: "16px",
|
||||
max: "24px",
|
||||
max: "22px",
|
||||
},
|
||||
},
|
||||
|
||||
@ -2098,7 +2100,7 @@ export const getBaseTheme = () => {
|
||||
|
||||
links: {
|
||||
iconColor: "#3B72A7",
|
||||
iconErrorColor: "rgba(242, 28, 14, 0.5)", // "#F21C0E",
|
||||
iconErrorColor: "#F24724",
|
||||
primaryColor: "#555F65",
|
||||
},
|
||||
|
||||
|
@ -1090,7 +1090,7 @@ const Dark: TTheme = {
|
||||
|
||||
roleWrapperContainer: {
|
||||
right: {
|
||||
min: "-5px",
|
||||
min: "-2px",
|
||||
small: "-2px",
|
||||
base: "-2px",
|
||||
medium: "-4px",
|
||||
@ -1099,7 +1099,7 @@ const Dark: TTheme = {
|
||||
},
|
||||
|
||||
bottom: {
|
||||
min: "-5px",
|
||||
min: "-2px",
|
||||
small: "3px",
|
||||
base: "4px",
|
||||
medium: "6px",
|
||||
@ -1108,11 +1108,13 @@ const Dark: TTheme = {
|
||||
},
|
||||
|
||||
width: {
|
||||
min: "12px",
|
||||
medium: "16px",
|
||||
max: "24px",
|
||||
},
|
||||
|
||||
height: {
|
||||
min: "12px",
|
||||
medium: "16px",
|
||||
max: "24px",
|
||||
},
|
||||
@ -2070,7 +2072,7 @@ const Dark: TTheme = {
|
||||
|
||||
links: {
|
||||
iconColor: "#858585",
|
||||
iconErrorColor: "rgba(242, 28, 14, 0.5)", // "#F21C0E",
|
||||
iconErrorColor: "#E06451",
|
||||
primaryColor: "#ADADAD",
|
||||
},
|
||||
|
||||
|
37
packages/shared/utils/copy.ts
Normal file
37
packages/shared/utils/copy.ts
Normal file
@ -0,0 +1,37 @@
|
||||
// (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 copy from "copy-to-clipboard";
|
||||
|
||||
const wait = (ms: number) =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
|
||||
export const copyShareLink = async (link: string) => {
|
||||
await wait(100);
|
||||
copy(link);
|
||||
};
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 65 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 76 KiB |
@ -1,4 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.95446 14.6591C9.49648 15.1136 8.75709 15.1136 8.30146 14.6591L1.86207 8.6339C1.50204 8.297 1.07291 7.65859 1.04197 7.16717C0.959191 5.83771 1.01755 3.29201 1.05807 1.94233C1.07263 1.45042 1.4872 1.03804 1.9806 1.02673C3.70894 0.986639 7.37082 0.943817 7.7112 1.28372L14.8024 7.6841C15.2577 8.13865 14.8447 9.28836 14.3858 9.74526L9.95446 14.6591Z" stroke="#333333" stroke-width="2"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.70716 3.29277C4.31616 2.90241 3.68392 2.90241 3.29259 3.29277C2.90247 3.68434 2.90247 4.31663 3.29259 4.70698C3.6842 5.09767 4.31644 5.09767 4.70716 4.70698C5.09761 4.31663 5.09761 3.68401 4.70716 3.29277Z" fill="#333333"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 815 B |
@ -153,7 +153,7 @@
|
||||
"ExpiredLink": "Просроченная ссылка",
|
||||
"FeedbackAndSupport": "Обратная связь и поддержка",
|
||||
"FillFormButton": "Заполнить форму",
|
||||
"Finish": "Заканчивать",
|
||||
"Finish": "Завершить",
|
||||
"FirstName": "Имя",
|
||||
"Free": "Бесплатно",
|
||||
"FreeProFeatures": "Бесплатный доступ к профессиональным функциональным возможностям",
|
||||
@ -378,4 +378,4 @@
|
||||
"Website": "Веб-сайт",
|
||||
"Yes": "Да",
|
||||
"Yesterday": "Вчера"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user