From 93439d4562856978be1d9fdba978ff43c9350334 Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Mon, 19 Aug 2024 16:31:27 +0300 Subject: [PATCH 1/5] Fix Bug 69727 - Settings: Backup. Fixed backup providers --- .../components/dialogs/ConnectDialog/index.js | 2 +- .../DirectThirdPartyConnection.js | 11 ++-- packages/client/src/store/BackupStore.js | 62 ++++++------------- packages/client/src/store/ThirdPartyStore.js | 3 + packages/client/src/store/index.js | 2 +- 5 files changed, 32 insertions(+), 48 deletions(-) diff --git a/packages/client/src/components/dialogs/ConnectDialog/index.js b/packages/client/src/components/dialogs/ConnectDialog/index.js index e6f1814fc8..f82f1516b0 100644 --- a/packages/client/src/components/dialogs/ConnectDialog/index.js +++ b/packages/client/src/components/dialogs/ConnectDialog/index.js @@ -170,7 +170,7 @@ const PureConnectDialogContainer = (props) => { provider_id, ) .then(async () => { - await setThirdPartyAccountsInfo(); + await setThirdPartyAccountsInfo(t); }) .catch((err) => { toastr.error(err); diff --git a/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js b/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js index 8e4586a12f..eceb0a4822 100644 --- a/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js +++ b/packages/client/src/pages/PortalSettings/categories/data-management/backup/common-container/DirectThirdPartyConnection.js @@ -83,7 +83,7 @@ const DirectThirdPartyConnection = (props) => { const onSetSettings = async () => { try { - await setThirdPartyAccountsInfo(); + await setThirdPartyAccountsInfo(t); setState({ isLoading: false, @@ -157,7 +157,7 @@ const DirectThirdPartyConnection = (props) => { provider_id, ); - await setThirdPartyAccountsInfo(); + await setThirdPartyAccountsInfo(t); } catch (e) { toastr.error(e); } @@ -167,7 +167,10 @@ const DirectThirdPartyConnection = (props) => { const onSelectAccount = (options) => { const key = options.key; - setSelectedThirdPartyAccount({ ...accounts[+key] }); + + const account = accounts.find((t) => t.key === key); + + setSelectedThirdPartyAccount(account); }; const onDisconnect = () => { @@ -187,7 +190,7 @@ const DirectThirdPartyConnection = (props) => { key: "Disconnect-settings", label: t("Common:Disconnect"), onClick: onDisconnect, - disabled: selectedThirdPartyAccount?.connected ? false : true, + disabled: selectedThirdPartyAccount?.storageIsConnected ? false : true, icon: AccessNoneReactSvgUrl, }, ]; diff --git a/packages/client/src/store/BackupStore.js b/packages/client/src/store/BackupStore.js index 5546423f34..081724348e 100644 --- a/packages/client/src/store/BackupStore.js +++ b/packages/client/src/store/BackupStore.js @@ -37,13 +37,15 @@ import { combineUrl } from "@docspace/shared/utils/combineUrl"; import config from "PACKAGE_FILE"; import { getSettingsThirdParty, - getThirdPartyCapabilities, uploadBackup, } from "@docspace/shared/api/files"; import i18n from "../i18n"; +import { connectedCloudsTypeTitleTranslation } from "../helpers/filesUtils.js"; + const { EveryDayType, EveryWeekType } = AutoBackupPeriod; class BackupStore { + thirdPartyStore = null; restoreResource = null; backupSchedule = {}; @@ -100,11 +102,12 @@ class BackupStore { selectedThirdPartyAccount = null; connectedThirdPartyAccount = null; accounts = []; - capabilities = []; connectedAccount = []; - constructor() { + constructor(thirdPartyStore) { makeAutoObservable(this); + + this.thirdPartyStore = thirdPartyStore; } setConnectedThirdPartyAccount = (account) => { @@ -195,37 +198,20 @@ class BackupStore { return false; } - setThirdPartyAccountsInfo = async () => { - const [connectedAccount, capabilities] = await Promise.all([ + setThirdPartyAccountsInfo = async (t) => { + const [connectedAccount, providers] = await Promise.all([ getSettingsThirdParty(), - getThirdPartyCapabilities(), + this.thirdPartyStore.fetchConnectingStorages(), ]); - 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, - ); + + providers.map((item) => { + const { account, isConnected } = this.getThirdPartyAccount(item, t); if (!account) return; @@ -248,28 +234,23 @@ class BackupStore { ); }; - getThirdPartyAccount = (providerKey, serviceTitle, index) => { - const accountIndex = - this.capabilities && - this.capabilities.findIndex((x) => x[0] === providerKey); - - if (accountIndex === -1) return { account: null, isConnected: false }; + getThirdPartyAccount = (provider, t) => { + const serviceTitle = connectedCloudsTypeTitleTranslation(provider.name, t); const isConnected = this.connectedThirdPartyAccount?.providerKey === "WebDav" ? serviceTitle === this.connectedThirdPartyAccount?.title - : this.capabilities[accountIndex][0] === - this.connectedThirdPartyAccount?.providerKey; + : provider.key === this.connectedThirdPartyAccount?.providerKey; const account = { - key: index.toString(), + key: provider.name, label: serviceTitle, title: serviceTitle, - provider_key: this.capabilities[accountIndex][0], - ...(this.capabilities[accountIndex][1] && { - provider_link: this.capabilities[accountIndex][1], + provider_key: provider.key, + ...(provider.clientId && { + provider_link: provider.clientId, }), - connected: isConnected, + storageIsConnected: isConnected, ...(isConnected && { provider_id: this.connectedThirdPartyAccount?.providerId, id: this.connectedThirdPartyAccount.id, @@ -279,9 +260,6 @@ class BackupStore { return { account, isConnected }; }; - setCapabilities = (capabilities) => { - this.capabilities = capabilities; - }; setThirdPartyAccounts = (accounts) => { this.accounts = accounts; }; diff --git a/packages/client/src/store/ThirdPartyStore.js b/packages/client/src/store/ThirdPartyStore.js index dfc240167c..06d978b81b 100644 --- a/packages/client/src/store/ThirdPartyStore.js +++ b/packages/client/src/store/ThirdPartyStore.js @@ -84,7 +84,10 @@ class ThirdPartyStore { oauthHref: storage.redirectUrl, category: storage.name, requiredConnectionUrl: storage.requiredConnectionUrl, + clientId: storage.clientId, })); + + return res; }; saveThirdParty = ( diff --git a/packages/client/src/store/index.js b/packages/client/src/store/index.js index bf72d4f179..12cf3f07f2 100644 --- a/packages/client/src/store/index.js +++ b/packages/client/src/store/index.js @@ -98,7 +98,7 @@ const paymentStore = new PaymentStore( ); const wizardStore = new WizardStore(); const confirmStore = new ConfirmStore(); -const backupStore = new BackupStore(); +const backupStore = new BackupStore(thirdPartyStore); const commonStore = new CommonStore(settingsStore); const ssoStore = new SsoFormStore(); From 7b1b2c527b6d995dcbe458c75bb17d1bedf04c57 Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Mon, 19 Aug 2024 17:39:30 +0300 Subject: [PATCH 2/5] Web: Files: BackupStore: fixed getThirdPartyAccount --- packages/client/src/store/BackupStore.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/client/src/store/BackupStore.js b/packages/client/src/store/BackupStore.js index 081724348e..85fdac58fb 100644 --- a/packages/client/src/store/BackupStore.js +++ b/packages/client/src/store/BackupStore.js @@ -235,6 +235,8 @@ class BackupStore { }; getThirdPartyAccount = (provider, t) => { + if (!provider.connected) return { account: null, isConnected: false }; + const serviceTitle = connectedCloudsTypeTitleTranslation(provider.name, t); const isConnected = From 91f7292676ef04618ba52ec5c76c2ac817bc296c Mon Sep 17 00:00:00 2001 From: gopienkonikita Date: Tue, 20 Aug 2024 15:06:31 +0300 Subject: [PATCH 3/5] Web: Files: Fixed ThirdPartyComboBox --- .../ThirdPartyStorage/ThirdPartyComboBox.js | 127 +++++++++++++----- .../sub-components/ThirdPartyStorage/index.js | 5 +- packages/client/src/helpers/constants.js | 11 ++ .../data-management/backup/StyledBackup.js | 26 ++++ .../DirectThirdPartyConnection.js | 72 ++++++++-- packages/client/src/store/BackupStore.js | 24 +++- packages/client/src/store/index.js | 2 +- .../shared/components/combobox/ComboBox.tsx | 2 + .../components/combobox/Combobox.types.ts | 2 + .../combobox/sub-components/ComboButton.tsx | 3 +- public/locales/en/Common.json | 3 +- 11 files changed, 224 insertions(+), 53 deletions(-) diff --git a/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/ThirdPartyStorage/ThirdPartyComboBox.js b/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/ThirdPartyStorage/ThirdPartyComboBox.js index 96c6867649..8506def57e 100644 --- a/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/ThirdPartyStorage/ThirdPartyComboBox.js +++ b/packages/client/src/components/dialogs/CreateEditRoomDialog/sub-components/ThirdPartyStorage/ThirdPartyComboBox.js @@ -24,18 +24,23 @@ // content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 // International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode -import React, { useEffect, useState, useRef } from "react"; +import { useEffect, useState } from "react"; import styled from "styled-components"; - +import { ReactSVG } from "react-svg"; import { isMobileOnly, isMobile } from "react-device-detect"; import { Button } from "@docspace/shared/components/button"; +import { DropDownItem } from "@docspace/shared/components/drop-down-item"; +import { Text } from "@docspace/shared/components/text"; +import { Tooltip } from "@docspace/shared/components/tooltip"; import { connectedCloudsTypeTitleTranslation as ProviderKeyTranslation } from "@docspace/client/src/helpers/filesUtils"; import { Base } from "@docspace/shared/themes"; import { toastr } from "@docspace/shared/components/toast"; import { ComboBox } from "@docspace/shared/components/combobox"; import ExternalLinkReactSvgUrl from "PUBLIC_DIR/images/external.link.react.svg?url"; +import { ThirdPartyServicesUrlName } from "../../../../../helpers/constants"; +import { isDesktop } from "@docspace/shared/utils"; const StyledStorageLocation = styled.div` display: flex; @@ -91,16 +96,29 @@ const StyledStorageLocation = styled.div` StyledStorageLocation.defaultProps = { theme: Base }; -const services = { - GoogleDrive: "google", - Box: "box", - Dropbox: "dropbox", - OneDrive: "skydrive", - Nextcloud: "nextcloud", - kDrive: "kdrive", - ownCloud: "owncloud", - WebDav: "webdav", -}; +const StyledComboBoxItem = styled.div` + display: flex; + + .drop-down-item_text { + color: ${({ theme, isDisabled }) => + isDisabled ? theme.dropDownItem.disableColor : theme.dropDownItem.color}; + } + .drop-down-item_icon { + display: flex; + align-items: center; + + div { + display: flex; + } + + margin-inline-start: auto; + + svg { + min-height: 16px; + min-width: 16px; + } + } +`; const ThirdPartyComboBox = ({ t, @@ -124,15 +142,16 @@ const ThirdPartyComboBox = ({ isDisabled, setIsScrollLocked, + isAdmin, }) => { - const deafultSelectedItem = { + const defaultSelectedItem = { key: "length", label: storageLocation?.provider?.title || t("ThirdPartyStorageComboBoxPlaceholder"), }; - const [selectedItem, setSelectedItem] = useState(deafultSelectedItem); + const [selectedItem, setSelectedItem] = useState(defaultSelectedItem); const thirdparties = connectItems.map((item) => ({ ...item, @@ -142,7 +161,7 @@ const ThirdPartyComboBox = ({ const setStorageLocaiton = (thirparty, isConnected) => { if (!isConnected) { window.open( - `/portal-settings/integration/third-party-services?service=${services[thirparty.id]}`, + `/portal-settings/integration/third-party-services?service=${ThirdPartyServicesUrlName[thirparty.id]}`, "_blank", ); return; @@ -207,35 +226,79 @@ const ThirdPartyComboBox = ({ setSaveThirdpartyResponse(null); }, [saveThirdpartyResponse]); - const options = thirdparties - .sort((storage) => (storage.isConnected ? -1 : 1)) - .map((item) => ({ - label: - item.title + (item.isConnected ? "" : ` (${t("ActivationRequired")})`), - title: item.title, - key: item.id, - icon: item.isConnected ? undefined : ExternalLinkReactSvgUrl, - className: item.isConnected ? "" : "storage-unavailable", - })); + const onSelect = (event) => { + const data = event.currentTarget.dataset; - const onSelect = (elem) => { const thirdparty = thirdparties.find((t) => { - return elem.key === t.id; + return t.id === data.thirdPartyId; }); thirdparty && setStorageLocaiton(thirdparty, thirdparty.isConnected); thirdparty.isConnected - ? setSelectedItem(elem) - : setSelectedItem({ ...deafultSelectedItem }); + ? setSelectedItem({ key: thirdparty.id, label: thirdparty.title }) + : setSelectedItem({ ...defaultSelectedItem }); }; + const getTextTooltip = () => { + return ( + + {t("Common:EnableThirdPartyIntegration")} + + ); + }; + + const advancedOptions = thirdparties + .sort((storage) => (storage.isConnected ? -1 : 1)) + ?.map((item) => { + const isDisabled = !item.isConnected && !isAdmin; + const itemLabel = + item.title + (item.isConnected ? "" : ` (${t("ActivationRequired")})`); + + const disabledData = isDisabled + ? { "data-tooltip-id": "file-links-tooltip", "data-tip": "tooltip" } + : {}; + + return ( + + + + {itemLabel} + + + {!isDisabled && !item.isConnected ? ( + + ) : ( + <> + )} + + {isDisabled && ( + + )} + + ); + }); + return (