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 && ( + + + + )} + + + + + + + + + + +