diff --git a/packages/asc-web-common/api/files/index.js b/packages/asc-web-common/api/files/index.js
index 00f5d1cc34..72bc8c22b5 100644
--- a/packages/asc-web-common/api/files/index.js
+++ b/packages/asc-web-common/api/files/index.js
@@ -699,6 +699,32 @@ export function saveThirdParty(
return request({ method: "post", url: "files/thirdparty", data });
}
+export function saveSettingsThirdParty(
+ url,
+ login,
+ password,
+ token,
+ isCorporate,
+ customerTitle,
+ providerKey,
+ providerId
+) {
+ const data = {
+ url,
+ login,
+ password,
+ token,
+ isCorporate,
+ customerTitle,
+ providerKey,
+ providerId,
+ };
+ return request({ method: "post", url: "files/thirdparty/backup", data });
+}
+export function getSettingsThirdParty() {
+ return request({ method: "get", url: "files/thirdparty/backup" });
+}
+
export function deleteThirdParty(providerId) {
return request({ method: "delete", url: `files/thirdparty/${providerId}` });
}
diff --git a/products/ASC.Files/Client/src/components/panels/SelectFolderInput/index.js b/products/ASC.Files/Client/src/components/panels/SelectFolderInput/index.js
index 629f06e787..752beb3d73 100644
--- a/products/ASC.Files/Client/src/components/panels/SelectFolderInput/index.js
+++ b/products/ASC.Files/Client/src/components/panels/SelectFolderInput/index.js
@@ -25,11 +25,9 @@ class SelectFolderInput extends React.PureComponent {
};
this._isMount = false;
}
- async componentDidMount() {
- this._isMount = true;
+ setBaseInfo = async () => {
const {
- setFirstLoad,
treeFolders,
foldersType,
id,
@@ -38,8 +36,6 @@ class SelectFolderInput extends React.PureComponent {
withoutBasicSelection,
} = this.props;
- setFirstLoad(false);
-
let resultingFolderTree, resultingId;
try {
@@ -68,11 +64,19 @@ class SelectFolderInput extends React.PureComponent {
resultingFolderTree,
baseId: resultingId,
});
+ };
+ componentDidMount() {
+ this._isMount = true;
+
+ const { setFirstLoad } = this.props;
+
+ setFirstLoad(false);
+ this.setBaseInfo();
}
componentDidUpdate(prevProps) {
const { isSuccessSave, isReset, id } = this.props;
- const { newFolderPath, baseFolderPath } = this.state;
+ const { newFolderPath, baseFolderPath, foldersList } = this.state;
if (!isSuccessSave && isSuccessSave !== prevProps.isSuccessSave) {
newFolderPath &&
@@ -90,6 +94,10 @@ class SelectFolderInput extends React.PureComponent {
newId: null,
});
}
+
+ if (foldersList !== prevProps.foldersList) {
+ this.setBaseInfo();
+ }
}
componentWillUnmount() {
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js
index a4964c8659..be2d5d3082 100644
--- a/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/auto-backup/sub-components/ThirdPartyModule.js
@@ -4,7 +4,7 @@ import { inject, observer } from "mobx-react";
import { BackupStorageType } from "@appserver/common/constants";
import SelectFolderInput from "files/SelectFolderInput";
import ScheduleComponent from "./ScheduleComponent";
-import DirectConnectionContainer from "../../common-container/DirectConnectionContainer";
+import DirectThirdPartyConnection from "../../common-container/DirectThirdPartyConnection";
class ThirdPartyModule extends React.PureComponent {
constructor(props) {
@@ -91,7 +91,7 @@ class ThirdPartyModule extends React.PureComponent {
t,
...rest
} = this.props;
- console.log("passedId", passedId);
+
return (
<>
{!isDocSpace ? (
@@ -113,27 +113,18 @@ class ThirdPartyModule extends React.PureComponent {
) : (
-
-
-
)}
@@ -158,7 +149,7 @@ export default inject(({ backup }) => {
defaultStorageType === `${BackupStorageType.ResourcesModuleType}`;
const passedId = isResourcesDefault ? defaultFolderId : "";
- const isDocSpace = false;
+ const isDocSpace = true;
return {
isResetProcess,
isSavingProcess,
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js
new file mode 100644
index 0000000000..f8bed134be
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js
@@ -0,0 +1,287 @@
+import React, { useEffect, useState } from "react";
+import Button from "@appserver/components/button";
+import SelectFolderInput from "files/SelectFolderInput";
+import {
+ getSettingsThirdParty,
+ getThirdPartyCapabilities,
+ saveSettingsThirdParty,
+} from "@appserver/common/api/files";
+import { StyledBackup } from "../StyledBackup";
+import Text from "@appserver/components/text";
+import ComboBox from "@appserver/components/combobox";
+import toastr from "@appserver/components/toast/toastr";
+import FormConnection from "./FormConnection";
+import { inject, observer } from "mobx-react";
+
+let accounts = [];
+const DirectThirdPartyConnection = (props) => {
+ const {
+ openConnectWindow,
+ getOAuthToken,
+ t,
+ onSelectFolder,
+ onClose,
+ onClickInput,
+ onSetLoadingData,
+ isDisabled,
+ isPanelVisible,
+ withoutBasicSelection,
+ isError,
+ id,
+ isReset,
+ isSuccessSave,
+ } = props;
+
+ useEffect(() => {
+ updateAccountsInfo();
+ }, []);
+
+ const updateAccountsInfo = async () => {
+ try {
+ setIsLoading(true);
+ const connectedAccount = await getConnectedAccounts();
+ onSetThirdPartySettings(
+ connectedAccount?.providerKey,
+ connectedAccount?.providerId,
+ connectedAccount
+ );
+ } catch (e) {
+ setIsLoading(false);
+ if (!e) return;
+ toastr.error(e);
+ }
+ };
+ const onSetThirdPartySettings = async (providerKey, providerId, account) => {
+ try {
+ !isLoading && setIsLoading(true);
+
+ const capabilities = await getThirdPartyCapabilities();
+ accounts = [];
+ let connectedAccount = {};
+
+ for (let i = 0; i < capabilities.length; i++) {
+ const isConnected = capabilities[i][0] === providerKey;
+
+ if (capabilities[i][0] !== "WebDav") {
+ accounts.push({
+ key: i.toString(),
+ label: capabilities[i][0],
+ provider_key: capabilities[i][0],
+ ...(capabilities[i][1] && { provider_link: capabilities[i][1] }),
+ connected: isConnected,
+ ...(isConnected && {
+ provider_id: providerId,
+ }),
+ });
+
+ if (isConnected) {
+ connectedAccount = { ...accounts[i] };
+ }
+ } else {
+ const WebDavVariability = [
+ "Nextcloud",
+ "ownCloud",
+ "ConnextOtherAccount",
+ ];
+ let index = 0;
+
+ for (let j = i; j < i + 3; j++) {
+ accounts.push({
+ key: j.toString(),
+ label: WebDavVariability[index],
+ provider_key: "WebDav",
+ connected: isConnected,
+ ...(isConnected && {
+ provider_id: providerId,
+ }),
+ });
+
+ // if (isConnected) { //TODO: changed for WebDav
+ // connectedAccount = { ...accounts[j] };
+ // }
+
+ index++;
+ }
+ }
+ }
+ setSelectedAccount(
+ Object.keys(connectedAccount).length !== 0
+ ? connectedAccount
+ : { ...accounts[0] }
+ );
+ setFolderList(account ? account : []);
+ } catch (e) {
+ if (!e) return;
+ toastr.error(e);
+ }
+
+ setIsLoading(false);
+ };
+
+ const [selectedAccount, setSelectedAccount] = useState({});
+ const [isLoading, setIsLoading] = useState(false);
+ const [isVisibleConnectionForm, setIsVisibleConnectionForm] = useState(false);
+ const [folderList, setFolderList] = useState([]);
+ const onConnect = () => {
+ const { label, provider_link } = selectedAccount;
+
+ const directConnection = provider_link;
+
+ if (directConnection) {
+ let authModal = window.open(
+ "",
+ "Authorization",
+ "height=600, width=1020"
+ );
+
+ openConnectWindow(label, authModal)
+ .then(getOAuthToken)
+ .then((token) => {
+ saveSettings(token);
+ authModal.close();
+ })
+ .catch((e) => {
+ if (!e) return;
+ toastr.error(e);
+ console.error(e);
+ });
+ } else {
+ setIsVisibleConnectionForm(true);
+ }
+ };
+
+ const getConnectedAccounts = async () => {
+ return await getSettingsThirdParty();
+ };
+
+ const saveSettings = async (
+ token = "",
+ urlValue = "",
+ loginValue = "",
+ passwordValue = ""
+ ) => {
+ const { label, provider_key, provider_id } = selectedAccount;
+
+ try {
+ setIsLoading(true);
+
+ await saveSettingsThirdParty(
+ urlValue,
+ loginValue,
+ passwordValue,
+ token,
+ false,
+ label,
+ provider_key,
+ provider_id
+ );
+ updateAccountsInfo();
+ isVisibleConnectionForm && setIsVisibleConnectionForm(false);
+ } catch (e) {
+ setIsLoading(false);
+ if (!e) return;
+ toastr.error(e);
+ }
+ };
+
+ const onCloseConnectionForm = () => {
+ setIsVisibleConnectionForm(false);
+ };
+
+ const onSelectAccount = (options) => {
+ const key = options.key;
+
+ setSelectedAccount({ ...accounts[+key] });
+ };
+
+ const onReconnect = () => {
+ let authModal = window.open("", "Authorization", "height=600, width=1020");
+ openConnectWindow(selectedAccount.provider_key, authModal).then((modal) =>
+ getOAuthToken(modal).then((token) => {
+ authModal.close();
+ saveSettings(token);
+ })
+ );
+ };
+
+ return (
+
+
+
+
+ {selectedAccount.connected ? (
+
+ ) : (
+
+ )}
+
+
+ {"Folder name:"}
+
+
+
+
+ {isVisibleConnectionForm && (
+
+ )}
+
+ );
+};
+
+export default inject(({ backup }) => {
+ const { commonThirdPartyList, openConnectWindow, getOAuthToken } = backup;
+
+ return {
+ commonThirdPartyList,
+ openConnectWindow,
+ getOAuthToken,
+ };
+})(observer(DirectThirdPartyConnection));
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/common-container/FormConnection.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/common-container/FormConnection.js
new file mode 100644
index 0000000000..85572fa648
--- /dev/null
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/common-container/FormConnection.js
@@ -0,0 +1,153 @@
+import React, { useState, useEffect, useCallback } from "react";
+import Button from "@appserver/components/button";
+import ModalDialog from "@appserver/components/modal-dialog";
+import TextInput from "@appserver/components/text-input";
+import PasswordInput from "@appserver/components/password-input";
+import FieldContainer from "@appserver/components/field-container";
+
+const FormConnection = (props) => {
+ const { visible, t, tReady, item, saveSettings, onClose } = props;
+ const { provider_key, key } = item;
+
+ const [urlValue, setUrlValue] = useState("");
+ const [loginValue, setLoginValue] = useState("");
+ const [passwordValue, setPasswordValue] = useState("");
+
+ const [isUrlValid, setIsUrlValid] = useState(true);
+ const [isLoginValid, setIsLoginValid] = useState(true);
+ const [isPasswordValid, setIsPasswordValid] = useState(true);
+
+ const [isLoading, setIsLoading] = useState(false);
+
+ const showUrlField =
+ provider_key === "WebDav" ||
+ provider_key === "SharePoint" ||
+ key === "WebDav" ||
+ key === "SharePoint";
+
+ const onChangeUrl = (e) => {
+ setIsUrlValid(true);
+ setUrlValue(e.target.value);
+ };
+ const onChangeLogin = (e) => {
+ setIsLoginValid(true);
+ setLoginValue(e.target.value);
+ };
+ const onChangePassword = (e) => {
+ setIsPasswordValid(true);
+ setPasswordValue(e.target.value);
+ };
+
+ const onKeyUpHandler = useCallback(
+ (e) => {
+ if (e.keyCode === 13) onSave();
+ },
+ [urlValue, loginValue, passwordValue, showUrlField]
+ );
+
+ useEffect(() => {
+ window.addEventListener("keyup", onKeyUpHandler);
+ return () => window.removeEventListener("keyup", onKeyUpHandler);
+ }, [onKeyUpHandler]);
+
+ const onSave = useCallback(() => {
+ const urlValid = !!urlValue.trim();
+ const loginValid = !!loginValue.trim();
+ const passwordValid = !!passwordValue.trim();
+
+ if (!loginValid || !passwordValid || (showUrlField && !urlValid)) {
+ showUrlField && setIsUrlValid(urlValid);
+ setIsLoginValid(loginValid);
+ setIsPasswordValid(passwordValid);
+ return;
+ }
+
+ saveSettings(undefined, urlValue, loginValue, passwordValue);
+ }, [urlValue, loginValue, passwordValue, showUrlField]);
+
+ return (
+
+
+ {t("Translations:ConnectingAccount")}
+
+
+ <>
+ {showUrlField && (
+
+
+
+ )}
+
+
+
+
+
+
+
+ >
+
+
+
+
+
+ );
+};
+
+export default FormConnection;
diff --git a/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js
index ad563b9e91..0bd5ef8fe7 100644
--- a/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js
+++ b/web/ASC.Web.Client/src/components/pages/Settings/categories/data-management/backup/manual-backup/sub-components/ThirdPartyModule.js
@@ -5,46 +5,22 @@ import SelectFolderInput from "files/SelectFolderInput";
import Button from "@appserver/components/button";
import { getFromSessionStorage } from "../../../../../utils";
import { BackupStorageType } from "@appserver/common/constants";
-import DirectConnectionContainer from "../../common-container/DirectConnectionContainer";
+import DirectThirdPartyConnection from "../../common-container/DirectThirdPartyConnection";
let folder = "";
class ThirdPartyModule extends React.Component {
constructor(props) {
super(props);
- const { isDocSpace } = props;
-
folder = getFromSessionStorage("LocalCopyFolder");
- if (isDocSpace) {
- this.accounts = [
- {
- key: "0",
- label: "Google Drive",
- },
- {
- key: "1",
- label: "OneDrive ",
- },
- {
- key: "2",
- label: "Dropbox ",
- },
- {
- key: "3",
- label: "Box.com",
- },
- ];
- }
-
this.state = {
+ isLoading: false,
isStartCopy: false,
isLoadingData: false,
selectedFolder: folder || "",
isPanelVisible: false,
isError: false,
- ...(isDocSpace && { selectedAccount: this.accounts[0] }),
- isConnected: false,
};
}
@@ -116,18 +92,12 @@ class ThirdPartyModule extends React.Component {
};
onSelectAccount = (options) => {
const key = options.key;
- const label = options.label;
this.setState({
- selectedAccount: { key, label },
+ selectedAccount: { ...this.accounts[+key] },
});
};
- onConnect = () => {
- const { isConnected } = this.state;
-
- this.setState({ isConnected: !isConnected });
- };
render() {
const {
isMaxProgress,
@@ -141,8 +111,6 @@ class ThirdPartyModule extends React.Component {
isLoadingData,
isError,
isStartCopy,
- selectedAccount,
- isConnected,
selectedFolder,
} = this.state;
@@ -185,26 +153,16 @@ class ThirdPartyModule extends React.Component {
>
) : (
-
-
-