Merge branch 'release/rc-v1.2.0' into bugfix/images-static-versioned
This commit is contained in:
commit
676ecb379c
@ -132,7 +132,6 @@ public class NotifyHelper
|
||||
Actions.RestoreCompletedV115,
|
||||
new IRecipient[] { user },
|
||||
new[] { StudioNotifyService.EMailSenderName },
|
||||
null,
|
||||
TagValues.GreenButton(greenButtonText, confirmationUrl));
|
||||
}
|
||||
}
|
||||
|
@ -186,9 +186,8 @@ public class RestoreProgressItem : BaseBackupProgressItem
|
||||
}
|
||||
|
||||
_tenantManager.SaveTenant(restoredTenant);
|
||||
_tenantManager.SetCurrentTenant(restoredTenant);
|
||||
// sleep until tenants cache expires
|
||||
Thread.Sleep(TimeSpan.FromMinutes(2));
|
||||
_tenantManager.SetCurrentTenant(restoredTenant);
|
||||
TenantId = restoredTenant.Id;
|
||||
|
||||
_notifyHelper.SendAboutRestoreCompleted(restoredTenant, Notify);
|
||||
}
|
||||
@ -199,13 +198,14 @@ public class RestoreProgressItem : BaseBackupProgressItem
|
||||
|
||||
File.Delete(tempFile);
|
||||
|
||||
Percentage = 100;
|
||||
PublishChanges();
|
||||
Percentage = 100;
|
||||
Status = DistributedTaskStatus.Completed;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
_logger.ErrorRestoreProgressItem(error);
|
||||
Exception = error;
|
||||
Exception = error;
|
||||
Status = DistributedTaskStatus.Failted;
|
||||
|
||||
if (tenant != null)
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ public class TenantsModuleSpecifics : ModuleSpecificsBase
|
||||
{
|
||||
new RelationInfo("tenants_tenants", "id", "tenants_quota", "tenant"),
|
||||
new RelationInfo("tenants_tenants", "id", "tenants_tariff", "tenant"),
|
||||
new RelationInfo("tenants_tenants", "id", "tenants_tariff", "tariff", x => Convert.ToInt32(x["tariff"]) > 0),
|
||||
new RelationInfo("tenants_tenants", "id", "tenants_tariff", "tariff"),
|
||||
new RelationInfo("core_user", "id", "tenants_tenants", "owner_id", null, null, RelationImportance.Low)
|
||||
};
|
||||
|
||||
|
@ -197,6 +197,7 @@ public class BackupController : ControllerBase
|
||||
/// <category>Backup</category>
|
||||
/// <returns>Restore Progress</returns>
|
||||
[HttpGet("getrestoreprogress")] //NOTE: this method doesn't check payment!!!
|
||||
[AllowAnonymous]
|
||||
[AllowNotPayment]
|
||||
public BackupProgress GetRestoreProgress()
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ global using ASC.Web.Api.Routing;
|
||||
global using ASC.Web.Studio.Core.Backup;
|
||||
global using ASC.Web.Studio.Core.Notify;
|
||||
global using ASC.Web.Studio.Utility;
|
||||
|
||||
global using Microsoft.AspNetCore.Authorization;
|
||||
global using Autofac;
|
||||
|
||||
global using Microsoft.AspNetCore.Http.Features;
|
||||
|
@ -107,7 +107,8 @@
|
||||
"web": {
|
||||
"api": "api/2.0",
|
||||
"alias": {
|
||||
"min": ""
|
||||
"min": 3,
|
||||
"max": 50
|
||||
},
|
||||
"images": "images",
|
||||
"hide-settings": "Monitoring,LdapSettings,DocService,MailService,PublicPortal,ProxyHttpContent,SpamSubscription,FullTextSearch",
|
||||
|
@ -73,7 +73,7 @@
|
||||
"PortalAccessSubTitle": "Bu bölmə sizə istifadəçiləri portala təhlükəsiz və rahat giriş imkanı ilə təmin etmək imkanı verir",
|
||||
"PortalNameEmpty": "Hesab adı boşdur",
|
||||
"PortalNameIncorrect": "Yanlış hesab adı",
|
||||
"PortalNameLength": "Hesab adı ən az 3, ən çox 50 işarədən ibarət ola bilər",
|
||||
"PortalNameLength": "Hesab adı ən az {{minLength}}, ən çox {{maxLength}} işarədən ibarət ola bilər",
|
||||
"PortalRenaming": "Portalın Adının dəyişdirilməsi",
|
||||
"PortalRenamingDescription": "Burada portal ünvanınızı dəyişə bilərsiniz.",
|
||||
"PortalRenamingLabelText": "Yeni portal adı",
|
||||
|
@ -72,7 +72,7 @@
|
||||
"PortalAccessSubTitle": "Този раздел Ви позволява да предоставите на потребителите безопасни и удобни начини за достъп до портала.",
|
||||
"PortalNameEmpty": "Името на профила е празно",
|
||||
"PortalNameIncorrect": "Неправилно име на профила",
|
||||
"PortalNameLength": "Името на профила трябва да бъде дълго между 3 и 50 знака",
|
||||
"PortalNameLength": "Името на профила трябва да бъде дълго между {{minLength}} и {{maxLength}} знака",
|
||||
"PortalRenaming": "Преименуване на портала",
|
||||
"PortalRenamingDescription": "Тук можете да промените адреса на вашия портал.",
|
||||
"PortalRenamingLabelText": "Ново име на портала",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Tato sekce umožňuje poskytnout uživatelům bezpečný a pohodlný způsob přístupu k portálu.",
|
||||
"PortalNameEmpty": "Název účtu je prázdný",
|
||||
"PortalNameIncorrect": "Nesprávný název účtu",
|
||||
"PortalNameLength": "Název účtu musí mít délku od 3 do 50 znaků",
|
||||
"PortalNameLength": "Název účtu musí mít délku od {{minLength}} do {{maxLength}} znaků",
|
||||
"PortalRenaming": "Přejmenování portálu",
|
||||
"PortalRenamingDescription": "Zde můžete změnit Vaši adresu portálu.",
|
||||
"PortalRenamingLabelText": "Nový název portálu",
|
||||
|
@ -73,7 +73,7 @@
|
||||
"PortalAccessSubTitle": "In diesem Bereich können Sie den Benutzern einen sicheren und nahtlosen Zugang zum Portal gewähren.",
|
||||
"PortalNameEmpty": "Der Kontoname ist leer",
|
||||
"PortalNameIncorrect": "Inkorrekter Kontoname",
|
||||
"PortalNameLength": "Der Kontoname muss zwischen 3 und 50 Zeichen lang sein",
|
||||
"PortalNameLength": "Der Kontoname muss zwischen {{minLength}} und {{maxLength}} Zeichen lang sein",
|
||||
"PortalRenaming": "Portalumbenennung",
|
||||
"PortalRenamingDescription": "Hier können Sie Ihre Portaladresse ändern.",
|
||||
"PortalRenamingLabelText": "Neuer Portalname",
|
||||
|
@ -68,7 +68,7 @@
|
||||
"PortalAccessSubTitle": "Αυτή η ενότητα σάς επιτρέπει να παρέχετε στους χρήστες ασφαλείς και βολικούς τρόπους πρόσβασης στην πύλη.",
|
||||
"PortalNameEmpty": "Το όνομα λογαριασμού είναι κενό",
|
||||
"PortalNameIncorrect": "Λανθασμένο όνομα λογαριασμού",
|
||||
"PortalNameLength": "Το όνομα του λογαριασμού πρέπει να έχει μήκος μεταξύ 3 και 50 χαρακτήρων",
|
||||
"PortalNameLength": "Το όνομα του λογαριασμού πρέπει να έχει μήκος μεταξύ {{minLength}} και {{maxLength}} χαρακτήρων",
|
||||
"PortalRenaming": "Μετονομασία πύλης",
|
||||
"PortalRenamingDescription": "Εδώ μπορείτε να αλλάξετε τη διεύθυνση της πύλης σας.",
|
||||
"PortalRenamingLabelText": "Νέο όνομα πύλης",
|
||||
|
@ -137,7 +137,7 @@
|
||||
"PortalIntegration": "Space integration",
|
||||
"PortalNameEmpty": "Account name is empty",
|
||||
"PortalNameIncorrect": "Incorrect account name",
|
||||
"PortalNameLength": "The account name must be between 3 and 50 characters long",
|
||||
"PortalNameLength": "The account name must be between {{minLength}} and {{maxLength}} characters long",
|
||||
"PortalRenaming": "Space Renaming",
|
||||
"PortalRenamingDescription": "Here you can change your space address.",
|
||||
"PortalRenamingLabelText": "New space name",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"ChangeEmailTitle": "Change email",
|
||||
"Desc": "Please set up the DocSpace registration data.",
|
||||
"Domain": "Domain:",
|
||||
"Domain": "Domain",
|
||||
"ErrorEmail": "Invalid email address",
|
||||
"ErrorInitWizard": "The service is currently unavailable, please try again later.",
|
||||
"ErrorInitWizardButton": "Try again",
|
||||
@ -16,7 +16,7 @@
|
||||
"License": "Accept the terms of the ",
|
||||
"LicenseLink": "License agreements",
|
||||
"PlaceholderLicense": "Your license file",
|
||||
"Timezone": "Time zone:",
|
||||
"Timezone": "Timezone",
|
||||
"WelcomeTitle": "Welcome to your DocSpace!",
|
||||
"WizardTitle": "Set up your DocSpace"
|
||||
}
|
||||
|
@ -73,7 +73,7 @@
|
||||
"PortalAccessSubTitle": "Esta sección le permite ofrecer a los usuarios formas seguras y cómodas de acceder al portal.",
|
||||
"PortalNameEmpty": "Nombre de cuenta está vacío",
|
||||
"PortalNameIncorrect": "Nombre de cuenta incorrecto",
|
||||
"PortalNameLength": "El nombre de cuenta debe tener entre 3 y 50 caracteres de longitud",
|
||||
"PortalNameLength": "El nombre de cuenta debe tener entre {{minLength}} y {{maxLength}} caracteres de longitud",
|
||||
"PortalRenaming": "Cambio del nombre de portal",
|
||||
"PortalRenamingDescription": "Puede cambiar la dirección de su portal aquí.",
|
||||
"PortalRenamingLabelText": "Nombre de portal nuevo",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Tämän osan avulla voit tarjota käyttäjille turvallisia ja käteviä tapoja käyttää portaalia.",
|
||||
"PortalNameEmpty": "Tilin nimi on tyhjä",
|
||||
"PortalNameIncorrect": "Virheellinen tilin nimi",
|
||||
"PortalNameLength": "Tilin nimen on oltava 3-50 merkkiä pitkä",
|
||||
"PortalNameLength": "Tilin nimen on oltava {{minLength}}-{{maxLength}} merkkiä pitkä",
|
||||
"PortalRenaming": "Portaalin uudelleennimeäminen",
|
||||
"PortalRenamingDescription": "Tässä voit vaihtaa portaalisi osoitteen.",
|
||||
"PortalRenamingLabelText": "Uusi portaalin nimi",
|
||||
|
@ -73,7 +73,7 @@
|
||||
"PortalAccessSubTitle": "Cette section vous permet de fournir aux utilisateurs des moyens sûrs et pratiques d'accéder au portail.",
|
||||
"PortalNameEmpty": "Nom de compte est vide",
|
||||
"PortalNameIncorrect": "Nom de compte incorrect",
|
||||
"PortalNameLength": "Le nom du compte doit comporter entre 3 et 50 caractères",
|
||||
"PortalNameLength": "Le nom du compte doit comporter entre {{minLength}} et {{maxLength}} caractères",
|
||||
"PortalRenaming": "Changement de nom du portail",
|
||||
"PortalRenamingDescription": "Ici vous pouvez changer l'adresse du portail.",
|
||||
"PortalRenamingLabelText": "Nouveau nom du portail",
|
||||
|
@ -68,7 +68,7 @@
|
||||
"PortalAccessSubTitle": "Այս բաժինը թույլ է տալիս օգտվողներին տրամադրել կայքէջ մուտք գործելու անվտանգ և հարմար եղանակներ:",
|
||||
"PortalNameEmpty": "Հաշվի անունը դատարկ է",
|
||||
"PortalNameIncorrect": "Հաշվի սխալ անուն",
|
||||
"PortalNameLength": "Հաշվի անունը պետք է լինի 3-ից 50 նիշ",
|
||||
"PortalNameLength": "Հաշվի անունը պետք է լինի {{minLength}}-ից {{maxLength}} նիշ",
|
||||
"PortalRenaming": "Կայքէջի վերանվանում",
|
||||
"PortalRenamingDescription": "Այստեղ Դուք կարող եք փոխել Ձեր կայքէջի հասցեն:",
|
||||
"PortalRenamingLabelText": "Նոր կայքէջի անուն",
|
||||
|
@ -73,7 +73,7 @@
|
||||
"PortalAccessSubTitle": "Questa sezione consente di fornire agli utenti modi sicuri e convenienti per accedere al portale.",
|
||||
"PortalNameEmpty": "Nome account vuoto",
|
||||
"PortalNameIncorrect": "Nome account errato",
|
||||
"PortalNameLength": "Il nome dell'account deve contenere da 3 a 50 caratteri",
|
||||
"PortalNameLength": "Il nome dell'account deve contenere da {{minLength}} a {{maxLength}} caratteri",
|
||||
"PortalRenaming": "Ridenominazione del portale",
|
||||
"PortalRenamingDescription": "Qui tu puoi cambiare il tuo indirizzo portale.",
|
||||
"PortalRenamingLabelText": "Nome del portale nuovo",
|
||||
|
@ -72,7 +72,7 @@
|
||||
"PortalAccessSubTitle": "このセクションでは、ユーザーがポータルにアクセスするための安全で便利な方法を提供することができます。",
|
||||
"PortalNameEmpty": "アカウント名が空です。",
|
||||
"PortalNameIncorrect": "アカウント名が無効です。",
|
||||
"PortalNameLength": "アカウント名は3~50文字がある必要です。",
|
||||
"PortalNameLength": "アカウント名は{{minLength}}~{{maxLength}}文字がある必要です。",
|
||||
"PortalRenaming": "ポータル改名",
|
||||
"PortalRenamingDescription": "ここではポータルアドレスを変更できます。",
|
||||
"PortalRenamingLabelText": "新のポータル名",
|
||||
|
@ -68,7 +68,7 @@
|
||||
"PortalAccessSubTitle": "이 섹션에서는 사용자에게 안전하고 편리한 포털 액세스 방법을 제공할 수 있습니다.",
|
||||
"PortalNameEmpty": "계정 이름이 비어 있습니다",
|
||||
"PortalNameIncorrect": "계정 이름이 잘못되었습니다",
|
||||
"PortalNameLength": "계정 이름은 3~50글자여야 합니다",
|
||||
"PortalNameLength": "계정 이름은 {{minLength}}~{{maxLength}}글자여야 합니다",
|
||||
"PortalRenaming": "포털 이름 변경",
|
||||
"PortalRenamingDescription": "여기에서 포털 주소를 변경할 수 있습니다.",
|
||||
"PortalRenamingLabelText": "새 포털 이름",
|
||||
|
@ -66,7 +66,7 @@
|
||||
"PortalAccessSubTitle": "ພາກນີ້ຊ່ວຍໃຫ້ທ່ານສາມາດໃຫ້ຜູ້ໃຊ້ມີວິທີທີ່ປອດໄພແລະສະດວກໃນການເຂົ້າເຖິງປະຕູ. ",
|
||||
"PortalNameEmpty": "ບັນຊີ ຊື່ ແມ່ນ ເປົ່າ",
|
||||
"PortalNameIncorrect": "ບໍ່ຖືກຕ້ອງ ບັນຊີ ຊື່ ",
|
||||
"PortalNameLength": "ຊື່ບັນຊີຕ້ອງມີຄວາມຍາວລະຫວ່າງ 3 ຫາ 50 ຕົວອັກສອນ",
|
||||
"PortalNameLength": "ຊື່ບັນຊີຕ້ອງມີຄວາມຍາວລະຫວ່າງ {{minLength}} ຫາ {{maxLength}} ຕົວອັກສອນ",
|
||||
"PortalRenaming": "ປະຕູ ການ ປ່ຽນຊື່ ",
|
||||
"PortalRenamingDescription": "ທີ່ນີ້ທ່ານສາມາດປ່ຽນທີ່ຢູ່ປະຕູຂອງເຈົ້າໄດ້.",
|
||||
"PortalRenamingLabelText": "ໃໝ່ ປະຕູ ຊື່ ",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Šī sadaļa ļauj lietotājiem nodrošināt drošus un ērtus veidus, kā piekļūt portālam.",
|
||||
"PortalNameEmpty": "Konta nosaukums ir tukšs",
|
||||
"PortalNameIncorrect": "Nepareizs konta nosaukums",
|
||||
"PortalNameLength": "Konta nosaukumam ir jābūt no 3 līdz 50 rakstzīmēm garam",
|
||||
"PortalNameLength": "Konta nosaukumam ir jābūt no {{minLength}} līdz {{maxLength}} rakstzīmēm garam",
|
||||
"PortalRenaming": "Portāla pārdēvēšana",
|
||||
"PortalRenamingDescription": "Šeit jūs varat mainīt savu portāla adresi.",
|
||||
"PortalRenamingLabelText": "Jauns portāla nosaukums",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "In dit gedeelte kunt u gebruikers veilige en handige manieren bieden om toegang te krijgen tot het portaal.",
|
||||
"PortalNameEmpty": "Accountnaam is leeg",
|
||||
"PortalNameIncorrect": "Onjuiste accountnaam",
|
||||
"PortalNameLength": "De naam van de account moet tussen 3 en 50 tekens lang zijn",
|
||||
"PortalNameLength": "De naam van de account moet tussen {{minLength}} en {{maxLength}} tekens lang zijn",
|
||||
"PortalRenaming": "Hernoemen Portaal",
|
||||
"PortalRenamingDescription": "Hier kunt u uw portaaladres veranderen.",
|
||||
"PortalRenamingLabelText": "Nieuwe portaalnaam",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Dana sekcja umożliwia zapewnienie użytkownikom bezpiecznych i wygodnych metod dostępu do portalu.",
|
||||
"PortalNameEmpty": "Nazwa konta jest pusta",
|
||||
"PortalNameIncorrect": "Nieprawidłowa nazwa konta",
|
||||
"PortalNameLength": "Nazwa konta musi zawierać od 3 do 50 znaków",
|
||||
"PortalNameLength": "Nazwa konta musi zawierać od {{minLength}} do {{maxLength}} znaków",
|
||||
"PortalRenaming": "Zmiana nazwy portalu",
|
||||
"PortalRenamingDescription": "Tutaj możesz zmienić adres portalu.",
|
||||
"PortalRenamingLabelText": "Nowa nazwa portalu",
|
||||
|
@ -73,7 +73,7 @@
|
||||
"PortalAccessSubTitle": "Esta seção permite que você forneça aos usuários formas seguras e convenientes de acessar o portal.",
|
||||
"PortalNameEmpty": "Nome da conta está vazio",
|
||||
"PortalNameIncorrect": "Nome da conta incorreto",
|
||||
"PortalNameLength": "O nome da conta deve ter entre 3 e 50 caracteres",
|
||||
"PortalNameLength": "O nome da conta deve ter entre {{minLength}} e {{maxLength}} caracteres",
|
||||
"PortalRenaming": "Renomear portal",
|
||||
"PortalRenamingDescription": "Aqui, você pode alterar o endereço do seu portal.",
|
||||
"PortalRenamingLabelText": "Nome do novo portal",
|
||||
|
@ -68,7 +68,7 @@
|
||||
"PortalAccessSubTitle": "Esta secção permite-lhe fornecer aos utilizadores formas seguras e convenientes de aceder ao portal.",
|
||||
"PortalNameEmpty": "Não colocou um nome para a conta",
|
||||
"PortalNameIncorrect": "Nome de conta incorreto",
|
||||
"PortalNameLength": "O nome da conta tem de ter entre 3 e 50 caracteres",
|
||||
"PortalNameLength": "O nome da conta tem de ter entre {{minLength}} e {{maxLength}} caracteres",
|
||||
"PortalRenaming": "Renomeação do Portal",
|
||||
"PortalRenamingDescription": "Aqui pode mudar o endereço do seu portal.",
|
||||
"PortalRenamingLabelText": "Novo nome de portal",
|
||||
|
@ -68,7 +68,7 @@
|
||||
"PortalAccessSubTitle": "Această secțiune va permite să le oferă utilizatorilor accesul sigur și convenabil la portal.",
|
||||
"PortalNameEmpty": "Denumirea contului este necompletată",
|
||||
"PortalNameIncorrect": "Denumirea contului incorectă",
|
||||
"PortalNameLength": "Denumirea contului trebuie să conțină de la 3 până la 50 de caractere",
|
||||
"PortalNameLength": "Denumirea contului trebuie să conțină de la {{minLength}} până la {{maxLength}} de caractere",
|
||||
"PortalRenaming": "Redenumirea portalului",
|
||||
"PortalRenamingDescription": "Aici puteți schimba adresa de portal dvs.",
|
||||
"PortalRenamingLabelText": "O nouă denumire de portal",
|
||||
|
@ -136,7 +136,7 @@
|
||||
"PortalIntegration": "Интеграция с порталом",
|
||||
"PortalNameEmpty": "Поле имя аккаунта не заполнено",
|
||||
"PortalNameIncorrect": "Неверное имя портала",
|
||||
"PortalNameLength": "Имя учетной записи должно быть от 3 до 50 символов",
|
||||
"PortalNameLength": "Имя учетной записи должно быть от {{minLength}} до {{maxLength}} символов",
|
||||
"PortalRenaming": "Изменение имени портала",
|
||||
"PortalRenamingDescription": "Здесь вы можете изменить адрес портала.",
|
||||
"PortalRenamingLabelText": "Новое имя портала",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Tu môžete vytvoriť pre používateľov bezpečné a pohodlné spôsoby prístupu na portál.",
|
||||
"PortalNameEmpty": "Názov účtu je prázdny",
|
||||
"PortalNameIncorrect": "Nesprávny názov účtu",
|
||||
"PortalNameLength": "Názov účtu musí mať 3 až 50 znakov",
|
||||
"PortalNameLength": "Názov účtu musí mať {{minLength}} až {{maxLength}} znakov",
|
||||
"PortalRenaming": "Premenovanie portálu",
|
||||
"PortalRenamingDescription": "Tu môžete zmeniť adresu portálu.",
|
||||
"PortalRenamingLabelText": "Nový názov portálu",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Ta razdelek omogoča uporabnikom varne in udobne načine za dostop do portala.",
|
||||
"PortalNameEmpty": "Ime računa je prazno",
|
||||
"PortalNameIncorrect": "Napačno ime računa",
|
||||
"PortalNameLength": "Ime računa mora imeti dolžino od 3 do 50 znakov",
|
||||
"PortalNameLength": "Ime računa mora imeti dolžino od {{minLength}} do {{maxLength}} znakov",
|
||||
"PortalRenaming": "Preimenovanje portala",
|
||||
"PortalRenamingDescription": "Tukaj lahko spremenite naslov vašega portala.",
|
||||
"PortalRenamingLabelText": "Novo ime portala",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Bu bölüm, kullanıcılara portala erişmeleri için güvenli ve uygun yollar sağlamanıza olanak tanır.",
|
||||
"PortalNameEmpty": "Hesap adı boş",
|
||||
"PortalNameIncorrect": "Yanlış hesap adı",
|
||||
"PortalNameLength": "Hesap adı 3 ila 50 karakter uzunluğunda olmalıdır",
|
||||
"PortalNameLength": "Hesap adı {{minLength}} ila {{maxLength}} karakter uzunluğunda olmalıdır",
|
||||
"PortalRenaming": "Portal Yeniden Adlandırma",
|
||||
"PortalRenamingDescription": "Buradan portal adresinizi değiştirebilirsiniz.",
|
||||
"PortalRenamingLabelText": "Yeni portal adı",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "У цьому розділі можна надати користувачам безпечні та зручні способи доступу до порталу.",
|
||||
"PortalNameEmpty": "Ім'я облікового запису порожнє",
|
||||
"PortalNameIncorrect": "Неправильне ім'я облікового запису",
|
||||
"PortalNameLength": "Довжина імені облікового запису має бути від 3 до 50 символів",
|
||||
"PortalNameLength": "Довжина імені облікового запису має бути від {{minLength}} до {{maxLength}} символів",
|
||||
"PortalRenaming": "Перейменування порталу",
|
||||
"PortalRenamingDescription": "Тут ви можете змінити адресу вашого порталу.",
|
||||
"PortalRenamingLabelText": "Нове ім'я порталу",
|
||||
|
@ -71,7 +71,7 @@
|
||||
"PortalAccessSubTitle": "Phần này cho phép bạn cung cấp cho người dùng những cách an toàn và thuận tiện để truy cập cổng thông tin.",
|
||||
"PortalNameEmpty": "Tên tài khoản trống",
|
||||
"PortalNameIncorrect": "Tên tài khoản không chính xác",
|
||||
"PortalNameLength": "Tên tài khoản phải dài từ 3 đến 50 ký tự",
|
||||
"PortalNameLength": "Tên tài khoản phải dài từ {{minLength}} đến {{maxLength}} ký tự",
|
||||
"PortalRenaming": "Đang đổi tên cổng",
|
||||
"PortalRenamingDescription": "Ở đây bạn có thể thay đổi địa chỉ cổng thông tin của bạn.",
|
||||
"PortalRenamingLabelText": "Tên cổng thông tin mới",
|
||||
|
@ -73,7 +73,7 @@
|
||||
"PortalAccessSubTitle": "这一部分允许您为用户提供安全又方便的方式来访问门户网站。",
|
||||
"PortalNameEmpty": "账户名称为空",
|
||||
"PortalNameIncorrect": "账户名称不正确",
|
||||
"PortalNameLength": "账户名称的长度必须在3至50个字符之间",
|
||||
"PortalNameLength": "账户名称的长度必须在{{minLength}}至{{maxLength}}个字符之间",
|
||||
"PortalRenaming": "门户重命名",
|
||||
"PortalRenamingDescription": "在此处,您可以更改您的门户地址。",
|
||||
"PortalRenamingLabelText": "新门户名称",
|
||||
|
@ -488,7 +488,7 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
|
||||
path={"/portal-settings"}
|
||||
component={PortalSettingsRoute}
|
||||
/>
|
||||
<PrivateRoute
|
||||
<PublicRoute
|
||||
path={"/preparation-portal"}
|
||||
component={PreparationPortalRoute}
|
||||
/>
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
} from "../dialogs";
|
||||
import ConvertPasswordDialog from "../dialogs/ConvertPasswordDialog";
|
||||
import ArchiveDialog from "../dialogs/ArchiveDialog";
|
||||
import PreparationPortalDialog from "../dialogs/PreparationPortalDialog";
|
||||
|
||||
const Panels = (props) => {
|
||||
const {
|
||||
@ -53,6 +54,7 @@ const Panels = (props) => {
|
||||
restoreAllPanelVisible,
|
||||
archiveDialogVisible,
|
||||
inviteUsersWarningDialogVisible,
|
||||
preparationPortalDialogVisible,
|
||||
} = props;
|
||||
|
||||
const { t } = useTranslation(["Translations", "Common"]);
|
||||
@ -119,11 +121,14 @@ const Panels = (props) => {
|
||||
inviteUsersWarningDialogVisible && (
|
||||
<InviteUsersWarningDialog key="invite-users-warning-dialog" />
|
||||
),
|
||||
preparationPortalDialogVisible && (
|
||||
<PreparationPortalDialog key="preparation-portal-dialog" />
|
||||
),
|
||||
];
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ auth, dialogsStore, uploadDataStore, versionHistoryStore }) => {
|
||||
({ auth, dialogsStore, uploadDataStore, versionHistoryStore, backup }) => {
|
||||
const {
|
||||
sharingPanelVisible,
|
||||
ownerPanelVisible,
|
||||
@ -151,11 +156,14 @@ export default inject(
|
||||
inviteUsersWarningDialogVisible,
|
||||
} = dialogsStore;
|
||||
|
||||
const { preparationPortalDialogVisible } = backup;
|
||||
|
||||
const { uploadPanelVisible } = uploadDataStore;
|
||||
const { isVisible: versionHistoryPanelVisible } = versionHistoryStore;
|
||||
const { hotkeyPanelVisible } = auth.settingsStore;
|
||||
|
||||
return {
|
||||
preparationPortalDialogVisible,
|
||||
sharingPanelVisible,
|
||||
uploadPanelVisible,
|
||||
ownerPanelVisible,
|
||||
|
@ -139,7 +139,6 @@ class NavMenu extends React.Component {
|
||||
asideContent,
|
||||
history,
|
||||
isDesktop,
|
||||
preparationPortalDialogVisible,
|
||||
isFrame,
|
||||
showHeader,
|
||||
} = this.props;
|
||||
@ -188,7 +187,6 @@ class NavMenu extends React.Component {
|
||||
{asideContent}
|
||||
</Aside>
|
||||
)}
|
||||
{preparationPortalDialogVisible && <PreparationPortalDialog />}
|
||||
</StyledContainer>
|
||||
)}
|
||||
</LayoutContextConsumer>
|
||||
@ -220,16 +218,16 @@ NavMenu.defaultProps = {
|
||||
isDesktop: false,
|
||||
};
|
||||
|
||||
const NavMenuWrapper = inject(({ auth, backup }) => {
|
||||
const NavMenuWrapper = inject(({ auth }) => {
|
||||
const { settingsStore, isAuthenticated, isLoaded, language } = auth;
|
||||
const { isDesktopClient: isDesktop, frameConfig, isFrame } = settingsStore;
|
||||
const { preparationPortalDialogVisible } = backup;
|
||||
|
||||
return {
|
||||
isAuthenticated,
|
||||
isLoaded,
|
||||
isDesktop,
|
||||
language,
|
||||
preparationPortalDialogVisible,
|
||||
|
||||
showHeader: frameConfig?.showHeader,
|
||||
isFrame,
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ const StyledPreparationPortalDialog = styled.div`
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.preparation-portal_body-wrapper {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -15,10 +15,9 @@ const PreparationPortalDialog = (props) => {
|
||||
isLoading={!tReady}
|
||||
visible={preparationPortalVisible}
|
||||
onClose={onClose}
|
||||
contentHeight="388px"
|
||||
contentWidth="520px"
|
||||
displayType="modal"
|
||||
withoutCloseButton
|
||||
isCloseable={false}
|
||||
isLarge
|
||||
>
|
||||
<ModalDialog.Header>{t("PortalRestoring")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
|
@ -538,7 +538,7 @@ class SharingPanelComponent extends React.Component {
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={true}
|
||||
isCloseable={false}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
@ -554,7 +554,7 @@ class SharingPanelComponent extends React.Component {
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={true}
|
||||
isCloseable={false}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
@ -572,7 +572,6 @@ class SharingPanelComponent extends React.Component {
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={false}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
@ -633,7 +632,6 @@ class SharingPanelComponent extends React.Component {
|
||||
<ModalDialog
|
||||
displayType="modal"
|
||||
visible={visible}
|
||||
withoutCloseButton={false}
|
||||
withoutBodyScroll={true}
|
||||
scale={true}
|
||||
onClose={this.onClose}
|
||||
|
@ -31,6 +31,7 @@ const PortalRenaming = (props) => {
|
||||
tenantAlias,
|
||||
initSettings,
|
||||
setIsLoaded,
|
||||
getAllSettings,
|
||||
} = props;
|
||||
|
||||
const portalNameFromSessionStorage = getFromSessionStorage("portalName");
|
||||
@ -71,6 +72,14 @@ const PortalRenaming = (props) => {
|
||||
|
||||
const [isCustomizationView, setIsCustomizationView] = useState(false);
|
||||
|
||||
const [domainValidator, setDomainValidator] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
getAllSettings().then((res) => {
|
||||
setDomainValidator(res.domainValidator);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("PortalRenaming"));
|
||||
if (!isLoaded) initSettings().then(() => setIsLoaded(true));
|
||||
@ -174,16 +183,28 @@ const PortalRenaming = (props) => {
|
||||
};
|
||||
|
||||
const onValidateInput = (value) => {
|
||||
const validDomain = new RegExp("^[a-z0-9]([a-z0-9-]){1,98}[a-z0-9]$", "i");
|
||||
const validDomain = new RegExp(domainValidator.regex);
|
||||
|
||||
switch (true) {
|
||||
case value === "":
|
||||
setErrorValue(t("PortalNameEmpty"));
|
||||
saveToSessionStorage("errorValue", t("PortalNameEmpty"));
|
||||
break;
|
||||
case value.length < 3 || value.length > 50:
|
||||
setErrorValue(t("PortalNameLength"));
|
||||
saveToSessionStorage("errorValue", t("PortalNameLength"));
|
||||
case value.length < domainValidator.minLength ||
|
||||
value.length > domainValidator.maxLength:
|
||||
setErrorValue(
|
||||
t("PortalNameLength", {
|
||||
minLength: domainValidator.minLength,
|
||||
maxLength: domainValidator.maxLength,
|
||||
})
|
||||
);
|
||||
saveToSessionStorage(
|
||||
"errorValue",
|
||||
t("PortalNameLength", {
|
||||
minLength: domainValidator.minLength,
|
||||
maxLength: domainValidator.maxLength,
|
||||
})
|
||||
);
|
||||
break;
|
||||
case !validDomain.test(value):
|
||||
setErrorValue(t("PortalNameIncorrect"));
|
||||
@ -305,7 +326,7 @@ const PortalRenaming = (props) => {
|
||||
|
||||
export default inject(({ auth, setup, common }) => {
|
||||
const { theme, tenantAlias } = auth.settingsStore;
|
||||
const { setPortalRename } = setup;
|
||||
const { setPortalRename, getAllSettings } = setup;
|
||||
const {
|
||||
isLoaded,
|
||||
setIsLoadedPortalRenaming,
|
||||
@ -320,6 +341,7 @@ export default inject(({ auth, setup, common }) => {
|
||||
tenantAlias,
|
||||
initSettings,
|
||||
setIsLoaded,
|
||||
getAllSettings,
|
||||
};
|
||||
})(
|
||||
withLoading(withTranslation(["Settings", "Common"])(observer(PortalRenaming)))
|
||||
|
@ -8,7 +8,7 @@ import { isMobileOnly } from "react-device-detect";
|
||||
import { mobile } from "@docspace/components/utils/device";
|
||||
|
||||
const linkColor = globalColors.black;
|
||||
const borderColor = globalColors.grayLightMid;
|
||||
|
||||
const INPUT_LENGTH = "350px";
|
||||
const TEXT_LENGTH = "700px";
|
||||
const commonStyles = css`
|
||||
@ -452,40 +452,11 @@ const StyledBackupList = styled.div`
|
||||
margin-right: 16px;
|
||||
color: ${(props) => props.theme.client.settings.backup.textColor};
|
||||
}
|
||||
#backup-list_help {
|
||||
display: flex;
|
||||
background-color: ${(props) => props.theme.backgroundColor};
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.backup-list_tooltip {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.backup-list_content {
|
||||
display: grid;
|
||||
height: calc(100% - 32px);
|
||||
height: 100%;
|
||||
grid-template-rows: max-content auto max-content;
|
||||
.backup-list_agreement-text {
|
||||
user-select: none;
|
||||
div:first-child {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.backup-list_footer {
|
||||
padding: 16px 16px 0 16px;
|
||||
${(props) => !props.isEmpty && `border-top: 1px solid ${borderColor}`};
|
||||
margin-left: -16px;
|
||||
margin-right: -16px;
|
||||
.restore_dialog-button {
|
||||
display: flex;
|
||||
button:first-child {
|
||||
margin-right: 10px;
|
||||
width: 50%;
|
||||
}
|
||||
button:last-child {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
const StyledSettingsHeader = styled.div`
|
||||
|
@ -8,7 +8,7 @@ import RadioButton from "@docspace/components/radio-button";
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
import { startRestore } from "@docspace/common/api/portal";
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import { BackupStorageType } from "@docspace/common/constants";
|
||||
import { BackupStorageType, TenantStatus } from "@docspace/common/constants";
|
||||
import { request } from "@docspace/common/api/client";
|
||||
import { StyledRestoreBackup } from "./../StyledBackup";
|
||||
import BackupListModalDialog from "./sub-components/backup-list";
|
||||
@ -39,10 +39,10 @@ class RestoreBackup extends React.Component {
|
||||
isNotify: true,
|
||||
isVisibleDialog: false,
|
||||
isPanelVisible: false,
|
||||
isCheckedDocuments: true,
|
||||
isCheckedDocuments: false,
|
||||
isCheckedThirdParty: false,
|
||||
isCheckedThirdPartyStorage: false,
|
||||
isCheckedLocalFile: false,
|
||||
isCheckedLocalFile: true,
|
||||
selectedFileId: "",
|
||||
selectedFile: "",
|
||||
|
||||
@ -187,7 +187,12 @@ class RestoreBackup extends React.Component {
|
||||
isCheckedThirdPartyStorage,
|
||||
isCheckedThirdParty,
|
||||
} = this.state;
|
||||
const { history, socketHelper, getStorageParams } = this.props;
|
||||
const {
|
||||
history,
|
||||
socketHelper,
|
||||
getStorageParams,
|
||||
setTenantStatus,
|
||||
} = this.props;
|
||||
|
||||
if (!this.canRestore()) {
|
||||
this.setState({
|
||||
@ -251,6 +256,7 @@ class RestoreBackup extends React.Component {
|
||||
}
|
||||
|
||||
startRestore(backupId, storageType, storageParams, isNotify)
|
||||
.then(() => setTenantStatus(TenantStatus.PortalRestore))
|
||||
.then(() => {
|
||||
socketHelper.emit({
|
||||
command: "restore-backup",
|
||||
@ -324,6 +330,16 @@ class RestoreBackup extends React.Component {
|
||||
{t("RestoreBackupDescription")}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<RadioButton
|
||||
label={t("LocalFile")}
|
||||
name={"isCheckedLocalFile"}
|
||||
key={4}
|
||||
isChecked={isCheckedLocalFile}
|
||||
isDisabled={!isEnableRestore}
|
||||
{...commonRadioButtonProps}
|
||||
/>
|
||||
|
||||
<RadioButton
|
||||
label={t("RoomsModule")}
|
||||
name={"isCheckedDocuments"}
|
||||
@ -351,15 +367,6 @@ class RestoreBackup extends React.Component {
|
||||
{...commonRadioButtonProps}
|
||||
/>
|
||||
|
||||
<RadioButton
|
||||
label={t("LocalFile")}
|
||||
name={"isCheckedLocalFile"}
|
||||
key={4}
|
||||
isChecked={isCheckedLocalFile}
|
||||
isDisabled={!isEnableRestore}
|
||||
{...commonRadioButtonProps}
|
||||
/>
|
||||
|
||||
<div className="restore-backup_modules">
|
||||
{isCheckedDocuments && (
|
||||
<RoomsModule
|
||||
@ -480,7 +487,7 @@ class RestoreBackup extends React.Component {
|
||||
|
||||
export default inject(({ auth, backup }) => {
|
||||
const { settingsStore, currentQuotaStore } = auth;
|
||||
const { socketHelper, theme, isTabletView } = settingsStore;
|
||||
const { socketHelper, theme, isTabletView, setTenantStatus } = settingsStore;
|
||||
const {
|
||||
downloadingProgress,
|
||||
getProgress,
|
||||
@ -495,6 +502,7 @@ export default inject(({ auth, backup }) => {
|
||||
const buttonSize = isTabletView ? "normal" : "small";
|
||||
const { isRestoreAndAutoBackupAvailable } = currentQuotaStore;
|
||||
return {
|
||||
setTenantStatus,
|
||||
isEnableRestore: isRestoreAndAutoBackupAvailable,
|
||||
setStorageRegions,
|
||||
setThirdPartyStorage,
|
||||
|
@ -21,6 +21,40 @@ import HelpButton from "@docspace/components/help-button";
|
||||
import config from "PACKAGE_FILE";
|
||||
import { StyledBackupList } from "../../../StyledBackup";
|
||||
import BackupListBody from "./BackupListBody";
|
||||
import { TenantStatus } from "@docspace/common/constants";
|
||||
import styled from "styled-components";
|
||||
|
||||
const StyledModalDialog = styled(ModalDialog)`
|
||||
.restore_footer {
|
||||
width: 100%;
|
||||
.restore_dialog-button {
|
||||
display: flex;
|
||||
button:first-child {
|
||||
margin-right: 10px;
|
||||
width: 50%;
|
||||
}
|
||||
button:last-child {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
#backup-list_help {
|
||||
display: flex;
|
||||
background-color: ${(props) => props.theme.backgroundColor};
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.backup-list_agreement-text {
|
||||
user-select: none;
|
||||
div:first-child {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.backup-list_tooltip {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
class BackupListModalDialog extends React.Component {
|
||||
constructor(props) {
|
||||
@ -89,7 +123,7 @@ class BackupListModalDialog extends React.Component {
|
||||
};
|
||||
onRestorePortal = () => {
|
||||
const { selectedFileId } = this.state;
|
||||
const { isNotify, history, socketHelper, t } = this.props;
|
||||
const { isNotify, history, socketHelper, t, setTenantStatus } = this.props;
|
||||
|
||||
if (!selectedFileId) {
|
||||
toastr.error(t("RecoveryFileNotSelected"));
|
||||
@ -106,6 +140,7 @@ class BackupListModalDialog extends React.Component {
|
||||
];
|
||||
|
||||
startRestore(backupId, storageType, storageParams, isNotify)
|
||||
.then(() => setTenantStatus(TenantStatus.PortalRestore))
|
||||
.then(() => {
|
||||
socketHelper.emit({
|
||||
command: "restore-backup",
|
||||
@ -159,15 +194,17 @@ class BackupListModalDialog extends React.Component {
|
||||
);
|
||||
|
||||
return (
|
||||
<ModalDialog
|
||||
<StyledModalDialog
|
||||
displayType="aside"
|
||||
visible={isVisibleDialog}
|
||||
onClose={onModalClose}
|
||||
displayType="aside"
|
||||
withoutBodyScroll
|
||||
contentHeight="100%"
|
||||
contentPaddingBottom="0px"
|
||||
withFooterBorder
|
||||
>
|
||||
<ModalDialog.Header>{t("BackupList")}</ModalDialog.Header>
|
||||
<ModalDialog.Header>
|
||||
<Text fontSize="21px" fontWeight={700}>
|
||||
{t("BackupList")}
|
||||
</Text>
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<StyledBackupList
|
||||
isCopyingToLocal={isCopyingToLocal}
|
||||
@ -210,53 +247,52 @@ class BackupListModalDialog extends React.Component {
|
||||
)
|
||||
) : (
|
||||
<div className="loader" key="loader">
|
||||
<Loaders.ListLoader />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="backup-list_footer">
|
||||
{filesList.length > 0 && (
|
||||
<div>
|
||||
<div id="backup-list_help">
|
||||
<Checkbox
|
||||
truncate
|
||||
className="backup-list_checkbox"
|
||||
onChange={this.onChangeCheckbox}
|
||||
isChecked={isChecked}
|
||||
/>
|
||||
<Text as="span" className="backup-list_agreement-text">
|
||||
{t("UserAgreement")}
|
||||
<HelpButton
|
||||
className="backup-list_tooltip"
|
||||
offsetLeft={100}
|
||||
iconName={HelpReactSvgUrl}
|
||||
getContent={helpContent}
|
||||
tooltipMaxWidth={"286px"}
|
||||
/>
|
||||
</Text>
|
||||
</div>
|
||||
<div className="restore_dialog-button">
|
||||
<Button
|
||||
primary
|
||||
size="normal"
|
||||
label={t("Common:Restore")}
|
||||
onClick={this.onRestorePortal}
|
||||
isDisabled={isCopyingToLocal || !isChecked}
|
||||
/>
|
||||
<Button
|
||||
size="normal"
|
||||
label={t("Common:CloseButton")}
|
||||
onClick={onModalClose}
|
||||
/>
|
||||
</div>
|
||||
<Loaders.ListLoader count={7} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</StyledBackupList>
|
||||
</ModalDialog.Body>
|
||||
</ModalDialog>
|
||||
|
||||
<ModalDialog.Footer>
|
||||
<div className="restore_footer">
|
||||
<div id="backup-list_help">
|
||||
<Checkbox
|
||||
truncate
|
||||
className="backup-list_checkbox"
|
||||
onChange={this.onChangeCheckbox}
|
||||
isChecked={isChecked}
|
||||
/>
|
||||
<Text as="span" className="backup-list_agreement-text">
|
||||
{t("UserAgreement")}
|
||||
<HelpButton
|
||||
className="backup-list_tooltip"
|
||||
offsetLeft={100}
|
||||
iconName={HelpReactSvgUrl}
|
||||
getContent={helpContent}
|
||||
tooltipMaxWidth={"286px"}
|
||||
/>
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="restore_dialog-button">
|
||||
<Button
|
||||
primary
|
||||
size="normal"
|
||||
label={t("Common:Restore")}
|
||||
onClick={this.onRestorePortal}
|
||||
isDisabled={isCopyingToLocal || !isChecked}
|
||||
/>
|
||||
<Button
|
||||
size="normal"
|
||||
label={t("Common:CloseButton")}
|
||||
onClick={onModalClose}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ModalDialog.Footer>
|
||||
</StyledModalDialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -268,9 +304,10 @@ BackupListModalDialog.propTypes = {
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore } = auth;
|
||||
const { socketHelper, theme } = settingsStore;
|
||||
const { socketHelper, theme, setTenantStatus } = settingsStore;
|
||||
|
||||
return {
|
||||
setTenantStatus,
|
||||
theme,
|
||||
socketHelper,
|
||||
};
|
||||
|
@ -17,6 +17,24 @@ const StyledPreparationPortal = styled.div`
|
||||
line-height: 20px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.preparation-portal_body-wrapper {
|
||||
margin-bottom: 24px;
|
||||
width: 100%;
|
||||
max-width: ${(props) => (props.errorMessage ? "560px" : "480px")};
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
.preparation-portal_error {
|
||||
text-align: center;
|
||||
color: ${(props) => props.theme.preparationPortalProgress.errorTextColor};
|
||||
}
|
||||
|
||||
.preparation-portal_text {
|
||||
text-align: center;
|
||||
color: ${(props) =>
|
||||
props.theme.preparationPortalProgress.descriptionTextColor};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export { StyledPreparationPortal };
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import ErrorContainer from "@docspace/common/components/ErrorContainer";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
@ -14,233 +14,237 @@ const unSizeMultiplicationFactor = 3;
|
||||
const baseFirstMultiplicationFactor = 700;
|
||||
const baseSecondMultiplicationFactor = 400;
|
||||
const baseThirdMultiplicationFactor = 180;
|
||||
const firstBound = 10,
|
||||
secondBound = 63,
|
||||
thirdBound = 98;
|
||||
|
||||
class PreparationPortal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
percent: 0,
|
||||
errorMessage: "",
|
||||
firstBound: 10,
|
||||
secondBound: 63,
|
||||
let timerId = null,
|
||||
progressTimerId = null,
|
||||
prevProgress;
|
||||
|
||||
const PreparationPortal = (props) => {
|
||||
const {
|
||||
multiplicationFactor,
|
||||
t,
|
||||
withoutHeader,
|
||||
style,
|
||||
clearLocalStorage,
|
||||
} = props;
|
||||
|
||||
const [percent, setPercent] = useState(0);
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
|
||||
const clearAllIntervals = () => {
|
||||
clearInterval(timerId);
|
||||
clearInterval(progressTimerId);
|
||||
|
||||
progressTimerId = null;
|
||||
timerId = null;
|
||||
};
|
||||
|
||||
const returnToPortal = () => {
|
||||
setTimeout(() => {
|
||||
window.location.replace("/");
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
const reachingFirstBoundary = (percent) => {
|
||||
let progress = percent;
|
||||
const delay = baseFirstMultiplicationFactor * multiplicationFactor;
|
||||
|
||||
if (progressTimerId) return;
|
||||
|
||||
progressTimerId = setInterval(() => {
|
||||
progress += 1;
|
||||
|
||||
if (progress !== firstBound) setPercent(progress);
|
||||
else {
|
||||
clearInterval(progressTimerId);
|
||||
progressTimerId = null;
|
||||
}
|
||||
}, delay);
|
||||
};
|
||||
const reachingSecondBoundary = (percent) => {
|
||||
let progress = percent;
|
||||
|
||||
const delay = baseSecondMultiplicationFactor * multiplicationFactor;
|
||||
|
||||
if (progressTimerId) return;
|
||||
|
||||
progressTimerId = setInterval(() => {
|
||||
progress += 1;
|
||||
|
||||
if (progress !== secondBound) setPercent(progress);
|
||||
else {
|
||||
clearInterval(progressTimerId);
|
||||
progressTimerId = null;
|
||||
}
|
||||
}, delay);
|
||||
};
|
||||
|
||||
const reachingThirdBoundary = (percent) => {
|
||||
let progress = percent;
|
||||
const delay = baseThirdMultiplicationFactor * multiplicationFactor;
|
||||
if (progressTimerId) return;
|
||||
|
||||
progressTimerId = setInterval(() => {
|
||||
progress += 1;
|
||||
|
||||
if (progress < thirdBound) setPercent(progress);
|
||||
else {
|
||||
clearInterval(progressTimerId);
|
||||
progressTimerId = null;
|
||||
}
|
||||
}, delay);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (percent >= firstBound) {
|
||||
if (percent < secondBound) {
|
||||
reachingSecondBoundary(percent);
|
||||
return;
|
||||
} else reachingThirdBoundary(percent);
|
||||
}
|
||||
}, [percent]);
|
||||
|
||||
const getIntervalProgress = async () => {
|
||||
try {
|
||||
const response = await getRestoreProgress();
|
||||
|
||||
if (!response) {
|
||||
setErrorMessage(t("Common:ErrorInternalServer"));
|
||||
clearAllIntervals();
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.error) {
|
||||
clearInterval(timerId);
|
||||
clearInterval(progressTimerId);
|
||||
|
||||
progressTimerId = null;
|
||||
timerId = null;
|
||||
setErrorMessage(response.error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const currProgress = response.progress;
|
||||
|
||||
if (currProgress > 0 && prevProgress !== currProgress) {
|
||||
setPercent(currProgress);
|
||||
|
||||
clearInterval(progressTimerId);
|
||||
progressTimerId = null;
|
||||
}
|
||||
|
||||
prevProgress = currProgress;
|
||||
|
||||
if (currProgress === 100) {
|
||||
clearAllIntervals();
|
||||
clearLocalStorage();
|
||||
returnToPortal();
|
||||
}
|
||||
} catch (error) {
|
||||
clearAllIntervals();
|
||||
setErrorMessage(error);
|
||||
}
|
||||
};
|
||||
|
||||
const getRecoveryProgress = async () => {
|
||||
const errorMessage = (error) => {
|
||||
if (typeof error !== "object") return error;
|
||||
|
||||
return (
|
||||
err?.response?.data?.error?.message ||
|
||||
err?.statusText ||
|
||||
err?.message ||
|
||||
t("Common:ErrorInternalServer")
|
||||
);
|
||||
};
|
||||
this.timerId = null;
|
||||
this.progressTimerId = null;
|
||||
}
|
||||
componentDidMount() {
|
||||
getRestoreProgress()
|
||||
.then((response) => {
|
||||
if (response) {
|
||||
if (!response.error) {
|
||||
if (response.progress === 100)
|
||||
this.setState({
|
||||
percent: 100,
|
||||
});
|
||||
if (response.progress !== 100) {
|
||||
this.timerId = setInterval(() => this.getProgress(), 1000);
|
||||
this.progressInitiationFirstBound();
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
errorMessage: response.error,
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
let errorMessage = "";
|
||||
if (typeof err === "object") {
|
||||
errorMessage =
|
||||
err?.response?.data?.error?.message ||
|
||||
err?.statusText ||
|
||||
err?.message ||
|
||||
"";
|
||||
} else {
|
||||
errorMessage = err;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
errorMessage: errorMessage,
|
||||
});
|
||||
});
|
||||
}
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.timerId);
|
||||
clearInterval(this.progressTimerId);
|
||||
}
|
||||
try {
|
||||
const response = await getRestoreProgress();
|
||||
|
||||
progressInitiationFirstBound = () => {
|
||||
const { multiplicationFactor } = this.props;
|
||||
const { percent, firstBound } = this.state;
|
||||
if (!response) {
|
||||
setErrorMessage(t("Common:ErrorInternalServer"));
|
||||
return;
|
||||
}
|
||||
const { error, progress } = response;
|
||||
|
||||
let progress = percent;
|
||||
if (error) {
|
||||
setErrorMessage(response.error);
|
||||
|
||||
const common = baseFirstMultiplicationFactor * multiplicationFactor;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.progressTimerId)
|
||||
this.progressTimerId = setInterval(() => {
|
||||
progress += 1;
|
||||
if (progress !== firstBound && percent < progress)
|
||||
percent < progress &&
|
||||
this.setState({
|
||||
percent: progress,
|
||||
});
|
||||
else {
|
||||
clearInterval(this.progressTimerId);
|
||||
this.progressTimerId = null;
|
||||
}
|
||||
}, common);
|
||||
if (progress === 100) {
|
||||
returnToPortal();
|
||||
clearLocalStorage();
|
||||
} else {
|
||||
timerId = setInterval(() => getIntervalProgress(), 1000);
|
||||
if (progress < firstBound) reachingFirstBoundary(progress);
|
||||
}
|
||||
|
||||
setPercent(progress);
|
||||
} catch (err) {
|
||||
setErrorMessage(errorMessage(err));
|
||||
}
|
||||
};
|
||||
progressInitiationSecondBound = () => {
|
||||
const { multiplicationFactor } = this.props;
|
||||
const { percent, secondBound } = this.state;
|
||||
useEffect(async () => {
|
||||
setTimeout(() => {
|
||||
getRecoveryProgress();
|
||||
}, 4000);
|
||||
|
||||
let progress = percent;
|
||||
return () => {
|
||||
clearAllIntervals();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const common = baseSecondMultiplicationFactor * multiplicationFactor;
|
||||
const headerText = errorMessage
|
||||
? t("Common:Error")
|
||||
: t("Common:PreparationPortalTitle");
|
||||
|
||||
if (!this.progressTimerId)
|
||||
this.progressTimerId = setInterval(() => {
|
||||
progress += 1;
|
||||
if (progress !== secondBound)
|
||||
percent < progress &&
|
||||
this.setState({
|
||||
percent: progress,
|
||||
});
|
||||
else {
|
||||
clearInterval(this.progressTimerId);
|
||||
this.progressTimerId = null;
|
||||
}
|
||||
}, common);
|
||||
};
|
||||
|
||||
progressInitiationThirdBound = () => {
|
||||
const { multiplicationFactor } = this.props;
|
||||
const { percent } = this.state;
|
||||
let progress = percent;
|
||||
const common = baseThirdMultiplicationFactor * multiplicationFactor;
|
||||
if (!this.progressTimerId)
|
||||
this.progressTimerId = setInterval(() => {
|
||||
progress += 1;
|
||||
|
||||
if (progress < 98)
|
||||
percent < progress &&
|
||||
this.setState({
|
||||
percent: progress,
|
||||
});
|
||||
else {
|
||||
clearInterval(this.progressTimerId);
|
||||
this.progressTimerId = null;
|
||||
}
|
||||
}, common);
|
||||
};
|
||||
getProgress = () => {
|
||||
const { secondBound } = this.state;
|
||||
getRestoreProgress()
|
||||
.then((response) => {
|
||||
if (response) {
|
||||
if (!response.error) {
|
||||
const percentProgress = response.progress;
|
||||
|
||||
percentProgress !== this.state.percent &&
|
||||
this.state.percent < percentProgress &&
|
||||
this.setState(
|
||||
{
|
||||
percent: percentProgress,
|
||||
},
|
||||
() => {
|
||||
clearInterval(this.progressTimerId);
|
||||
this.progressTimerId = null;
|
||||
|
||||
if (percentProgress < secondBound) {
|
||||
this.progressInitiationSecondBound();
|
||||
} else {
|
||||
this.progressInitiationThirdBound();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (percentProgress === 100) {
|
||||
clearInterval(this.timerId);
|
||||
clearInterval(this.progressTimerId);
|
||||
|
||||
this.progressTimerId = null;
|
||||
this.timerId = null;
|
||||
}
|
||||
} else {
|
||||
clearInterval(this.timerId);
|
||||
clearInterval(this.progressTimerId);
|
||||
|
||||
this.progressTimerId = null;
|
||||
this.timerId = null;
|
||||
|
||||
this.setState({
|
||||
errorMessage: response.error,
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
clearInterval(this.timerId);
|
||||
clearInterval(this.progressTimerId);
|
||||
|
||||
this.progressTimerId = null;
|
||||
this.timerId = null;
|
||||
|
||||
this.setState({
|
||||
percent: 100,
|
||||
});
|
||||
});
|
||||
};
|
||||
render() {
|
||||
const { t, withoutHeader, style } = this.props;
|
||||
const { percent, errorMessage } = this.state;
|
||||
|
||||
return (
|
||||
<StyledPreparationPortal>
|
||||
<ErrorContainer
|
||||
headerText={withoutHeader ? "" : t("Common:PreparationPortalTitle")}
|
||||
style={style}
|
||||
>
|
||||
<ColorTheme
|
||||
themeId={ThemeType.Progress}
|
||||
percent={percent}
|
||||
errorMessage={errorMessage}
|
||||
className="preparation-portal_body-wrapper"
|
||||
>
|
||||
{errorMessage ? (
|
||||
<Text
|
||||
className="preparation-portal_error"
|
||||
color="#F21C0E"
|
||||
>{`${errorMessage}`}</Text>
|
||||
) : (
|
||||
<>
|
||||
<div className="preparation-portal_progress">
|
||||
<div className="preparation-portal_progress-bar">
|
||||
<div className="preparation-portal_progress-line"></div>
|
||||
</div>
|
||||
<Text className="preparation-portal_percent">{`${percent} %`}</Text>
|
||||
return (
|
||||
<StyledPreparationPortal errorMessage={errorMessage}>
|
||||
<ErrorContainer
|
||||
headerText={withoutHeader ? "" : headerText}
|
||||
style={style}
|
||||
>
|
||||
<div className="preparation-portal_body-wrapper">
|
||||
{errorMessage ? (
|
||||
<Text className="preparation-portal_error">{`${errorMessage}`}</Text>
|
||||
) : (
|
||||
<ColorTheme
|
||||
themeId={ThemeType.Progress}
|
||||
percent={percent}
|
||||
errorMessage={errorMessage}
|
||||
className="preparation-portal_body-wrapper"
|
||||
>
|
||||
<div className="preparation-portal_progress">
|
||||
<div className="preparation-portal_progress-bar">
|
||||
<div className="preparation-portal_progress-line"></div>
|
||||
</div>
|
||||
<Text className="preparation-portal_text">
|
||||
{t("PreparationPortalDescription")}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</ColorTheme>
|
||||
</ErrorContainer>
|
||||
</StyledPreparationPortal>
|
||||
);
|
||||
}
|
||||
}
|
||||
<Text className="preparation-portal_percent">{`${percent} %`}</Text>
|
||||
</div>
|
||||
<Text className="preparation-portal_text">
|
||||
{t("PreparationPortalDescription")}
|
||||
</Text>
|
||||
</ColorTheme>
|
||||
)}
|
||||
</div>
|
||||
</ErrorContainer>
|
||||
</StyledPreparationPortal>
|
||||
);
|
||||
};
|
||||
|
||||
const PreparationPortalWrapper = inject(({ backup }) => {
|
||||
const { backupSize } = backup;
|
||||
const { backupSize, clearLocalStorage } = backup;
|
||||
|
||||
const multiplicationFactor = backupSize
|
||||
? backupSize / baseSize
|
||||
: unSizeMultiplicationFactor;
|
||||
|
||||
return {
|
||||
clearLocalStorage,
|
||||
multiplicationFactor,
|
||||
};
|
||||
})(
|
||||
|
@ -73,7 +73,7 @@ export const WizardContainer = styled.div`
|
||||
}
|
||||
|
||||
.password-field {
|
||||
margin: 0 0 10px 0 !important;
|
||||
margin: 0px !important;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -82,7 +82,8 @@ export const StyledLink = styled.div`
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
padding-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
padding-top: 8px;
|
||||
|
||||
.generate-password-link {
|
||||
color: ${(props) => props.theme.client.wizard.generatePasswordColor};
|
||||
@ -98,14 +99,21 @@ export const StyledLink = styled.div`
|
||||
export const StyledInfo = styled.div`
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 83px 1fr;
|
||||
grid-template-columns: 59px 1fr;
|
||||
align-items: center;
|
||||
padding-bottom: 4px;
|
||||
gap: 16px;
|
||||
|
||||
margin-bottom: 4px;
|
||||
|
||||
.machine-name {
|
||||
padding-bottom: 4px;
|
||||
padding-top: 4px;
|
||||
padding-left: 16px;
|
||||
padding-left: 8px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.combo-button {
|
||||
padding-left: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -114,7 +122,7 @@ export const StyledAcceptTerms = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3em;
|
||||
padding-top: 12px;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 24px;
|
||||
|
||||
.wizard-checkbox svg {
|
||||
|
@ -326,6 +326,7 @@ const Wizard = (props) => {
|
||||
{t("Common:Language")}
|
||||
</Text>
|
||||
<ComboBox
|
||||
withoutPadding
|
||||
directionY="both"
|
||||
options={cultureNames}
|
||||
selectedOption={selectedLanguage}
|
||||
@ -348,6 +349,7 @@ const Wizard = (props) => {
|
||||
{t("Timezone")}
|
||||
</Text>
|
||||
<ComboBox
|
||||
withoutPadding
|
||||
directionY="both"
|
||||
options={timezones}
|
||||
selectedOption={selectedTimezone}
|
||||
|
@ -367,6 +367,10 @@ class SettingsSetupStore {
|
||||
return api.settings.removeActiveSession(id);
|
||||
};
|
||||
|
||||
getAllSettings = () => {
|
||||
return api.settings.getSettings();
|
||||
};
|
||||
|
||||
setLogoutVisible = (visible) => (this.logoutVisible = visible);
|
||||
|
||||
setLogoutAllVisible = (visible) => (this.logoutAllVisible = visible);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import styled, { css } from "styled-components";
|
||||
import StyledBodyPreparationPortal from "../../StyledBodyPreparationPortal";
|
||||
import StyledPreparationPortalProgress from "../../StyledPreparationPortalProgress";
|
||||
import Base from "@docspace/components/themes/base";
|
||||
|
||||
const getDefaultStyles = ({ $currentColorScheme, theme }) =>
|
||||
@ -10,6 +10,6 @@ const getDefaultStyles = ({ $currentColorScheme, theme }) =>
|
||||
}
|
||||
`;
|
||||
|
||||
StyledBodyPreparationPortal.defaultProps = { theme: Base };
|
||||
StyledPreparationPortalProgress.defaultProps = { theme: Base };
|
||||
|
||||
export default styled(StyledBodyPreparationPortal)(getDefaultStyles);
|
||||
export default styled(StyledPreparationPortalProgress)(getDefaultStyles);
|
||||
|
@ -136,10 +136,7 @@ const PrivateRoute = ({ component: Component, ...rest }) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (tenantStatus !== TenantStatus.PortalRestore && isPortalUrl) {
|
||||
return window.location.replace("/");
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
isNotPaidPeriod &&
|
||||
isLoaded &&
|
||||
|
@ -3,15 +3,26 @@ import React from "react";
|
||||
import { Redirect, Route } from "react-router-dom";
|
||||
import AppLoader from "../AppLoader";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { TenantStatus } from "../../constants";
|
||||
|
||||
export const PublicRoute = ({ component: Component, ...rest }) => {
|
||||
const { wizardCompleted, isAuthenticated, isLoaded, personal } = rest;
|
||||
const {
|
||||
wizardCompleted,
|
||||
isAuthenticated,
|
||||
isLoaded,
|
||||
personal,
|
||||
tenantStatus,
|
||||
} = rest;
|
||||
const renderComponent = (props) => {
|
||||
const isPreparationPortalUrl =
|
||||
props.location.pathname === "/preparation-portal";
|
||||
const isPortalRestoring = tenantStatus === TenantStatus.PortalRestore;
|
||||
|
||||
if (!isLoaded) {
|
||||
return <AppLoader />;
|
||||
}
|
||||
|
||||
if (isAuthenticated || personal) {
|
||||
if (personal) {
|
||||
return (
|
||||
<Redirect
|
||||
to={{
|
||||
@ -22,6 +33,31 @@ export const PublicRoute = ({ component: Component, ...rest }) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (isAuthenticated && !isPortalRestoring) {
|
||||
return (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: "/",
|
||||
state: { from: props.location },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isAuthenticated && isPortalRestoring && !isPreparationPortalUrl) {
|
||||
return (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
"/preparation-portal"
|
||||
),
|
||||
state: { from: props.location },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!wizardCompleted && props.location.pathname !== "/wizard") {
|
||||
return (
|
||||
<Redirect
|
||||
@ -33,6 +69,28 @@ export const PublicRoute = ({ component: Component, ...rest }) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!isAuthenticated &&
|
||||
isPortalRestoring &&
|
||||
wizardCompleted &&
|
||||
!isPreparationPortalUrl
|
||||
) {
|
||||
return (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
"/preparation-portal"
|
||||
),
|
||||
state: { from: props.location },
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (wizardCompleted && !isAuthenticated && !isPortalRestoring)
|
||||
return window.location.replace("/login");
|
||||
|
||||
return <Component {...props} {...rest} />;
|
||||
};
|
||||
return <Route {...rest} render={renderComponent} />;
|
||||
@ -40,9 +98,10 @@ export const PublicRoute = ({ component: Component, ...rest }) => {
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore, isAuthenticated, isLoaded } = auth;
|
||||
const { wizardCompleted, personal } = settingsStore;
|
||||
const { wizardCompleted, personal, tenantStatus } = settingsStore;
|
||||
|
||||
return {
|
||||
tenantStatus,
|
||||
wizardCompleted,
|
||||
isAuthenticated,
|
||||
isLoaded,
|
||||
|
@ -1,13 +1,7 @@
|
||||
import styled from "styled-components";
|
||||
import { Base } from "@docspace/components/themes";
|
||||
|
||||
const StyledBodyPreparationPortal = styled.div`
|
||||
margin-bottom: 24px;
|
||||
width: 100%;
|
||||
max-width: ${(props) => (props.errorMessage ? "560px" : "480px")};
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
|
||||
const StyledPreparationPortalProgress = styled.div`
|
||||
.preparation-portal_progress {
|
||||
display: flex;
|
||||
margin-bottom: 16px;
|
||||
@ -40,13 +34,8 @@ const StyledBodyPreparationPortal = styled.div`
|
||||
left: calc(50% - 9px);
|
||||
}
|
||||
}
|
||||
|
||||
.preparation-portal_text {
|
||||
text-align: center;
|
||||
color: ${(props) => props.theme.text.disableColor};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledBodyPreparationPortal.defaultProps = { theme: Base };
|
||||
StyledPreparationPortalProgress.defaultProps = { theme: Base };
|
||||
|
||||
export default StyledBodyPreparationPortal;
|
||||
export default StyledPreparationPortalProgress;
|
@ -64,18 +64,23 @@ class AuthStore {
|
||||
}
|
||||
|
||||
if (this.isAuthenticated && !skipRequest) {
|
||||
requests.push(
|
||||
this.currentQuotaStore.init(),
|
||||
this.currentTariffStatusStore.init()
|
||||
);
|
||||
|
||||
!this.settingsStore.passwordSettings &&
|
||||
if (this.settingsStore.tenantStatus !== TenantStatus.PortalRestore) {
|
||||
requests.push(
|
||||
this.settingsStore.getPortalPasswordSettings(),
|
||||
this.settingsStore.getAdditionalResources(),
|
||||
this.settingsStore.getCompanyInfoSettings(),
|
||||
this.settingsStore.getWhiteLabelLogoUrls()
|
||||
this.currentQuotaStore.init(),
|
||||
this.currentTariffStatusStore.init()
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.settingsStore.passwordSettings) {
|
||||
if (this.settingsStore.tenantStatus !== TenantStatus.PortalRestore) {
|
||||
requests.push(
|
||||
this.settingsStore.getPortalPasswordSettings(),
|
||||
this.settingsStore.getAdditionalResources(),
|
||||
this.settingsStore.getCompanyInfoSettings()
|
||||
);
|
||||
}
|
||||
requests.push(this.settingsStore.getWhiteLabelLogoUrls());
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.all(requests);
|
||||
@ -95,10 +100,8 @@ class AuthStore {
|
||||
get isLoaded() {
|
||||
let success = false;
|
||||
if (this.isAuthenticated) {
|
||||
success =
|
||||
(this.userStore.isLoaded && this.settingsStore.isLoaded) ||
|
||||
this.settingsStore.tenantStatus === TenantStatus.PortalRestore;
|
||||
|
||||
success = this.userStore.isLoaded && this.settingsStore.isLoaded;
|
||||
|
||||
success && this.setLanguage();
|
||||
} else {
|
||||
success = this.settingsStore.isLoaded;
|
||||
@ -231,8 +234,8 @@ class AuthStore {
|
||||
|
||||
get isAuthenticated() {
|
||||
return (
|
||||
(this.settingsStore.isLoaded && !!this.settingsStore.socketUrl) || //this.userStore.isAuthenticated ||
|
||||
this.settingsStore.tenantStatus === TenantStatus.PortalRestore
|
||||
this.settingsStore.isLoaded && !!this.settingsStore.socketUrl
|
||||
//|| //this.userStore.isAuthenticated
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -257,12 +257,10 @@ class SettingsStore {
|
||||
requests.push(
|
||||
this.getPortalSettings(),
|
||||
this.getAppearanceTheme(),
|
||||
this.getWhiteLabelLogoUrls()
|
||||
this.getWhiteLabelLogoUrls(),
|
||||
this.getBuildVersionInfo()
|
||||
);
|
||||
|
||||
this.tenantStatus !== TenantStatus.PortalRestore &&
|
||||
requests.push(this.getBuildVersionInfo());
|
||||
|
||||
await Promise.all(requests);
|
||||
|
||||
this.setIsLoading(false);
|
||||
|
@ -113,6 +113,7 @@ class ComboBox extends React.Component {
|
||||
withBackground,
|
||||
advancedOptionsCount,
|
||||
isMobileView,
|
||||
withoutPadding,
|
||||
} = this.props;
|
||||
|
||||
const { tabIndex, ...props } = this.props;
|
||||
@ -168,6 +169,7 @@ class ComboBox extends React.Component {
|
||||
toggleAction={toggleAction}
|
||||
isOpen={isOpen}
|
||||
disableMobileView={disableMobileView}
|
||||
withoutPadding={withoutPadding}
|
||||
{...props}
|
||||
>
|
||||
<ComboButton
|
||||
@ -315,6 +317,7 @@ ComboBox.propTypes = {
|
||||
/**Count of advanced options */
|
||||
advancedOptionsCount: PropTypes.number,
|
||||
tabIndex: PropTypes.number,
|
||||
withoutPadding: PropTypes.bool,
|
||||
};
|
||||
|
||||
ComboBox.defaultProps = {
|
||||
@ -335,6 +338,7 @@ ComboBox.defaultProps = {
|
||||
isExternalLink: false,
|
||||
modernView: false,
|
||||
tabIndex: -1,
|
||||
withoutPadding: false,
|
||||
};
|
||||
|
||||
export default ComboBox;
|
||||
|
@ -13,7 +13,7 @@ const StyledComboBox = styled.div`
|
||||
position: relative;
|
||||
outline: 0;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
padding: 4px 0;
|
||||
padding: ${(props) => (props.withoutPadding ? "0" : "4px 0")};
|
||||
|
||||
${(props) =>
|
||||
props.isOpen &&
|
||||
|
@ -73,6 +73,7 @@ const Container = styled.div`
|
||||
max-width: ${(props) => (props.maxwidth ? props.maxwidth : "293px")};
|
||||
color: ${(props) =>
|
||||
props.color ? props.color : props.theme.fieldContainer.errorLabel.color};
|
||||
padding-top: 4px;
|
||||
}
|
||||
${(props) =>
|
||||
props.vertical ? getVerticalCss() : getHorizontalCss(props.maxLabelWidth)}
|
||||
|
@ -42,7 +42,11 @@ const ModalDialog = ({
|
||||
isScrollLocked,
|
||||
containerVisible,
|
||||
isDoubleFooterLine,
|
||||
isCloseable,
|
||||
}) => {
|
||||
const onCloseEvent = () => {
|
||||
isCloseable && onClose();
|
||||
};
|
||||
const [currentDisplayType, setCurrentDisplayType] = useState(
|
||||
getCurrentDisplayType(displayType, displayTypeDetailed)
|
||||
);
|
||||
@ -59,7 +63,7 @@ const ModalDialog = ({
|
||||
const onSwipe = (e) => setModalSwipeOffset(handleTouchMove(e, onClose));
|
||||
const onSwipeEnd = () => setModalSwipeOffset(0);
|
||||
const onKeyPress = (e) => {
|
||||
if ((e.key === "Esc" || e.key === "Escape") && visible) onClose();
|
||||
if ((e.key === "Esc" || e.key === "Escape") && visible) onCloseEvent();
|
||||
};
|
||||
|
||||
window.addEventListener("resize", onResize);
|
||||
@ -102,7 +106,7 @@ const ModalDialog = ({
|
||||
autoMaxHeight={autoMaxHeight}
|
||||
autoMaxWidth={autoMaxWidth}
|
||||
withFooterBorder={withFooterBorder}
|
||||
onClose={onClose}
|
||||
onClose={onCloseEvent}
|
||||
isLoading={isLoading}
|
||||
header={header}
|
||||
body={body}
|
||||
@ -111,6 +115,7 @@ const ModalDialog = ({
|
||||
visible={visible}
|
||||
modalSwipeOffset={modalSwipeOffset}
|
||||
containerVisible={containerVisible}
|
||||
isCloseable={isCloseable}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
@ -137,6 +142,9 @@ ModalDialog.propTypes = {
|
||||
/** Show loader in body */
|
||||
isLoading: PropTypes.bool,
|
||||
|
||||
/**The displayed dialog can be closed or not */
|
||||
isCloseable: PropTypes.bool,
|
||||
|
||||
/** **`MODAL-ONLY`**
|
||||
|
||||
Sets `width: 520px` and `max-hight: 400px`*/
|
||||
@ -180,7 +188,7 @@ ModalDialog.defaultProps = {
|
||||
zIndex: 310,
|
||||
isLarge: false,
|
||||
isLoading: false,
|
||||
withoutCloseButton: false,
|
||||
isCloseable: true,
|
||||
withBodyScroll: false,
|
||||
withFooterBorder: false,
|
||||
containerVisible: false,
|
||||
|
@ -39,6 +39,7 @@ const Modal = ({
|
||||
modalSwipeOffset,
|
||||
containerVisible,
|
||||
isDoubleFooterLine,
|
||||
isCloseable,
|
||||
}) => {
|
||||
const headerComponent = header ? header.props.children : null;
|
||||
const bodyComponent = body ? body.props.children : null;
|
||||
@ -82,11 +83,13 @@ const Modal = ({
|
||||
autoMaxWidth={autoMaxWidth}
|
||||
modalSwipeOffset={modalSwipeOffset}
|
||||
>
|
||||
<CloseButton
|
||||
currentDisplayType={currentDisplayType}
|
||||
onClick={onClose}
|
||||
id={id}
|
||||
/>
|
||||
{isCloseable && (
|
||||
<CloseButton
|
||||
currentDisplayType={currentDisplayType}
|
||||
onClick={onClose}
|
||||
id={id}
|
||||
/>
|
||||
)}
|
||||
{isLoading ? (
|
||||
currentDisplayType === "modal" ? (
|
||||
<Loaders.DialogLoader
|
||||
|
@ -824,7 +824,7 @@ const Base = {
|
||||
middle: "8px 12px",
|
||||
big: "8px 16px",
|
||||
huge: "8px 20px",
|
||||
large: "11px 15px",
|
||||
large: "11px 12px",
|
||||
},
|
||||
},
|
||||
|
||||
@ -3100,6 +3100,8 @@ const Base = {
|
||||
backgroundColor: "#F3F4F4",
|
||||
colorPercentSmall: "#333333",
|
||||
colorPercentBig: "#FFFFFF",
|
||||
errorTextColor: "#F21C0E",
|
||||
descriptionTextColor: "#A3A9AE",
|
||||
},
|
||||
|
||||
codeInput: {
|
||||
|
@ -816,7 +816,7 @@ const Dark = {
|
||||
middle: "8px 12px",
|
||||
big: "8px 16px",
|
||||
huge: "8px 20px",
|
||||
large: "11px 15px",
|
||||
large: "11px 12px",
|
||||
},
|
||||
},
|
||||
|
||||
@ -3099,6 +3099,8 @@ const Dark = {
|
||||
backgroundColor: "#282828",
|
||||
colorPercentSmall: "#FFFFFF",
|
||||
colorPercentBig: "#333333",
|
||||
errorTextColor: "#E06451",
|
||||
descriptionTextColor: "#858585",
|
||||
},
|
||||
|
||||
codeInput: {
|
||||
|
@ -629,13 +629,18 @@ function Editor({
|
||||
}
|
||||
};
|
||||
|
||||
const errorMessage = () => {
|
||||
if (typeof error !== "string") return error.errorMessage;
|
||||
|
||||
if (error === "restore-backup") return t("Common:PreparationPortalTitle");
|
||||
return error;
|
||||
};
|
||||
|
||||
const additionalComponents =
|
||||
error && !error?.unAuthorized ? (
|
||||
<ErrorContainerBody
|
||||
headerText={t("Common:Error")}
|
||||
customizedBodyText={
|
||||
typeof error === "string" ? error : error.errorMessage
|
||||
}
|
||||
customizedBodyText={errorMessage()}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
|
@ -44,7 +44,7 @@ const withDialogs = (WrappedComponent) => {
|
||||
const { socketHelper } = window.authStore.auth.settingsStore;
|
||||
socketHelper.emit({
|
||||
command: "subscribe",
|
||||
data: { roomParts: "backup-restore" }
|
||||
data: { roomParts: "backup-restore" },
|
||||
});
|
||||
socketHelper.on("restore-backup", () => {
|
||||
const message = t("Common:PreparationPortalTitle");
|
||||
@ -52,7 +52,7 @@ const withDialogs = (WrappedComponent) => {
|
||||
typeof window !== "undefined" &&
|
||||
window.DocEditor?.instances[EDITOR_ID];
|
||||
|
||||
docEditor?.showMessage(message);
|
||||
docEditor?.denyEditingRights(message);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
getSettingsFiles,
|
||||
// getShareFiles,
|
||||
} from "@docspace/common/api/files";
|
||||
import { TenantStatus } from "@docspace/common/constants";
|
||||
|
||||
import { getLogoFromPath } from "@docspace/common/utils";
|
||||
|
||||
@ -56,20 +57,25 @@ export const initDocEditor = async (req) => {
|
||||
const view = url.indexOf("action=view") !== -1;
|
||||
const fileVersion = version || null;
|
||||
|
||||
[
|
||||
user,
|
||||
settings,
|
||||
filesSettings,
|
||||
versionInfo,
|
||||
appearanceTheme,
|
||||
logoUrls,
|
||||
] = await Promise.all([
|
||||
const baseSettings = [
|
||||
getUser(),
|
||||
getSettings(),
|
||||
getSettingsFiles(),
|
||||
getBuildVersion(),
|
||||
getAppearanceTheme(),
|
||||
getLogoUrls(),
|
||||
];
|
||||
|
||||
[user, settings, appearanceTheme, logoUrls] = await Promise.all(
|
||||
baseSettings
|
||||
);
|
||||
|
||||
if (settings.tenantStatus === TenantStatus.PortalRestore) {
|
||||
error = "restore-backup";
|
||||
return { error, logoUrls };
|
||||
}
|
||||
|
||||
[filesSettings, versionInfo] = await Promise.all([
|
||||
getSettingsFiles(),
|
||||
getBuildVersion(),
|
||||
]);
|
||||
|
||||
const successAuth = !!user;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback } from "react";
|
||||
import React, { useState, useCallback, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ButtonsWrapper, LoginFormWrapper } from "./StyledLogin";
|
||||
@ -26,7 +26,7 @@ import { getBgPattern } from "@docspace/common/utils";
|
||||
import useIsomorphicLayoutEffect from "../hooks/useIsomorphicLayoutEffect";
|
||||
import { getLogoFromPath } from "@docspace/common/utils";
|
||||
import { useThemeDetector } from "@docspace/common/utils/useThemeDetector";
|
||||
|
||||
import { TenantStatus } from "@docspace/common/constants";
|
||||
interface ILoginProps extends IInitialState {
|
||||
isDesktopEditor?: boolean;
|
||||
}
|
||||
@ -42,13 +42,20 @@ const Login: React.FC<ILoginProps> = ({
|
||||
setTheme,
|
||||
logoUrls,
|
||||
}) => {
|
||||
const isRestoringPortal =
|
||||
portalSettings.tenantStatus === TenantStatus.PortalRestore;
|
||||
|
||||
useEffect(() => {
|
||||
isRestoringPortal && window.location.replace("/preparation-portal");
|
||||
}, []);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [moreAuthVisible, setMoreAuthVisible] = useState(false);
|
||||
const [recoverDialogVisible, setRecoverDialogVisible] = useState(false);
|
||||
|
||||
const { enabledJoin, greetingSettings, enableAdmMess } = portalSettings;
|
||||
const { ssoLabel, ssoUrl } = capabilities;
|
||||
|
||||
const ssoLabel = capabilities?.ssoLabel;
|
||||
const ssoUrl = capabilities?.ssoUrl;
|
||||
const { t } = useTranslation(["Login", "Common"]);
|
||||
const mounted = useMounted();
|
||||
const systemTheme = typeof window !== "undefined" && useThemeDetector();
|
||||
@ -191,6 +198,7 @@ const Login: React.FC<ILoginProps> = ({
|
||||
: getLogoFromPath(logo.path.light).replace("client/", "login/");
|
||||
|
||||
if (!mounted) return <></>;
|
||||
if (isRestoringPortal) return <></>;
|
||||
|
||||
return (
|
||||
<LoginFormWrapper
|
||||
|
@ -6,9 +6,10 @@ import {
|
||||
getAuthProviders,
|
||||
getCapabilities,
|
||||
getAppearanceTheme,
|
||||
getLogoUrls
|
||||
getLogoUrls,
|
||||
} from "@docspace/common/api/settings";
|
||||
import { checkIsAuthenticated } from "@docspace/common/api/user";
|
||||
import { TenantStatus } from "@docspace/common/constants";
|
||||
|
||||
export const getAssets = (): assetsType => {
|
||||
const manifest = fs.readFileSync(
|
||||
@ -61,23 +62,25 @@ export const getInitialState = async (
|
||||
isAuth: any,
|
||||
logoUrls: any;
|
||||
|
||||
[
|
||||
portalSettings,
|
||||
buildInfo,
|
||||
providers,
|
||||
capabilities,
|
||||
availableThemes,
|
||||
isAuth,
|
||||
logoUrls
|
||||
] = await Promise.all([
|
||||
const baseSettings = [
|
||||
getSettings(),
|
||||
getBuildVersion(),
|
||||
getAppearanceTheme(),
|
||||
getLogoUrls(),
|
||||
];
|
||||
|
||||
const settings = [
|
||||
getAuthProviders(),
|
||||
getCapabilities(),
|
||||
getAppearanceTheme(),
|
||||
checkIsAuthenticated(),
|
||||
getLogoUrls()
|
||||
]);
|
||||
];
|
||||
|
||||
[portalSettings, buildInfo, availableThemes, logoUrls] = await Promise.all(
|
||||
baseSettings
|
||||
);
|
||||
|
||||
if (portalSettings.tenantStatus !== TenantStatus.PortalRestore)
|
||||
[providers, capabilities, isAuth] = await Promise.all(settings);
|
||||
|
||||
const currentColorScheme = availableThemes.themes.find((theme) => {
|
||||
return availableThemes.selected === theme.id;
|
||||
@ -91,7 +94,7 @@ export const getInitialState = async (
|
||||
match: query,
|
||||
currentColorScheme,
|
||||
isAuth,
|
||||
logoUrls
|
||||
logoUrls,
|
||||
};
|
||||
|
||||
return initialState;
|
||||
|
@ -62,10 +62,9 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
private readonly bool _isEmptyTrash;
|
||||
private readonly IDictionary<string, StringValues> _headers;
|
||||
private readonly ThumbnailSettings _thumbnailSettings;
|
||||
private readonly SocketManager _socketManager;
|
||||
|
||||
public FileDeleteOperation(
|
||||
IServiceProvider serviceProvider, FileDeleteOperationData<T> fileOperationData, ThumbnailSettings thumbnailSettings, SocketManager socketManager)
|
||||
IServiceProvider serviceProvider, FileDeleteOperationData<T> fileOperationData, ThumbnailSettings thumbnailSettings)
|
||||
: base(serviceProvider, fileOperationData)
|
||||
{
|
||||
_ignoreException = fileOperationData.IgnoreException;
|
||||
@ -73,7 +72,6 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
_headers = fileOperationData.Headers;
|
||||
_isEmptyTrash = fileOperationData.IsEmptyTrash;
|
||||
_thumbnailSettings = thumbnailSettings;
|
||||
_socketManager = socketManager;
|
||||
this[OpType] = (int)FileOperationType.Delete;
|
||||
}
|
||||
|
||||
@ -81,6 +79,8 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
{
|
||||
var folderDao = scope.ServiceProvider.GetService<IFolderDao<int>>();
|
||||
var messageService = scope.ServiceProvider.GetService<MessageService>();
|
||||
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
|
||||
tenantManager.SetCurrentTenant(CurrentTenant);
|
||||
_trashId = await folderDao.GetFolderIDTrashAsync(true);
|
||||
|
||||
Folder<T> root = null;
|
||||
@ -112,6 +112,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
private async Task DeleteFoldersAsync(IEnumerable<T> folderIds, IServiceScope scope, bool isNeedSendActions = false, bool checkPermissions = true)
|
||||
{
|
||||
var scopeClass = scope.ServiceProvider.GetService<FileDeleteOperationScope>();
|
||||
var socketManager = scope.ServiceProvider.GetService<SocketManager>();
|
||||
var (fileMarker, filesMessageService, roomLogoManager) = scopeClass;
|
||||
foreach (var folderId in folderIds)
|
||||
{
|
||||
@ -154,7 +155,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
if (providerInfo.FolderId != null)
|
||||
{
|
||||
var room = await roomLogoManager.DeleteAsync(providerInfo.FolderId, checkPermissions);
|
||||
await _socketManager.UpdateFolderAsync(room);
|
||||
await socketManager.UpdateFolderAsync(room);
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +184,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
if (isRoom)
|
||||
{
|
||||
var room = await roomLogoManager.DeleteAsync(folder.Id, checkPermissions);
|
||||
await _socketManager.UpdateFolderAsync(room);
|
||||
await socketManager.UpdateFolderAsync(room);
|
||||
}
|
||||
|
||||
await FolderDao.DeleteFolderAsync(folder.Id);
|
||||
@ -193,7 +194,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
await ProviderDao.RemoveProviderInfoAsync(folder.ProviderId);
|
||||
}
|
||||
|
||||
await _socketManager.DeleteFolder(folder);
|
||||
await socketManager.DeleteFolder(folder);
|
||||
|
||||
filesMessageService.Send(folder, _headers, isRoom ? MessageAction.RoomDeleted : MessageAction.FolderDeleted, folder.Title);
|
||||
|
||||
@ -215,7 +216,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
if (isRoom)
|
||||
{
|
||||
var room = await roomLogoManager.DeleteAsync(folder.Id, checkPermissions);
|
||||
await _socketManager.UpdateFolderAsync(room);
|
||||
await socketManager.UpdateFolderAsync(room);
|
||||
}
|
||||
|
||||
await FolderDao.DeleteFolderAsync(folder.Id);
|
||||
@ -225,7 +226,7 @@ class FileDeleteOperation<T> : FileOperation<FileDeleteOperationData<T>, T>
|
||||
await ProviderDao.RemoveProviderInfoAsync(folder.ProviderId);
|
||||
}
|
||||
|
||||
await _socketManager.DeleteFolder(folder);
|
||||
await socketManager.DeleteFolder(folder);
|
||||
|
||||
if (isNeedSendActions)
|
||||
{
|
||||
|
@ -81,10 +81,9 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
private readonly FileConflictResolveType _resolveType;
|
||||
private readonly IDictionary<string, StringValues> _headers;
|
||||
private readonly ThumbnailSettings _thumbnailSettings;
|
||||
private readonly SocketManager _socketManager;
|
||||
private readonly Dictionary<T, Folder<T>> _parentRooms = new Dictionary<T, Folder<T>>();
|
||||
|
||||
public FileMoveCopyOperation(IServiceProvider serviceProvider, FileMoveCopyOperationData<T> data, ThumbnailSettings thumbnailSettings, SocketManager socketManager)
|
||||
public FileMoveCopyOperation(IServiceProvider serviceProvider, FileMoveCopyOperationData<T> data, ThumbnailSettings thumbnailSettings)
|
||||
: base(serviceProvider, data)
|
||||
{
|
||||
_daoFolderId = data.DaoFolderId;
|
||||
@ -94,7 +93,6 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
|
||||
_headers = data.Headers;
|
||||
_thumbnailSettings = thumbnailSettings;
|
||||
_socketManager = socketManager;
|
||||
this[OpType] = (int)(_copy ? FileOperationType.Copy : FileOperationType.Move);
|
||||
}
|
||||
|
||||
@ -226,6 +224,7 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
var (filesMessageService, fileMarker, _, _, _) = scopeClass;
|
||||
var folderDao = scope.ServiceProvider.GetService<IFolderDao<TTo>>();
|
||||
var countRoomChecker = scope.ServiceProvider.GetRequiredService<CountRoomChecker>();
|
||||
var socketManager = scope.ServiceProvider.GetService<SocketManager>();
|
||||
|
||||
var toFolderId = toFolder.Id;
|
||||
var isToFolder = Equals(toFolderId, _daoFolderId);
|
||||
@ -332,7 +331,7 @@ class FileMoveCopyOperation<T> : FileOperation<FileMoveCopyOperationData<T>, T>
|
||||
{
|
||||
await FolderDao.DeleteFolderAsync(folder.Id);
|
||||
|
||||
await _socketManager.DeleteFolder(folder);
|
||||
await socketManager.DeleteFolder(folder);
|
||||
|
||||
if (ProcessedFolder(folderId))
|
||||
{
|
||||
|
@ -31,7 +31,6 @@ public class FileOperationsManager
|
||||
{
|
||||
public const string CUSTOM_DISTRIBUTED_TASK_QUEUE_NAME = "files_operation";
|
||||
private readonly ThumbnailSettings _thumbnailSettings;
|
||||
private readonly SocketManager _socketManager;
|
||||
private readonly DistributedTaskQueue _tasks;
|
||||
private readonly TempStream _tempStream;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
@ -40,14 +39,12 @@ public class FileOperationsManager
|
||||
TempStream tempStream,
|
||||
IDistributedTaskQueueFactory queueFactory,
|
||||
IServiceProvider serviceProvider,
|
||||
ThumbnailSettings thumbnailSettings,
|
||||
SocketManager socketManager)
|
||||
ThumbnailSettings thumbnailSettings)
|
||||
{
|
||||
_tasks = queueFactory.CreateQueue(CUSTOM_DISTRIBUTED_TASK_QUEUE_NAME);
|
||||
_tempStream = tempStream;
|
||||
_serviceProvider = serviceProvider;
|
||||
_thumbnailSettings = thumbnailSettings;
|
||||
_socketManager = socketManager;
|
||||
}
|
||||
|
||||
public List<FileOperationResult> GetOperationResults(Guid userId)
|
||||
@ -143,8 +140,8 @@ public class FileOperationsManager
|
||||
var (folderIntIds, folderStringIds) = GetIds(folders);
|
||||
var (fileIntIds, fileStringIds) = GetIds(files);
|
||||
|
||||
var op1 = new FileMoveCopyOperation<int>(_serviceProvider, new FileMoveCopyOperationData<int>(folderIntIds, fileIntIds, tenant, destFolderId, copy, resolveType, holdResult, headers), _thumbnailSettings, _socketManager);
|
||||
var op2 = new FileMoveCopyOperation<string>(_serviceProvider, new FileMoveCopyOperationData<string>(folderStringIds, fileStringIds, tenant, destFolderId, copy, resolveType, holdResult, headers), _thumbnailSettings, _socketManager);
|
||||
var op1 = new FileMoveCopyOperation<int>(_serviceProvider, new FileMoveCopyOperationData<int>(folderIntIds, fileIntIds, tenant, destFolderId, copy, resolveType, holdResult, headers), _thumbnailSettings);
|
||||
var op2 = new FileMoveCopyOperation<string>(_serviceProvider, new FileMoveCopyOperationData<string>(folderStringIds, fileStringIds, tenant, destFolderId, copy, resolveType, holdResult, headers), _thumbnailSettings);
|
||||
var op = new FileMoveCopyOperation(_serviceProvider, op2, op1);
|
||||
|
||||
return QueueTask(userId, op);
|
||||
@ -152,7 +149,7 @@ public class FileOperationsManager
|
||||
|
||||
public List<FileOperationResult> Delete<T>(Guid userId, Tenant tenant, IEnumerable<T> folders, IEnumerable<T> files, bool ignoreException, bool holdResult, bool immediately, IDictionary<string, StringValues> headers, bool isEmptyTrash = false)
|
||||
{
|
||||
var op = new FileDeleteOperation<T>(_serviceProvider, new FileDeleteOperationData<T>(folders, files, tenant, holdResult, ignoreException, immediately, headers, isEmptyTrash), _thumbnailSettings, _socketManager);
|
||||
var op = new FileDeleteOperation<T>(_serviceProvider, new FileDeleteOperationData<T>(folders, files, tenant, holdResult, ignoreException, immediately, headers, isEmptyTrash), _thumbnailSettings);
|
||||
return QueueTask(userId, op);
|
||||
}
|
||||
|
||||
@ -161,8 +158,8 @@ public class FileOperationsManager
|
||||
var (folderIntIds, folderStringIds) = GetIds(folders);
|
||||
var (fileIntIds, fileStringIds) = GetIds(files);
|
||||
|
||||
var op1 = new FileDeleteOperation<int>(_serviceProvider, new FileDeleteOperationData<int>(folderIntIds, fileIntIds, tenant, holdResult, ignoreException, immediately, headers, isEmptyTrash), _thumbnailSettings, _socketManager);
|
||||
var op2 = new FileDeleteOperation<string>(_serviceProvider, new FileDeleteOperationData<string>(folderStringIds, fileStringIds, tenant, holdResult, ignoreException, immediately, headers, isEmptyTrash), _thumbnailSettings, _socketManager);
|
||||
var op1 = new FileDeleteOperation<int>(_serviceProvider, new FileDeleteOperationData<int>(folderIntIds, fileIntIds, tenant, holdResult, ignoreException, immediately, headers, isEmptyTrash), _thumbnailSettings);
|
||||
var op2 = new FileDeleteOperation<string>(_serviceProvider, new FileDeleteOperationData<string>(folderStringIds, fileStringIds, tenant, holdResult, ignoreException, immediately, headers, isEmptyTrash), _thumbnailSettings);
|
||||
var op = new FileDeleteOperation(_serviceProvider, op2, op1);
|
||||
|
||||
return QueueTask(userId, op);
|
||||
|
Loading…
Reference in New Issue
Block a user