Merge branch 'release/v1.0.0' of https://github.com/ONLYOFFICE/DocSpace into release/v1.0.0

This commit is contained in:
Maria Sukhova 2023-04-11 13:59:27 +03:00
commit b4b03ba498
30 changed files with 1070 additions and 928 deletions

View File

@ -272,6 +272,10 @@ public class TariffService : ITariffService
}
}
}
else
{
tariff = CalculateTariff(tenantId, tariff);
}
if (tariffId.HasValue && tariffId.Value != 0)
{

View File

@ -1083,7 +1083,7 @@ public class LocalesTest
[Category("Locales")]
public void WrongTranslationVariablesTest()
{
var message = $"Next keys have wrong variables:\r\n\r\n";
var message = $"Next keys have wrong or empty variables:\r\n\r\n";
var regVariables = new Regex("\\{\\{([^\\{].?[^\\}]+)\\}\\}", RegexOptions.Compiled | RegexOptions.Multiline);
var groupedByLng = TranslationFiles
@ -1092,8 +1092,8 @@ public class LocalesTest
{
Language = g.Key,
TranslationsWithVariables = g.ToList()
.SelectMany(t => t.Translations)
.Where(k => k.Value.IndexOf("{{") != -1)
.SelectMany(t => t.Translations)
//.Where(k => k.Value.IndexOf("{{") != -1)
.Select(t => new
{
t.Key,
@ -1109,6 +1109,7 @@ public class LocalesTest
var enWithVariables = groupedByLng
.Where(t => t.Language == "en")
.SelectMany(t => t.TranslationsWithVariables)
.Where(t => t.Variables.Count > 0)
.ToList();
var otherLanguagesWithVariables = groupedByLng
@ -1118,11 +1119,129 @@ public class LocalesTest
var i = 0;
var errorsCount = 0;
foreach (var lng in otherLanguagesWithVariables)
{
foreach (var t in lng.TranslationsWithVariables)
foreach (var enKeyWithVariables in enWithVariables)
{
foreach (var lng in otherLanguagesWithVariables)
{
var lngKey = lng.TranslationsWithVariables
.Where(t => t.Key == enKeyWithVariables.Key)
.FirstOrDefault();
if (lngKey == null)
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{enKeyWithVariables.Key}' not found\r\n\r\n";
errorsCount++;
continue;
}
if (enKeyWithVariables.Variables.Count != lngKey.Variables.Count)
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has less variables then 'en' language have " +
$"(en={enKeyWithVariables.Variables.Count}|{lng.Language}={lngKey.Variables.Count})\r\n" +
$"'en': '{enKeyWithVariables.Value}'\r\n'{lng.Language}': '{lngKey.Value}'\r\n\r\n";
errorsCount++;
}
if (!lngKey.Variables.All(v => enKeyWithVariables.Variables.Contains(v)))
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has not equals variables of 'en' language have \r\n" +
$"'{enKeyWithVariables.Value}' Variables=[{string.Join(",", enKeyWithVariables.Variables)}]\r\n" +
$"'{lngKey.Value}' Variables=[{string.Join(",", lngKey.Variables)}]\r\n\r\n";
errorsCount++;
}
}
}
Assert.AreEqual(0, errorsCount, message);
}
[Test]
[Category("Locales")]
public void WrongTranslationTagsTest()
{
var message = $"Next keys have wrong or empty translation's html tags:\r\n\r\n";
var regString = "<([^>]*)>(\\s*(.+?)\\s*)</([^>/]*)>";
var regTags = new Regex(regString, RegexOptions.Compiled | RegexOptions.Multiline);
var groupedByLng = TranslationFiles
.GroupBy(t => t.Language)
.Select(g => new
{
var enKey = enWithVariables
Language = g.Key,
TranslationsWithTags = g.ToList()
.SelectMany(t => t.Translations)
//.Where(k => k.Value.IndexOf("<") != -1)
.Select(t => new
{
t.Key,
t.Value,
Tags = regTags.Matches(t.Value)
.Select(m => m.Groups[1]?.Value?.Trim())
.ToList()
})
.ToList()
})
.ToList();
var enWithTags = groupedByLng
.Where(t => t.Language == "en")
.SelectMany(t => t.TranslationsWithTags)
.Where(t => t.Tags.Count > 0)
.ToList();
var otherLanguagesWithTags = groupedByLng
.Where(t => t.Language != "en")
.ToList();
var i = 0;
var errorsCount = 0;
foreach (var enKeyWithTags in enWithTags)
{
foreach (var lng in otherLanguagesWithTags)
{
var lngKey = lng.TranslationsWithTags
.Where(t => t.Key == enKeyWithTags.Key)
.FirstOrDefault();
if (lngKey == null)
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{enKeyWithTags.Key}' not found\r\n\r\n";
errorsCount++;
continue;
}
if (enKeyWithTags.Tags.Count != lngKey.Tags.Count)
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has less tags then 'en' language have " +
$"(en={enKeyWithTags.Tags.Count}|{lng.Language}={lngKey.Tags.Count})\r\n" +
$"'en': '{enKeyWithTags.Value}'\r\n'{lng.Language}': '{lngKey.Value}'\r\n\r\n";
errorsCount++;
}
if (!lngKey.Tags.All(v => enKeyWithTags.Tags.Contains(v)))
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has not equals tags of 'en' language have \r\n" +
$"'{enKeyWithTags.Value}' Tags=[{string.Join(",", enKeyWithTags.Tags)}]\r\n" +
$"'{lngKey.Value}' Tags=[{string.Join(",", lngKey.Tags)}]\r\n\r\n";
errorsCount++;
}
}
}
/*foreach (var lng in otherLanguagesWithTags)
{
foreach (var t in lng.TranslationsWithTags)
{
var enKey = enWithTags
.Where(en => en.Key == t.Key)
.FirstOrDefault();
@ -1134,25 +1253,25 @@ public class LocalesTest
continue;
}
if (enKey.Variables.Count != t.Variables.Count)
if (enKey.Tags.Count != t.Tags.Count)
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has less variables then 'en' language have " +
$"(en={enKey.Variables.Count}|{lng.Language}={t.Variables.Count})\r\n" +
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has less tags then 'en' language have " +
$"(en={enKey.Tags.Count}|{lng.Language}={t.Tags.Count})\r\n" +
$"'en': '{enKey.Value}'\r\n'{lng.Language}': '{t.Value}'\r\n\r\n";
errorsCount++;
}
if (!t.Variables.All(v => enKey.Variables.Contains(v)))
if (!t.Tags.All(v => enKey.Tags.Contains(v)))
{
// wrong
errorsCount++;
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has not equals variables of 'en' language have\r\n\r\n" +
$"Have to be:\r\n'{enKey.Value}'\r\n\r\n{string.Join("\r\n", enKey.Variables)}\r\n\r\n" +
$"But in real:\r\n'{t.Value}'\r\n\r\n{string.Join("\r\n", t.Variables)} \r\n\r\n";
message += $"{++i}. lng='{lng.Language}' key='{t.Key}' has not equals tags of 'en' language have\r\n\r\n" +
$"Have to be:\r\n'{enKey.Value}'\r\n\r\n{string.Join("\r\n", enKey.Tags)}\r\n\r\n" +
$"But in real:\r\n'{t.Value}'\r\n\r\n{string.Join("\r\n", t.Tags)} \r\n\r\n";
}
}
}
}*/
Assert.AreEqual(0, errorsCount, message);
}

View File

@ -81,6 +81,7 @@
"style-loader": "3.2.1",
"terser-webpack-plugin": "^5.2.4",
"typescript": "^4.7.4",
"use-resize-observer": "^9.1.0",
"webpack": "5.52.1",
"webpack-cli": "4.10.0",
"webpack-dev-server": "4.3.1"

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Cari mobil telefon nömrəniz",
"DeleteProfileBtn": "Hesabımı silin",
"DeleteProfileConfirmation": "Diqqət! Hesabınızı silmək üzrəsiniz.",
"DeleteProfileConfirmationInfo": "\"Hesabımı silin\" seçiminə klikləməklə bizim Məxfilik siyasətimizlə razılaşırsınız.",
"DeleteProfileConfirmationInfo": "\"Hesabımı silin\" seçiminə klikləməklə bizim <1>Məxfilik siyasətimizlə razılaşırsınız.</1>",
"DeleteProfileSuccessMessage": "Hesabınız uğurla silinmişdir.",
"DeleteProfileSuccessMessageInfo": "Hesabınızın və onunla bağlı məlumatların silinməsi haqqında daha ətraflı öyrənmək üçün bizim Məxfilik Siyasətimizə nəzər yetirin.",
"EmailAndPasswordCopiedToClipboard": "E-poçt ünvanı və şifrə mübadilə buferinə kopyalandı.",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Вашият текущ мобилен телефон",
"DeleteProfileBtn": "Изтрий моя профил",
"DeleteProfileConfirmation": "Внимание! На път сте да изтриете профила си.",
"DeleteProfileConfirmationInfo": "Като натиснете \"Изтрий профила ми\", се съгласявате с нашата Политика за поверителност.",
"DeleteProfileConfirmationInfo": "Като натиснете \"Изтрий профила ми\", се съгласявате с нашата <1>Политика за поверителност.</1>",
"DeleteProfileSuccessMessage": "Профилът Ви беше изтрит успешно.",
"DeleteProfileSuccessMessageInfo": "Вижте Политиката ни за поверителност, за да научите повече за изтриването на профила Ви и данните, свързани с него.",
"EmailAndPasswordCopiedToClipboard": "Имейлът и паролата са копирани в клипборда",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Vaše aktuální číslo mobilního telefonu",
"DeleteProfileBtn": "Smazat můj účet",
"DeleteProfileConfirmation": "Pozor! Chystáte se smazat svůj účet.",
"DeleteProfileConfirmationInfo": "Kliknutím na \"Smazat můj účet\" souhlasíte s našimi Zásadami ochrany osobních údajů.",
"DeleteProfileConfirmationInfo": "Kliknutím na \"Smazat můj účet\" souhlasíte s našimi <1>Zásadami ochrany osobních údajů.</1>",
"DeleteProfileSuccessMessage": "Váš účet byl úspěšně smazán.",
"DeleteProfileSuccessMessageInfo": "Více informací o vymazání vašeho účtu a údajů s ním spojených naleznete v našich Zásadách ochrany osobních údajů.",
"EmailAndPasswordCopiedToClipboard": "Email a heslo zkopírované do schránky",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Ihre aktuelle Telefonnummer",
"DeleteProfileBtn": "Mein Konto löschen",
"DeleteProfileConfirmation": "Achtung! Dies wird Ihr Konto löschen.",
"DeleteProfileConfirmationInfo": "Wenn Sie auf \"Mein Konto löschen\" klicken, akzeptieren Sie unsere Datenschutzerklärung.",
"DeleteProfileConfirmationInfo": "Wenn Sie auf \"Mein Konto löschen\" klicken, akzeptieren Sie unsere <1>Datenschutzerklärung.</1>",
"DeleteProfileSuccessMessage": "Ihr Konto wurde erfolgreich gelöscht. ",
"DeleteProfileSuccessMessageInfo": "Erfahren Sie mehr über Löschen Ihres Portals und aller Daten in unserer Datenschutzerklärung.",
"EmailAndPasswordCopiedToClipboard": "E-Mail und Passwort wurde in die Zwischenablage kopiert",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Ο τωρινός αριθμός κινητού τηλεφώνου σας",
"DeleteProfileBtn": "Διαγραφή του λογαριασμού μου",
"DeleteProfileConfirmation": "Προσοχή! Πρόκειται να διαγράψετε τον λογαριασμό σας.",
"DeleteProfileConfirmationInfo": "Κάνοντας κλικ στο \"Διαγραφή του λογαριασμού μου\" συμφωνείτε με την πολιτική απορρήτου μας.",
"DeleteProfileConfirmationInfo": "Κάνοντας κλικ στο \"Διαγραφή του λογαριασμού μου\" συμφωνείτε με την <1>πολιτική απορρήτου μας.</1>",
"DeleteProfileSuccessMessage": "Ο λογαριασμός σας διαγράφηκε επιτυχώς.",
"DeleteProfileSuccessMessageInfo": "Ανατρέξτε στην πολιτική απορρήτου μας για να μάθετε περισσότερα σχετικά με τη διαγραφή του λογαριασμού σας και των δεδομένων που σχετίζονται με αυτόν.",
"EmailAndPasswordCopiedToClipboard": "Το Email και ο κωδικός πρόσβασης αντιγράφηκαν στο πρόχειρο",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Nykyinen matkapuhelinnumerosi",
"DeleteProfileBtn": "Poista tilini",
"DeleteProfileConfirmation": "Huomio! Olet poistamassa tilisi.",
"DeleteProfileConfirmationInfo": "Napsauttamalla \"Poista tilini\", hyväksyt yksityisyyskäytäntömme.",
"DeleteProfileConfirmationInfo": "Napsauttamalla \"Poista tilini\", hyväksyt <1>yksityisyyskäytäntömme.</1>",
"DeleteProfileSuccessMessage": "Tilisi poistaminen onnistui.",
"DeleteProfileSuccessMessageInfo": "Katso yksityisyyskäytäntömme jos haluat lisätietoja tilisi ja siihen liittyvien tietojen poistamisesta.",
"EmailAndPasswordCopiedToClipboard": "Sähköposti ja salasana oon kopioitu leikepöydälle",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Votre numéro de téléphone mobile actuel",
"DeleteProfileBtn": "Supprimer mon compte",
"DeleteProfileConfirmation": "Attention ! Vous êtes sur le point de supprimer ce compte.",
"DeleteProfileConfirmationInfo": "En cliquant sur \"Supprimer mon compte\", vous acceptez notre politique de confidentialité.",
"DeleteProfileConfirmationInfo": "En cliquant sur \"Supprimer mon compte\", vous acceptez notre <1>politique de confidentialité.</1>",
"DeleteProfileSuccessMessage": "Votre compte a été supprimé avec succès.",
"DeleteProfileSuccessMessageInfo": "Consultez notre politique de confidentialité pour en savoir plus sur la suppression de votre compte et des données qui y sont associées.",
"EmailAndPasswordCopiedToClipboard": "Adresse mail et mot de passe copiés dans le Presse-papier",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Il tuo attuale numero di cellulare",
"DeleteProfileBtn": "Cancella il mio account",
"DeleteProfileConfirmation": "Attenzione! Stai per eliminare il tuo account.",
"DeleteProfileConfirmationInfo": "Facendo clic su \"Elimina il mio account\" accetti la nostra politica sulla privacy.",
"DeleteProfileConfirmationInfo": "Facendo clic su \"Elimina il mio account\" accetti la nostra <1>politica sulla privacy.</1>",
"DeleteProfileSuccessMessage": "Il tuo account è stato eliminato con successo.",
"DeleteProfileSuccessMessageInfo": "Consulta la nostra Informativa sulla privacy per saperne di più sull'eliminazione del tuo account e dei dati ad esso associati.",
"EmailAndPasswordCopiedToClipboard": "Email e password copiate negli appunti",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Jūsu pašreizējais mobilā tālruņa numurs",
"DeleteProfileBtn": "Dzēst manu kontu",
"DeleteProfileConfirmation": "Uzmanību! Jūs gatavojaties izdzēst savu kontu.",
"DeleteProfileConfirmationInfo": "Noklikšķinot uz \"Dzēst manu kontu\", jūs piekrītat mūsu konfidencialitātes politikai.",
"DeleteProfileConfirmationInfo": "Noklikšķinot uz \"Dzēst manu kontu\", jūs piekrītat mūsu <1>konfidencialitātes politikai.</1>",
"DeleteProfileSuccessMessage": "Jūsu konts ir veiksmīgi izdzēsts.",
"DeleteProfileSuccessMessageInfo": "Skatiet mūsu konfidencialitātes politiku, lai uzzinātu vairāk par sava konta un ar to saistīto datu dzēšanu.",
"EmailAndPasswordCopiedToClipboard": "E-pasts un parole ir kopēti starpliktuvē",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Uw huidige mobiele nummer",
"DeleteProfileBtn": "Verwijder mijn account",
"DeleteProfileConfirmation": "Let op! U staat op het punt uw account te verwijderen.",
"DeleteProfileConfirmationInfo": "Door op Mijn account verwijderen te klikken, gaat u akkoord met ons Privacybeleid.",
"DeleteProfileConfirmationInfo": "Door op Mijn account verwijderen te klikken, gaat u akkoord met ons <1>Privacybeleid.</1>",
"DeleteProfileSuccessMessage": "Uw account is met succes verwijderd.",
"DeleteProfileSuccessMessageInfo": "Zie ons Privacybeleid voor meer informatie over het verwijderen van uw account en de gegevens die daaraan gekoppeld zijn.",
"EmailAndPasswordCopiedToClipboard": "E-mail en wachtwoord gekopieerd naar klembord",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Twój aktualny numer telefonu komórkowego",
"DeleteProfileBtn": "Usuń moje konto",
"DeleteProfileConfirmation": "Uwaga! Zamierzasz usunąć swoje konto.",
"DeleteProfileConfirmationInfo": "Klikając przycisk \"Usuń moje konto\", wyrażasz zgodę na zasady naszej Polityki prywatności.",
"DeleteProfileConfirmationInfo": "Klikając przycisk \"Usuń moje konto\", wyrażasz zgodę na zasady naszej <1>Polityki prywatności.</1>",
"DeleteProfileSuccessMessage": "Twoje konto zostało pomyślnie usunięte.",
"DeleteProfileSuccessMessageInfo": "Zapoznaj się z naszą Polityką prywatności, aby dowiedzieć się więcej na temat usunięcia swojego konta oraz powiązanych z nim danych.",
"EmailAndPasswordCopiedToClipboard": "E-mail i hasło zostały skopiowane do schowka",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "O seu número de celular atual",
"DeleteProfileBtn": "Apagar minha conta",
"DeleteProfileConfirmation": "Atenção! Você está prestes a apagar sua conta.",
"DeleteProfileConfirmationInfo": "Ao clicar em \"Apagar minha conta\", você concorda com nossa política de privacidade.",
"DeleteProfileConfirmationInfo": "Ao clicar em \"Apagar minha conta\", você concorda com nossa <1>política de privacidade.</1>",
"DeleteProfileSuccessMessage": "Sua conta foi excluída com sucesso.",
"DeleteProfileSuccessMessageInfo": "Consulte nossa política de privacidade para saber mais sobre como excluir sua conta e os dados associados a ela.",
"EmailAndPasswordCopiedToClipboard": "Email e senha copiados para a área de transferência",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "O seu número de telemóvel atual",
"DeleteProfileBtn": "Eliminar a minha conta",
"DeleteProfileConfirmation": "Atenção! Está prestes a eliminar a sua conta.",
"DeleteProfileConfirmationInfo": "Ao clicar em \"Eliminar a minha conta\" concorda com a nossa política de privacidade.",
"DeleteProfileConfirmationInfo": "Ao clicar em \"Eliminar a minha conta\" concorda com a nossa <1>política de privacidade.</1>",
"DeleteProfileSuccessMessage": "A sua conta foi eliminada com êxito.",
"DeleteProfileSuccessMessageInfo": "Consulte a nossa Política de Privacidade para saber mais sobre a eliminação da sua conta e dos dados que lhe estão associados.",
"EmailAndPasswordCopiedToClipboard": "Email e palavra-chave copiados para a área de transferência",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Numărul dvs. de telefon mobil curent",
"DeleteProfileBtn": "Șterge contul meu",
"DeleteProfileConfirmation": "Atenție! Dumneavoastră sunteți pe cale de a șterge contul dvs.",
"DeleteProfileConfirmationInfo": "Apăsând Șterge contul meu, acceptați că sunteți de acord cu Politica de confidențialitate a companiei.",
"DeleteProfileConfirmationInfo": "Apăsând Șterge contul meu, acceptați că sunteți de acord cu <1>Politica de confidențialitate a companiei.</1>",
"DeleteProfileSuccessMessage": "Contul dvs a fost șters cu succes.",
"DeleteProfileSuccessMessageInfo": "Vă invităm să luați la cunoștință Politica de confidențialitate ca să aflați mai multe despre suprimarea contului și datelor asociate contului.",
"EmailAndPasswordCopiedToClipboard": "Adresa de e-mail și parola sunt copiate în clipboard ",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Vaše aktuálne číslo mobilného telefónu",
"DeleteProfileBtn": "Vymazať môj účet",
"DeleteProfileConfirmation": "Pozor! Idete si zmazať účet.",
"DeleteProfileConfirmationInfo": "Odkliknutím \"Vymazať môj účet\" súhlasíte s našou politikou Ochrany súkromia.",
"DeleteProfileConfirmationInfo": "Odkliknutím \"Vymazať môj účet\" súhlasíte s našou <1>politikou Ochrany súkromia.</1>",
"DeleteProfileSuccessMessage": "Váš účet bol úspešne odstránený.",
"DeleteProfileSuccessMessageInfo": "Viac informácií o odstránení účtu a údajov s ním spojených nájdete v našich pravidlách ochrany osobných údajov.",
"EmailAndPasswordCopiedToClipboard": "E-mail a heslo boli skopírované do schránky",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Vaša trenutna številka mobilnega telefona",
"DeleteProfileBtn": "Izbriši moj račun",
"DeleteProfileConfirmation": "Pozor! Izbrisali boste svoj račun.",
"DeleteProfileConfirmationInfo": "S klikom na \"izbriši moj račun\" se strinjate z našo Politiko zasebnosti.",
"DeleteProfileConfirmationInfo": "S klikom na \"izbriši moj račun\" se strinjate z našo <1>Politiko zasebnosti.</1>",
"DeleteProfileSuccessMessage": "Vaš račun je bil uspešno izbrisan.",
"DeleteProfileSuccessMessageInfo": "Oglejte si naš pravilnik o zasebnosti, če želite izvedeti več o brisanju računa in podatkov, povezanih z njim.",
"EmailAndPasswordCopiedToClipboard": "Email in geslo sta kopirana v odložišče",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Güncel mobil telefon numaranız",
"DeleteProfileBtn": "Hesabımı sil",
"DeleteProfileConfirmation": "Dikkat! Hesabınızı silmek üzeresiniz.",
"DeleteProfileConfirmationInfo": "\"Hesabımı sil\"e tıklayarak Gizlilik politikamızı kabul etmiş olursunuz.",
"DeleteProfileConfirmationInfo": "\"Hesabımı sil\"e tıklayarak <1>Gizlilik politikamızı kabul etmiş olursunuz.</1>",
"DeleteProfileSuccessMessage": "Hesabınız başarıyla silindi.",
"DeleteProfileSuccessMessageInfo": "Hesabınızı ve onunla ilgili bilgileri silmekle alakalı daha fazla bilgi almak için Gizlilik politikamıza göz atın.",
"EmailAndPasswordCopiedToClipboard": "E-posta ve şifre panoya kopyalandı",

View File

@ -5,7 +5,7 @@
"CurrentNumber": "Số điện thoại di động hiện tại của bạn",
"DeleteProfileBtn": "Xóa tài khoản của tôi",
"DeleteProfileConfirmation": "Chú ý! Bạn sắp xóa tài khoản của mình.",
"DeleteProfileConfirmationInfo": "Với việc nhấp vào\"Xóa tài khoản của tôi\"bạn đồng ý với Chính sách Bảo mật của chúng tôi.",
"DeleteProfileConfirmationInfo": "Với việc nhấp vào\"Xóa tài khoản của tôi\"bạn đồng ý với <1>Chính sách Bảo mật của chúng tôi.</1>",
"DeleteProfileSuccessMessage": "Tài khoản của bạn đã được xóa thành công.",
"DeleteProfileSuccessMessageInfo": "Hãy xem chính sách Bảo mật của chúng tôi để tìm hiểu thêm về cách xóa tài khoản của bạn và dữ liệu liên quan đến tài khoản đó.",
"EmailAndPasswordCopiedToClipboard": "Đã sao chép email và mật khẩu vào bộ nhớ tạm",

View File

@ -226,7 +226,7 @@ const StyledButtons = styled(Box)`
position: absolute;
bottom: 0px;
width: 100%;
background: ${(props) => props.theme.filesPanels.sharing.backgroundButtons};
border-top: ${(props) => props.theme.filesPanels.sharing.borderTop};
`;

View File

@ -50,6 +50,11 @@ const InvitePanel = ({
const [shareLinks, setShareLinks] = useState([]);
const [roomUsers, setRoomUsers] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [externalLinksVisible, setExternalLinksVisible] = useState(false);
const onChangeExternalLinksVisible = (visible) => {
setExternalLinksVisible(visible);
};
const selectRoom = () => {
const room = folders.find((folder) => folder.id === roomId);
@ -222,6 +227,8 @@ const InvitePanel = ({
shareLinks={shareLinks}
getInfo={getInfo}
roomType={roomType}
onChangeExternalLinksVisible={onChangeExternalLinksVisible}
externalLinksVisible={externalLinksVisible}
/>
<InviteInput
@ -233,7 +240,13 @@ const InvitePanel = ({
{!!inviteItems.length && (
<>
<ItemsList t={t} setHasErrors={setHasErrors} roomType={roomType} />
<ItemsList
t={t}
setHasErrors={setHasErrors}
roomType={roomType}
externalLinksVisible={externalLinksVisible}
/>
<StyledButtons>
<Button
scale={true}

View File

@ -32,8 +32,9 @@ const ExternalLinks = ({
setInvitationLinks,
isOwner,
getInfo,
onChangeExternalLinksVisible,
externalLinksVisible,
}) => {
const [linksVisible, setLinksVisible] = useState(false);
const [actionLinksVisible, setActionLinksVisible] = useState(false);
const [activeLink, setActiveLink] = useState({});
@ -54,12 +55,12 @@ const ExternalLinks = ({
} else {
link = shareLinks[0];
!linksVisible ? editLink() : disableLink();
!externalLinksVisible ? editLink() : disableLink();
}
setLinksVisible(!linksVisible);
onChangeExternalLinksVisible(!externalLinksVisible);
if (!linksVisible && withCopy) copyLink(link?.shareLink);
if (!externalLinksVisible && withCopy) copyLink(link?.shareLink);
};
const disableLink = () => {
@ -185,14 +186,17 @@ const ExternalLinks = ({
</DropDown>
</div>
)}
<StyledToggleButton isChecked={linksVisible} onChange={toggleLinks} />
<StyledToggleButton
isChecked={externalLinksVisible}
onChange={toggleLinks}
/>
</StyledSubHeader>
<StyledDescription>
{roomId === -1
? t("InviteViaLinkDescriptionAccounts")
: t("InviteViaLinkDescriptionRoom")}
</StyledDescription>
{linksVisible && (
{externalLinksVisible && (
<StyledInviteInputContainer key={activeLink.id}>
<StyledInviteInput>
<InputBlock

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef, memo, useCallback } from "react";
import { inject, observer } from "mobx-react";
import { FixedSizeList as List } from "react-window";
import CustomScrollbarsVirtualList from "@docspace/components/scrollbar/custom-scrollbars-virtual-list";
import useResizeObserver from "use-resize-observer";
import Item from "./Item";
import { StyledRow, ScrollList } from "../StyledInvitePanel";
@ -48,19 +48,23 @@ const ItemsList = ({
setHasErrors,
roomType,
isOwner,
externalLinksVisible,
}) => {
const [bodyHeight, setBodyHeight] = useState(0);
const [offsetTop, setOffsetTop] = useState(0);
const bodyRef = useRef();
const { height } = useResizeObserver({ ref: bodyRef });
const onBodyResize = useCallback(() => {
setBodyHeight(bodyRef.current.offsetHeight - FOOTER_HEIGHT);
const heightList = height ? height : bodyRef.current.offsetHeight;
setBodyHeight(heightList - FOOTER_HEIGHT);
setOffsetTop(bodyRef.current.offsetTop);
}, [bodyRef?.current?.offsetHeight]);
}, [height, bodyRef?.current?.offsetHeight]);
useEffect(() => {
onBodyResize();
}, [bodyRef.current]);
}, [bodyRef.current, externalLinksVisible, height]);
useEffect(() => {
window.addEventListener("resize", onBodyResize);

View File

@ -2654,6 +2654,8 @@ const Base = {
itemOwnerColor: "rgb(163, 169, 174)",
backgroundButtons: "#FFFFFF",
dropdownColor: black,
loader: {

View File

@ -2655,6 +2655,8 @@ const Dark = {
itemOwnerColor: "#858585",
backgroundButtons: "#333333",
dropdownColor: grayMaxLight,
loader: {

View File

@ -60,7 +60,7 @@ public class RemoveUserDataController : ApiControllerBase
}
[HttpGet("remove/progress")]
public RemoveProgressItem GetRemoveProgress(Guid userId)
public RemoveProgressItem GetRemoveProgress(Guid userId)
{
_permissionContext.DemandPermissions(Constants.Action_EditUser);
@ -72,7 +72,7 @@ public class RemoveUserDataController : ApiControllerBase
{
var user = _userManager.GetUsers(_securityContext.CurrentAccount.ID);
if (user.IsLDAP())
if (user.IsLDAP() || user.IsOwner(Tenant))
{
throw new SecurityException();
}
@ -85,7 +85,7 @@ public class RemoveUserDataController : ApiControllerBase
[HttpPost("remove/start")]
public RemoveProgressItem StartRemove(TerminateRequestDto inDto)
{
{
_permissionContext.DemandPermissions(Constants.Action_EditUser);
var user = _userManager.GetUsers(inDto.UserId);
@ -105,7 +105,7 @@ public class RemoveUserDataController : ApiControllerBase
[HttpPut("remove/terminate")]
public void TerminateRemove(TerminateRequestDto inDto)
{
{
_permissionContext.DemandPermissions(Constants.Action_EditUser);
_queueWorkerRemove.Terminate(Tenant.Id, inDto.UserId);

View File

@ -444,11 +444,11 @@ public class UserController : PeopleControllerBase
throw new Exception(Resource.ErrorUserNotFound);
}
if (user.IsLDAP())
if (user.IsLDAP() || user.IsOwner(Tenant))
{
throw new SecurityException();
}
_securityContext.AuthenticateMeWithoutCookie(Core.Configuration.Constants.CoreSystem);
user.Status = EmployeeStatus.Terminated;

1747
yarn.lock

File diff suppressed because it is too large Load Diff