diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index e5df7c7915..3766c15bc9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -493,6 +493,44 @@ "QuotationTemplate.Tax/VAT:": "Tax / Vat (%{0}) :", "QuotationTemplate.TotalDiscount:": "Total Discount :", "QuotationTemplate.TOTALDUE:": "TOTAL DUE :", - "QuotationTemplate.BankAccount": "Our bank account information can be found at {0}" + "QuotationTemplate.BankAccount": "Our bank account information can be found at {0}", + "Permission:Raffles": "Raffle", + "Permission:Draw": "Draw", + "Menu:Raffles": "Raffles", + "RaffleIsNotDrawable": "Raffle is not drawable", + "WinnerCountMustBeGreaterThanZero": "Winner count must be greater than zero", + "FullDescription": "Full Description", + "VisibilityStartDate": "Visibility Start Date", + "VisibilityEndDate": "Visibility End Date", + "RaffleDate": "Raffle Date", + "SubscriptionCode": "Subscription Code", + "GroupCode": "Group Code", + "MaxWinnerCount": "Max Winner Count", + "ReDraw": "Re-Draw", + "EditRaffle": "Edit Raffle", + "Raffles": "Raffles", + "CreateARaffle": "Create a raffle", + "Draw": "Draw", + "Enum:RaffleStatus:0": "Active", + "Enum:RaffleStatus:1": "Next", + "Enum:RaffleStatus:2": "Past", + "DrawDone": "Draw Done", + "HomePageShowType": "Home Page Show Type", + "None": "None", + "Card": "Card", + "Horizontal": "Horizontal", + "Winners": "Winners", + "StartDateMustBeLessThanEndDate": "Start date must be less than end date", + "VisibilityStartDateMustBeLessThanVisibilityEndDate": "Visibility start date must be less than visibility end date", + "StartDateMustBeGreaterThanVisibilityStartDate": "Start date must be greater than visibility start date", + "EndDateMustBeLessThanVisibilityEndDate": "End date must be less than visibility end date", + "DrawnDone": "Drawn Done", + "AddColor": "Add Color", + "Colors": "Colors", + "RemoveColor": "Remove Color", + "MaxColorCountWarning": "You can add up to {0} colors", + "MinColorCountWarning": "You must add at least {0} colors", + "RaffleDeletionConfirmationMessage": "Are you sure you want to delete this raffle?", + "CreateRaffle": "Create Raffle" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json index 7226737b84..362a5f0f22 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": " نظام أساسي كامل لتطوير الويب مدمج framework ", "AbpCommercialShortDescription": "يوفر ABP Commercial وحدات تطبيق مسبقة الإنشاء وأدوات تطوير سريعة للتطبيقات وموضوعات واجهة مستخدم احترافية ودعمًا متميزًا والمزيد.", "LiveDemo": "عرض حي", + "LiveDemoLead": "{1} باستخدام حساب ABP الخاص بك، {3}إلى abp.io.
أو املأ النموذج أدناه لإنشاء عرض توضيحي مباشر الآن", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "هناك حساب بالفعل باستخدام عنوان البريد الإلكتروني المحدد: {0}
يمكنك تسجيل الدخول باستخدام حسابك للمتابعة.", "GetLicence": "احصل على ترخيص", "Application": "تطبيق", "StartupTemplates": "قوالب بدء تشغيل ABP", @@ -129,12 +131,14 @@ "YourFullName": "اسمك الكامل", "EmailField": "عنوان البريد الإلكتروني", "YourEmailAddress": "عنوان بريدك الإلكتروني", + "ValidEmailAddressIsRequired": "مطلوب عنوان بريد إلكتروني صالح.", "HowMayWeHelpYou": "كيف يمكن أن نساعدك؟", "SendMessage": "أرسل رسالة", "Success": "النجاح", "WeWillReplyYou": "لقد تلقينا رسالتك وسنتواصل معك قريبًا.", "GoHome": "اذهب للمنزل", "CreateLiveDemo": "إنشاء عرض حي", + "CreateLiveDemoDescription": "بمجرد إرسال هذا النموذج ، ستتلقى رسالة بريد إلكتروني تحتوي على رابط العرض التوضيحي الخاص بك.", "RegisterToTheNewsletter": "سجل في النشرة الإخبارية لتلقي معلومات بخصوص ABP.IO ، بما في ذلك الإصدارات الجديدة وما إلى ذلك.", "EnterYourEmailOrLogin": "أدخل عنوان بريدك الإلكتروني لإنشاء العرض التوضيحي أو تسجيل الدخول باستخدام حسابك الحالي.", "ApplicationTemplate": "نموذج التطبيق", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json index a1205f1809..ef5e3d17c6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "Kompletní platforma pro vývoj webuvestavěná na framework", "AbpCommercialShortDescription": "ABP Commercial poskytuje předpřipravené aplikační moduly, nástroje pro rychlý vývoj aplikací, profesionální témata uživatelského rozhraní, prémiovou podporu a další.", "LiveDemo": "Živá ukázka", + "LiveDemoLead": "{1} pomocí vašeho účtu ABP, {3} na abp.io.
Nebo vyplňte níže uvedený formulář a vytvořte si nyní živou ukázku", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Zadaná e-mailová adresa {0} je již registrována.
Můžete se přihlásit se svým účtem a pokračovat.", "GetLicence": "Získejte licenci", "Application": "aplikace", "StartupTemplates": "Spouštěcí šablony", @@ -129,12 +131,14 @@ "YourFullName": "Vaše celé jméno", "EmailField": "Emailová adresa", "YourEmailAddress": "Vaše emailová adresa", + "ValidEmailAddressIsRequired": "Je vyžadována platná e-mailová adresa.", "HowMayWeHelpYou": "Jak vám můžeme pomoci?", "SendMessage": "Poslat zprávu", "Success": "Úspěch", "WeWillReplyYou": "Obdrželi jsme vaši zprávu a brzy se vám ozveme.", "GoHome": "Jdi domů", "CreateLiveDemo": "Vytvořit živé demo", + "CreateLiveDemoDescription": "Po odeslání tohoto formuláře obdržíte e-mail obsahující odkaz na vaši ukázku.", "RegisterToTheNewsletter": "Zaregistrujte se k odběru newsletteru a získejte informace o ABP.IO, včetně nových verzí atd.", "EnterYourEmailOrLogin": "Chcete-li vytvořit ukázku, zadejte svou e-mailovou adresu nebo se přihlaste pomocí svého stávajícího účtu.", "ApplicationTemplate": "Šablona aplikace", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json index ebc78f8b51..e2bd413dfe 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "Eine komplette Webentwicklungsplattformaufgebaute Framework", "AbpCommercialShortDescription": "ABP Commercial bietet vorgefertigte Anwendungsmodule, schnelle Anwendungsentwicklungstools, professionelle UI-Themen, Premium-Support und mehr.", "LiveDemo": "Live-Demo", + "LiveDemoLead": "{1} mit Ihrem ABP-Konto, {3} zu abp.io.
Oder füllen Sie das Formular unten aus, um jetzt eine Live-Demo zu erstellen", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Es gibt bereits ein Konto mit der angegebenen E-Mail-Adresse: {0}
Sie können sich mit Ihrem Konto anmelden, um fortzufahren.", "GetLicence": "Holen Sie sich eine Lizenz", "Application": "Anwendung", "StartupTemplates": "Startup-Vorlagen", @@ -129,12 +131,14 @@ "YourFullName": "Ihren vollständigen Namen", "EmailField": "E-Mail-Addresse", "YourEmailAddress": "Ihre E-Mail-Adresse", + "ValidEmailAddressIsRequired": "Eine gültige E-Mail-Adresse ist erforderlich.", "HowMayWeHelpYou": "Wie können wir Ihnen helfen?", "SendMessage": "Nachricht senden", "Success": "Erfolg", "WeWillReplyYou": "Wir haben Ihre Nachricht erhalten und werden uns in Kürze bei Ihnen melden.", "GoHome": "Nach Hause gehen", "CreateLiveDemo": "Live-Demo erstellen", + "CreateLiveDemoDescription": "Sobald Sie dieses Formular absenden, erhalten Sie eine E-Mail mit Ihrem Demo-Link.", "RegisterToTheNewsletter": "Melden Sie sich für den Newsletter an, um Informationen zu ABP.IO, einschließlich Neuerscheinungen etc. zu erhalten.", "EnterYourEmailOrLogin": "Geben Sie Ihre E-Mail-Adresse ein, um Ihre Demo zu erstellen, oder Login mit Ihrem bestehenden Konto.", "ApplicationTemplate": "Bewerbungsvorlage", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 4ec259664c..4de6bb2ec8 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -49,6 +49,8 @@ "IndexPageHeroSection": "A complete web development platformbuilt-on framework", "AbpCommercialShortDescription": "ABP Commercial provides pre-built application modules, rapid application development tooling, professional UI themes, premium support and more.", "LiveDemo": "Live Demo", + "LiveDemoLead": "{1} using your ABP account, {3} to abp.io.
Or fill the form below to create a live demo now", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "There is already an account with the given email address: {0}
You can login with your account to proceed.", "GetLicence": "Get a License", "Application": "Application", "StartupTemplates": "Startup Templates", @@ -132,12 +134,14 @@ "LastNameField": "Last Name", "EmailField": "E-mail Address", "YourEmailAddress": "Your e-mail address", + "ValidEmailAddressIsRequired": "A valid e-mail address is required.", "HowMayWeHelpYou": "How may we help you?", "SendMessage": "Send Message", "Success": "Success", "WeWillReplyYou": "We received your message and will be in touch shortly.", "GoHome": "Go Home", "CreateLiveDemo": "Create Live Demo", + "CreateLiveDemoDescription": "Once you submit this form, you will receive an email containing your demo link.", "RegisterToTheNewsletter": "Register for the newsletter to receive information regarding ABP.IO, including new releases etc.", "EnterYourEmailOrLogin": "Enter your e-mail address to create your demo or Login using your existing account.", "ApplicationTemplate": "Application Template", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json index 88ce642703..0d211064d7 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": " Una plataforma de desarrollo web completa integrada marco ", "AbpCommercialShortDescription": "ABP Commercial proporciona módulos de aplicaciones prediseñados, herramientas de desarrollo rápido de aplicaciones, temas de interfaz de usuario profesionales, soporte premium y más.", "LiveDemo": "Demo en vivo", + "LiveDemoLead": "{1} usando su cuenta ABP, {3} a abp.io.
O complete el siguiente formulario para crear una demostración en vivo ahora", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Ya existe una cuenta con la dirección de correo electrónico especificada: {0}
Puede iniciar sesión con su cuenta para continuar.", "GetLicence": "Obtener una licencia", "Application": "Solicitud", "StartupTemplates": "Plantillas de inicio", @@ -129,12 +131,14 @@ "YourFullName": "Tu nombre completo", "EmailField": "Dirección de correo electrónico", "YourEmailAddress": "Tu correo electrónico", + "ValidEmailAddressIsRequired": "Se requiere una dirección de correo electrónico válida.", "HowMayWeHelpYou": "¿Cómo podemos ayudarle?", "SendMessage": "Enviar mensaje", "Success": "Éxito", "WeWillReplyYou": "Recibimos su mensaje y nos pondremos en contacto a la brevedad.", "GoHome": "Vete a casa", "CreateLiveDemo": "Crear demostración en vivo", + "CreateLiveDemoDescription": "Una vez que envíe este formulario, recibirá un correo electrónico con el enlace de su demostración.", "RegisterToTheNewsletter": "Regístrese para recibir el boletín informativo para recibir información sobre ABP.IO, incluidos nuevos lanzamientos, etc.", "EnterYourEmailOrLogin": "Ingrese su dirección de correo electrónico para crear su demostración o Iniciar sesión con su cuenta existente.", "ApplicationTemplate": "Plantilla de aplicación", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json index 3e1b92ff90..cb94010c0e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json @@ -49,6 +49,8 @@ "IndexPageHeroSection": " Täydellinen verkkokehitysympäristö sisäänrakennettu kehys ", "AbpCommercialShortDescription": "ABP Commercial tarjoaa valmiita sovellusmoduuleja, nopean sovelluskehitystyökalun, ammattimaiset käyttöliittymäteemat, ensiluokkaisen tuen ja paljon muuta.", "LiveDemo": "Live-esittely", + "LiveDemoLead": "{1} käyttämällä ABP-tiliäsi, {3} abp.io: lle.
Tai täytä alla oleva lomake luodaksesi live-esittelyn nyt", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Sähköpostiosoitteella {0} on jo tili.
Voit kirjautua sisään tilillesi jatkaaksesi.", "GetLicence": "Hanki lisenssi", "Application": "Sovellus", "StartupTemplates": "Käynnistysmallit", @@ -132,12 +134,14 @@ "LastNameField": "Sukunimi", "EmailField": "Sähköpostiosoite", "YourEmailAddress": "Sähköpostiosoitteesi", + "ValidEmailAddressIsRequired": "Kelvollinen sähköpostiosoite vaaditaan", "HowMayWeHelpYou": "Kuinka voimme auttaa sinua?", "SendMessage": "Lähetä viesti", "Success": "Menestys", "WeWillReplyYou": "Saimme viestisi ja otamme sinuun pian yhteyttä.", "GoHome": "Mene kotiin", "CreateLiveDemo": "Luo live-esittely", + "CreateLiveDemoDescription": "Kun lähetät tämän lomakkeen, saat sähköpostin, jossa on linkki demoosi.", "RegisterToTheNewsletter": "Rekisteröidy uutiskirjeeseen saadaksesi tietoa ABP.IO: sta, mukaan lukien uudet julkaisut jne.", "EnterYourEmailOrLogin": "Kirjoita sähköpostiosoitteesi luodaksesi esittely tai kirjaudu sisään nykyisellä tililläsi.", "ApplicationTemplate": "Sovelluksen malli", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json index 0588062ad8..3f3be7d3be 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "Une plate-forme de développement Web complète intégrée cadre ", "AbpCommercialShortDescription": "ABP Commercial fournit des modules d'application prédéfinis, des outils de développement rapide d'applications, des thèmes d'interface utilisateur professionnels, un support premium et plus encore.", "LiveDemo": "Démo en direct", + "LiveDemoLead": "{1} en utilisant votre compte ABP, {3} à abp.io.
Ou remplissez le formulaire ci-dessous pour créer une démo en direct maintenant", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Il existe déjà un compte avec l'adresse e-mail fournie: {0}
Vous pouvez vous connecter avec votre compte pour continuer.", "GetLicence": "Obtenez une licence", "Application": "Application", "StartupTemplates": "Modèles de démarrage", @@ -129,12 +131,14 @@ "YourFullName": "Votre nom complet", "EmailField": "Adresse e-mail", "YourEmailAddress": "Votre adresse email", + "ValidEmailAddressIsRequired": "Une adresse e-mail valide est requise.", "HowMayWeHelpYou": "Comment pouvons nous vous aider?", "SendMessage": "Envoyer le message", "Success": "Succès", "WeWillReplyYou": "Nous avons reçu votre message et vous contacterons sous peu.", "GoHome": "Retour à l'acceuil", "CreateLiveDemo": "Créer une démo en direct", + "CreateLiveDemoDescription": "Une fois que vous avez soumis ce formulaire, vous recevrez un e-mail contenant le lien de votre démo.", "RegisterToTheNewsletter": "Inscrivez-vous à la newsletter pour recevoir des informations concernant ABP.IO, y compris les nouvelles versions, etc.", "EnterYourEmailOrLogin": "Saisissez votre adresse e-mail pour créer votre démo ou Connectez-vous à l'aide de votre compte existant.", "ApplicationTemplate": "Modèle d'application", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json index 2d16ac121d..935c1b12d0 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "एक पूर्ण वेब डेवलपमेंट प्लेटफॉर्मबिल्ट-ऑन Framework", "AbpCommercialShortDescription": "एबीपी कमर्शियल प्री-बिल्ट एप्लिकेशन मॉड्यूल, रैपिड एप्लिकेशन डेवलपमेंट टूलिंग, पेशेवर यूआई थीम, प्रीमियम सपोर्ट आदि प्रदान करता है।", "LiveDemo": "लाइव डेमो", + "LiveDemoLead": "{1} अपने एबीपी खाते का उपयोग करते हुए, {3} abp.io पर आपका स्वागत है।
या अब एक लाइव डेमो बनाने के लिए नीचे दिए गए फॉर्म को भरें", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "दिए गए ईमेल पते {0} के साथ पहले से ही एक खाता है।
आप अपने खाते से लॉगिन करके आगे बढ़ सकते हैं।", "GetLicence": "एक लाइसेंस प्राप्त करें", "Application": "आवेदन", "StartupTemplates": "स्टार्टअप टेम्पलेट", @@ -129,12 +131,14 @@ "YourFullName": "आपका पूरा नाम", "EmailField": "ईमेल पता", "YourEmailAddress": "आपका ईमेल पता", + "ValidEmailAddressIsRequired": "एक वैध ईमेल पता आवश्यक है।", "HowMayWeHelpYou": "हम कैसे आपकी सहायता कर सकते हैं?", "SendMessage": "मेसेज भेजें", "Success": "सफलता", "WeWillReplyYou": "हमें आपका संदेश प्राप्त हुआ और शीघ्र ही संपर्क में आएगा।", "GoHome": "घर जाओ", "CreateLiveDemo": "लाइव डेमो बनाएँ", + "CreateLiveDemoDescription": "एक बार जब आप इस फॉर्म को जमा करते हैं, तो आपको अपने डेमो लिंक को समेत एक ईमेल प्राप्त होगा।", "RegisterToTheNewsletter": "ABP.IO के बारे में जानकारी प्राप्त करने के लिए न्यूज़लेटर के लिए रजिस्टर करें, जिसमें नई रिलीज़ आदि शामिल हैं।", "EnterYourEmailOrLogin": "अपना डेमो बनाने के लिए अपना ई-मेल पता दर्ज करें या अपने मौजूदा खाते का उपयोग करके लॉगिन करें।", "ApplicationTemplate": "एप्लिकेशन टेम्पलेट", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json index 351a468fe4..03cd52cbca 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json @@ -49,6 +49,8 @@ "IndexPageHeroSection": "Teljes webfejlesztői platformbeépített keretrendszer", "AbpCommercialShortDescription": "Az ABP Commercial előre beépített alkalmazásmodulokat, gyors alkalmazásfejlesztési eszközöket, professzionális felhasználói felületi témákat, prémium támogatást és még sok mást kínál.", "LiveDemo": "Élő Demo", + "LiveDemoLead": "{1} az ABP-fiókjával, {3} az abp.io-ra.
Vagy töltse ki az alábbi űrlapot, hogy most létrehozzon egy élő bemutatót", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Már van fiók a megadott e-mail címmel: {0}
Bejelentkezhet a fiókjával a folytatáshoz.", "GetLicence": "Szerezzen engedélyt", "Application": "Alkalmazás", "StartupTemplates": "Indítási sablonok", @@ -132,12 +134,14 @@ "LastNameField": "Vezetéknév", "EmailField": "Email cím", "YourEmailAddress": "Az email címed", + "ValidEmailAddressIsRequired": "Érvényes e-mail cím szükséges", "HowMayWeHelpYou": "Hogyan segíthetünk?", "SendMessage": "Üzenet küldése", "Success": "Siker", "WeWillReplyYou": "Megkaptuk üzenetét, és hamarosan felvesszük Önnel a kapcsolatot.", "GoHome": "Hazamenni", "CreateLiveDemo": "Élő bemutató létrehozása", + "CreateLiveDemoDescription": "Miután elküldte ezt a űrlapot, e-mailt kap, amely tartalmazza a bemutató linkjét.", "RegisterToTheNewsletter": "Regisztráljon a hírlevélre, hogy információkat kapjon az ABP.IO-ról, beleértve az új kiadásokat stb.", "EnterYourEmailOrLogin": "Adja meg e-mail címét a bemutató létrehozásához, vagy jelentkezzen be meglévő fiókjával.", "ApplicationTemplate": "Alkalmazássablon", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json index ff0c6cc417..c125ce7d3e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "Heilstætt vefþróunar umhverfi byggt á ABP", "AbpCommercialShortDescription": "ABP Commercial býður upp á forsmíðaðar forritareiningar, tól sem hraða þróun, fagmanlega hannaðar UI þemur, úrvals stuðning og fleira.", "LiveDemo": "Virkt sýnidæmi", + "LiveDemoLead": "{1} með þínum ABP reikningi, {3} til abp.io.
Eða fylltu út formið hér að neðan til að búa til virkt sýnidæmi núna", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Það er nú þegar reikningur með þessu netfangi: {0}
Þú getur skráð þig inn með þínum reikningi til að halda áfram.", "GetLicence": "Sækja Leyfi", "Application": "Umsókn", "StartupTemplates": "Byrjunar Sniðmát", @@ -129,12 +131,14 @@ "YourFullName": "Þitt fulla nafn", "EmailField": "Netfang", "YourEmailAddress": "Netfangið þitt", + "ValidEmailAddressIsRequired": "Netfangið þarf að vera gilt.", "HowMayWeHelpYou": "Hvernig getum við aðstoðað þig?", "SendMessage": "Senda skilaboð", "Success": "Heppnaðist", "WeWillReplyYou": "Við höfum móttekið skilaboðin þín og munum hafa samband innan tíðar.", "GoHome": "Fara heim", "CreateLiveDemo": "Búa til Live Demo", + "CreateLiveDemoDescription": "Þegar þú sendir þetta form, færðu tölvupóst sem inniheldur tengilinn þinn.", "RegisterToTheNewsletter": "Skráning á póstlista fyrir fréttabréf með upplýsingum um ABP.IO, þ.á.m. nýjar útgáfur o.s.frv..", "EnterYourEmailOrLogin": "Settu inn netfangið þitt til að búa til kynningu eða Login með þínum notandareikningi.", "ApplicationTemplate": "Forritssniðmát", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json index ccd74fd005..a1e06f4a06 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": " Una completa piattaforma di sviluppo web integrata framework ", "AbpCommercialShortDescription": "ABP Commercial fornisce moduli applicativi predefiniti, strumenti per lo sviluppo rapido di applicazioni, temi dell'interfaccia utente professionale, supporto premium e altro ancora.", "LiveDemo": "Dimostrazione dal vivo", + "LiveDemoLead": "{1} utilizzando il tuo account ABP, {3} a abp.io.
O compilare il modulo sottostante per creare una demo live ora", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Esiste già un account con l'indirizzo email specificato: {0}
Puoi accedere con il tuo account per procedere.", "GetLicence": "Ottieni una licenza", "Application": "Applicazione", "StartupTemplates": "Modelli di avvio", @@ -129,12 +131,14 @@ "YourFullName": "Il tuo nome completo", "EmailField": "Indirizzo e-mail", "YourEmailAddress": "Il tuo indirizzo di posta elettronica", + "ValidEmailAddressIsRequired": "È richiesto un indirizzo email valido.", "HowMayWeHelpYou": "Come possiamo aiutarti?", "SendMessage": "Invia messaggio", "Success": "Successo", "WeWillReplyYou": "Abbiamo ricevuto il tuo messaggio e ti contatteremo a breve.", "GoHome": "Torna all'inizio", "CreateLiveDemo": "Crea demo live", + "CreateLiveDemoDescription": "Una volta inviato questo modulo, riceverai un'e-mail contenente il link alla tua demo.", "RegisterToTheNewsletter": "Registrati alla newsletter per ricevere informazioni su ABP.IO, comprese le nuove versioni ecc.", "EnterYourEmailOrLogin": "Inserisci il tuo indirizzo e-mail per creare la tua demo o Accedi utilizzando il tuo account esistente.", "ApplicationTemplate": "Modello di applicazione", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json index cc7a076848..a1b445a81c 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "Een compleet webontwikkelingsplatformingebouwd raamwerk", "AbpCommercialShortDescription": "ABP Commercial biedt kant-en-klare applicatiemodules, tooling voor snelle applicatieontwikkeling, professionele UI-thema's, premium ondersteuning en meer.", "LiveDemo": "Live demonstratie", + "LiveDemoLead": "{1} met behulp van uw ABP-account, {3} naar abp.io.
Of vul het onderstaande formulier in om nu een live demo te maken", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Er is al een account met het opgegeven e-mailadres: {0}
U kunt inloggen met uw account om door te gaan.", "GetLicence": "Verkrijg een licentie", "Application": "Sollicitatie", "StartupTemplates": "Opstartsjablonen", @@ -129,12 +131,14 @@ "YourFullName": "Je volledige naam", "EmailField": "E-mailadres", "YourEmailAddress": "Jouw e-mailadres", + "ValidEmailAddressIsRequired": "Een geldig e-mailadres is vereist.", "HowMayWeHelpYou": "Hoe kunnen we je helpen?", "SendMessage": "Bericht versturen", "Success": "Succes", "WeWillReplyYou": "We hebben uw bericht ontvangen en nemen spoedig contact met u op.", "GoHome": "Ga naar huis", "CreateLiveDemo": "Live demo maken", + "CreateLiveDemoDescription": "Zodra u dit formulier indient, ontvangt u een e-mail met uw demolink.", "RegisterToTheNewsletter": "Schrijf je in voor de nieuwsbrief om informatie over ABP.IO te ontvangen, inclusief nieuwe releases etc.", "EnterYourEmailOrLogin": "Voer uw e-mailadres in om uw demo te maken of Log in met uw bestaande account.", "ApplicationTemplate": "Toepassingssjabloon", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json index 4aa4f6616f..ed08bb1583 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "A complete web development platformbuilt-on framework", "AbpCommercialShortDescription": "ABP Commercial zapewnia gotowe moduły aplikacji, narzędzia do szybkiego tworzenia aplikacji, profesjonalne motywy interfejsu użytkownika, wsparcie premium i nie tylko.", "LiveDemo": "Demo na żywo", + "LiveDemoLead": "{1} korzystając z konta ABP, {3} to abp.io.
Lub wypełnij poniższy formularz, aby utworzyć teraz demo na żywo", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Istnieje już konto o podanym adresie e-mail: {0}
Możesz się zalogować na swoje konto, aby kontynuować.", "GetLicence": "Uzyskaj licencję", "Application": "Podanie", "StartupTemplates": "Szablony startowe", @@ -129,12 +131,14 @@ "YourFullName": "Twoje pełne imię", "EmailField": "Adres e-mail", "YourEmailAddress": "Twój adres email", + "ValidEmailAddressIsRequired": "Wymagany jest prawidłowy adres e-mail.", "HowMayWeHelpYou": "Jak możemy Ci pomóc?", "SendMessage": "Wyślij wiadomość", "Success": "Powodzenie", "WeWillReplyYou": "Otrzymaliśmy Twoją wiadomość i wkrótce się z Tobą skontaktujemy.", "GoHome": "Idź do domu", "CreateLiveDemo": "Utwórz demo na żywo", + "CreateLiveDemoDescription": "Po wysłaniu tego formularza otrzymasz e-mail z linkiem do swojego demo.", "RegisterToTheNewsletter": "Zarejestruj się do newslettera, aby otrzymywać informacje dotyczące ABP.IO, w tym nowości itp.", "EnterYourEmailOrLogin": "Wprowadź swój adres e-mail, aby utworzyć demo lub Zaloguj się przy użyciu istniejącego konta.", "ApplicationTemplate": "Szablon aplikacji", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json index 4e06b40112..2aebae87cd 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": " Uma completa plataforma de desenvolvimento web integrada estrutura ", "AbpCommercialShortDescription": "ABP Commercial fornece módulos de aplicativos pré-construídos, ferramentas de desenvolvimento rápido de aplicativos, temas de UI profissionais, suporte premium e muito mais.", "LiveDemo": "Demonstração ao vivo", + "LiveDemoLead": "{1} usando sua conta ABP, {3} para abp.io.
Ou preencha o formulário abaixo para criar uma demonstração ao vivo agora", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Já existe uma conta com o endereço de e-mail fornecido: {0}
Você pode fazer login com sua conta para continuar.", "GetLicence": "Obtenha uma licença", "Application": "Aplicativo", "StartupTemplates": "Modelos de inicialização", @@ -129,12 +131,14 @@ "YourFullName": "Seu nome completo", "EmailField": "Endereço de e-mail", "YourEmailAddress": "Seu endereço de email", + "ValidEmailAddressIsRequired": "Um endereço de e-mail válido é obrigatório.", "HowMayWeHelpYou": "Como podemos ajudá-lo?", "SendMessage": "Enviar mensagem", "Success": "Sucesso", "WeWillReplyYou": "Recebemos sua mensagem e entraremos em contato em breve.", "GoHome": "Ir para casa", "CreateLiveDemo": "Criar demonstração ao vivo", + "CreateLiveDemoDescription": "Depois de enviar este formulário, você receberá um e-mail contendo o link da sua demonstração.", "RegisterToTheNewsletter": "Cadastre-se no boletim informativo para receber informações sobre ABP.IO, incluindo novos lançamentos etc.", "EnterYourEmailOrLogin": "Digite seu endereço de e-mail para criar sua demonstração ou Faça login usando sua conta existente.", "ApplicationTemplate": "Modelo de aplicativo", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json index 358bd87038..25d24193ad 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "A complete web development platformbuilt-on framework", "AbpCommercialShortDescription": "ABP Commercial oferă module de aplicaţii pre-construite, instrumente de dezvoltare rapidă a aplicaţiilor, teme UI profesionale, asistenţă premium şi multe altele.", "LiveDemo": "Live Demo", + "LiveDemoLead": "{1} folosind contul ABP, {3} la abp.io.
Sau completaţi formularul de mai jos pentru a crea un demo live acum", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Există deja un cont cu adresa de email specificată: {0}
Puteţi să vă autentificaţi cu contul dumneavoastră pentru a continua.", "GetLicence": "Obţine o licenţă", "Application": "Application", "StartupTemplates": "Şabloane de lansare", @@ -129,12 +131,14 @@ "YourFullName": "Numele dumneavoastră complet", "EmailField": "Adresa de email", "YourEmailAddress": "Adresa dumneavoastră de email", + "ValidEmailAddressIsRequired": "Vă rugăm să introduceţi o adresă de email validă.", "HowMayWeHelpYou": "Cum vă putem ajuta?", "SendMessage": "Trimite mesaj", "Success": "Succes", "WeWillReplyYou": "Am primit mesajul dumneavoastră şi vă vom contacta cât de repede posibil.", "GoHome": "Navigaţi acasă", "CreateLiveDemo": "Crează Demo Live", + "CreateLiveDemoDescription": "După ce trimiteţi acest formular, veţi primi un email care conţine link-ul demo-ului dumneavoastră.", "RegisterToTheNewsletter": "Înregistraţi-va la newsletter pentru a primi informaţii despre ABP.IO, inclusiv lansări noi etc.", "EnterYourEmailOrLogin": "Introduceţi-vă adresa de email pentru a vă crea demo-ul sau Autentificaţi-vă folosind contul existent.", "ApplicationTemplate": "Application Template", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json index 8c53bc9ea8..4832618e30 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ru.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": " Полная платформа веб-разработки встроенная каркас ", "AbpCommercialShortDescription": "ABP Commercial предоставляет готовые модули приложений, инструменты для быстрой разработки приложений, профессиональные темы пользовательского интерфейса, поддержку премиум-класса и многое другое.", "LiveDemo": "Живая демонстрация", + "LiveDemoLead": "{1} используя свою учетную запись ABP, {3} на abp.io.
Или заполните форму ниже, чтобы создать живую демонстрацию прямо сейчас", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Уже есть учетная запись с указанным адресом электронной почты: {0}
Вы можете войти в свою учетную запись, чтобы продолжить.", "GetLicence": "Получить лицензию", "Application": "заявка", "StartupTemplates": "Шаблоны запуска", @@ -129,12 +131,14 @@ "YourFullName": "Ваше полное имя", "EmailField": "Адрес электронной почты", "YourEmailAddress": "Ваш адрес электронной почты", + "ValidEmailAddressIsRequired": "Требуется действительный адрес электронной почты.", "HowMayWeHelpYou": "Как мы можем Вам помочь?", "SendMessage": "Отправить сообщение", "Success": "Успех", "WeWillReplyYou": "Мы получили ваше сообщение и скоро свяжемся с вами.", "GoHome": "Иди домой", "CreateLiveDemo": "Создать живую демонстрацию", + "CreateLiveDemoDescription": "После отправки этой формы вы получите электронное письмо со ссылкой на демонстрацию.", "RegisterToTheNewsletter": "Подпишитесь на рассылку новостей, чтобы получать информацию о ABP.IO, в том числе о новых выпусках и т. Д.", "EnterYourEmailOrLogin": "Введите свой адрес электронной почты, чтобы создать демоверсию, или войдите , используя существующую учетную запись.", "ApplicationTemplate": "Шаблон приложения", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json index b0a6d6490e..0d4ca5e610 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "Kompletná web vývojová platformapostavená na frameworku", "AbpCommercialShortDescription": "ABP Commercial poskytuje predpripravené aplikačné moduly, nástroje na rýchly vývoj aplikácií, profesionálne témy používateľského rozhrania, prémiovú podporu a ďalšie.", "LiveDemo": "Live ukážka", + "LiveDemoLead": "{1} použitím vášho ABP účtu, {3} na abp.io.
Alebo vyplňte nižšie uvedený formulár a vytvorte si teraz live ukážku", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Už existuje účet s danou emailovou adresou: {0}
Môžete sa prihlásiť pomocou svojho účtu a pokračovať.", "GetLicence": "Získajte licenciu", "Application": "Aplikácia", "StartupTemplates": "Štartovacie šablóny", @@ -129,12 +131,14 @@ "YourFullName": "Vaše celé meno", "EmailField": "Emailová adresa", "YourEmailAddress": "Vaša emailová adresa", + "ValidEmailAddressIsRequired": "Je potrebná platná emailová adresa.", "HowMayWeHelpYou": "Ako vám môžeme pomôcť?", "SendMessage": "Odoslať správu", "Success": "Úspech", "WeWillReplyYou": "Dostali sme vašu správu a čoskoro vás budeme kontaktovať.", "GoHome": "Prejsť Domov", "CreateLiveDemo": "Vytvoriť live ukážku", + "CreateLiveDemoDescription": "Po odoslaní tohto formulára obdržíte e-mail obsahujúci odkaz na vašu ukážku.", "RegisterToTheNewsletter": "Zaregistrujte sa na odber noviniek a dostávajte informácie o ABP.IO, vrátane nových verzií atď.", "EnterYourEmailOrLogin": "Zadajte svoju emailovú adresu a vytvorte si ukážku alebo sa prihláste pomocou svojho existujúceho konta.", "ApplicationTemplate": "Šablóna žiadosti", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json index 85acb70552..6687f04ec6 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": "Popolna platforma za spletno razvojvgrajena okvir", "AbpCommercialShortDescription": "ABP Commercial ponuja vnaprej izdelane aplikacijske module, orodja za hiter razvoj aplikacij, profesionalne teme uporabniškega vmesnika, vrhunsko podporo in še več.", "LiveDemo": "Demo v živo", + "LiveDemoLead": "{1} s svojim ABP računom, {3} na abp.io.
Ali izpolnite spodnji obrazec, da ustvarite demo v živo zdaj", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Za navedeni e-poštni naslov že obstaja račun: {0}
Lahko se prijavite s svojim računom, da nadaljujete.", "GetLicence": "Pridobite licenco", "Application": "Aplikacija", "StartupTemplates": "Predloge za zagon", @@ -129,12 +131,14 @@ "YourFullName": "Tvoje polno ime", "EmailField": "Email naslov", "YourEmailAddress": "Vaš email naslov", + "ValidEmailAddressIsRequired": "Veljaven e-poštni naslov je obvezen", "HowMayWeHelpYou": "Kako vam lahko pomagamo?", "SendMessage": "Pošlji sporočilo", "Success": "uspeh", "WeWillReplyYou": "Prejeli smo vaše sporočilo in vas bomo v kratkem kontaktirali.", "GoHome": "Pojdi domov", "CreateLiveDemo": "Ustvari demo v živo", + "CreateLiveDemoDescription": "Ko pošljete ta obrazec, boste prejeli e-poštno sporočilo s povezavo do svojega demo.", "RegisterToTheNewsletter": "Registrirajte se za glasilo, če želite prejemati informacije o ABP.IO, vključno z novimi izdajami itd.", "EnterYourEmailOrLogin": "Vnesite svoj e-poštni naslov, če želite ustvariti predstavitev, ali Prijavite se z obstoječim računom.", "ApplicationTemplate": "Predloga aplikacije", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json index 7c4df52c6c..1dad32c034 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json @@ -48,6 +48,8 @@ "IndexPageHeroSection": "A complete web development platformbuilt-on framework", "AbpCommercialShortDescription": "ABP Commercial, önceden oluşturulmuş uygulama modülleri, hızlı uygulama geliştirme araçları, profesyonel UI temaları, premium destek ve daha fazlasını sağlar.", "LiveDemo": "Canlı Demo", + "LiveDemoLead": "{1} ABP hesabınızı kullanarak, {3} abp.io'ya hoş geldiniz.
Veya aşağıdaki formu doldurarak şimdi canlı bir demo oluşturun", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Zaten {0} e-posta adresiyle bir hesap var.
Devam etmek için hesabınızla giriş yapabilirsiniz.", "GetLicence": "Lisans Alın", "Application": "Başvuru", "StartupTemplates": "Başlangıç Şablonları", @@ -131,12 +133,14 @@ "YourFullName": "Tam adınız", "EmailField": "E-posta Adresi", "YourEmailAddress": "E-posta adresiniz", + "ValidEmailAddressIsRequired": "Geçerli bir e-posta adresi gereklidir", "HowMayWeHelpYou": "Size nasıl yardımcı olabiliriz?", "SendMessage": "Mesaj gönder", "Success": "Başarı", "WeWillReplyYou": "Mesajınızı aldık ve kısa süre içinde sizinle iletişime geçeceğiz.", "GoHome": "Eve git", "CreateLiveDemo": "Canlı Demo Oluştur", + "CreateLiveDemoDescription": "Bu formu gönderdikten sonra, demo bağlantınızı içeren bir e-posta alacaksınız.", "RegisterToTheNewsletter": "ABP.IO hakkında yeni yayınlar vb. dahil olmak üzere bilgi almak için haber bültenine kaydolun.", "EnterYourEmailOrLogin": "Demonuzu oluşturmak için e-posta adresinizi girin veya mevcut hesabınızı kullanarak Giriş yapın.", "ApplicationTemplate": "Uygulama Şablonu", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json index e5ed696808..05658075db 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json @@ -46,6 +46,8 @@ "IndexPageHeroSection": " Nền tảng phát triển web hoàn chỉnh được tích hợp sẵn khung ", "AbpCommercialShortDescription": "ABP Commercial cung cấp các mô-đun ứng dụng được tạo sẵn, công cụ phát triển ứng dụng nhanh chóng, các chủ đề giao diện người dùng chuyên nghiệp, hỗ trợ cao cấp và hơn thế nữa.", "LiveDemo": "Bản thử trực tiếp", + "LiveDemoLead": "{1} hoặc {3} đến abp.io.
Hoặc điền vào biểu mẫu bên dưới để tạo bản trình diễn trực tiếp ngay bây giờ", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "Đã có một tài khoản với địa chỉ email đã cho: {0}
Bạn có thể đăng nhập vào tài khoản của mình để tiếp tục.", "GetLicence": "Nhận giấy phép", "Application": "Ứng dụng", "StartupTemplates": "Mẫu khởi động", @@ -129,12 +131,14 @@ "YourFullName": "Tên đầy đủ của bạn", "EmailField": "Địa chỉ email", "YourEmailAddress": "Địa chỉ email của bạn", + "ValidEmailAddressIsRequired": "Địa chỉ email hợp lệ là bắt buộc", "HowMayWeHelpYou": "Chúng tôi có thể giúp gì cho bạn?", "SendMessage": "Gửi tin nhắn", "Success": "Sự thành công", "WeWillReplyYou": "Chúng tôi đã nhận được tin nhắn của bạn và sẽ sớm liên hệ với bạn.", "GoHome": "Về nhà", "CreateLiveDemo": "Tạo bản trình diễn trực tiếp", + "CreateLiveDemoDescription": "Sau khi bạn gửi biểu mẫu này, bạn sẽ nhận được một email chứa liên kết bản demo của mình.", "RegisterToTheNewsletter": "Đăng ký nhận bản tin để nhận thông tin về ABP.IO, bao gồm các bản phát hành mới, v.v.", "EnterYourEmailOrLogin": "Nhập địa chỉ e-mail của bạn để tạo bản demo hoặc Đăng nhập bằng tài khoản hiện có của bạn.", "ApplicationTemplate": "Mẫu ứng dụng", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json index 0aadd74a52..dc2046e197 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json @@ -49,6 +49,8 @@ "IndexPageHeroSection": "一个完整的web开发平台基于 框架", "AbpCommercialShortDescription": "ABP商业版提供了预构建的应用程序模块, 快速的应用程序开发工具, 专业的UI主题, 高级支持等.", "LiveDemo": "在线演示", + "LiveDemoLead": "{1} 到你的ABP账户, {3} 到 abp.io.
或者填写下面的表单立即创建在线演示", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "已经有一个使用此电子邮件地址的帐户: {0}
你可以使用你的帐户登录继续.", "GetLicence": "获得许可", "Application": "应用程序", "StartupTemplates": "启动模板", @@ -132,12 +134,14 @@ "LastNameField": "姓氏", "EmailField": "E-mail地址", "YourEmailAddress": "你的e-mail地址", + "ValidEmailAddressIsRequired": "请输入有效的e-mail地址", "HowMayWeHelpYou": "需要获得购买帮助?(提供中文服务)", "SendMessage": "发送消息", "Success": "成功", "WeWillReplyYou": "你的消息已经发送! 我们会在短时间内给你答复.", "GoHome": "回到主页面", "CreateLiveDemo": "创建在线演示", + "CreateLiveDemoDescription": "一旦你提交此表单,你将收到一封包含你的演示链接的电子邮件.", "RegisterToTheNewsletter": "注册到时事简报以获取有关ABP.IO的消息,比如新发布的内容.", "EnterYourEmailOrLogin": "输入你的e-mail地址来创建你的演示或者使用你的已有账号登录.", "ApplicationTemplate": "应用程序模板", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json index 1f50563750..a90e7f20bb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json @@ -48,6 +48,8 @@ "IndexPageHeroSection": "一個完整的web開發平臺基於 框架", "AbpCommercialShortDescription": "ABP商業版提供了預構建的應用程序模塊, 快速的應用程序開發工具, 專業的UI主題, 高級支持等.", "LiveDemo": "在線演示", + "LiveDemoLead": " {1} 使用你的ABP賬號, {3} 到 abp.io.
或者填寫下面的表單立即創建一個在線演示", + "ThereIsAlreadyAnAccountWithTheGivenEmailAddress": "已經有一個使用該電子郵件地址的賬號: {0}
你可以使用你的賬號登錄以繼續.", "GetLicence": "獲得許可", "Application": "應用程序", "StartupTemplates": "啟動模板", @@ -131,12 +133,14 @@ "YourFullName": "你的全名", "EmailField": "E-mail地址", "YourEmailAddress": "你的e-mail地址", + "ValidEmailAddressIsRequired": "請輸入有效的e-mail地址", "HowMayWeHelpYou": "我們如何幫助你", "SendMessage": "發送消息", "Success": "成功", "WeWillReplyYou": "你的消息已經發送! 我們會在短時間內給你答復.", "GoHome": "回到主頁面", "CreateLiveDemo": "創建在線演示", + "CreateLiveDemoDescription": "一旦你提交此表單,你將收到一封包含你的演示鏈接的電子郵件.", "RegisterToTheNewsletter": "註冊到時事簡報以獲取有關ABP.IO的消息,比如新發布的內容.", "EnterYourEmailOrLogin": "輸入你的e-mail地址來創建你的演示或者使用你的已有賬號登錄.", "ApplicationTemplate": "應用程序模板", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index 4951ee85b4..f5a637676e 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -191,6 +191,34 @@ "DiscordPageTitle": "ABP Discord Community", "ViewVideo": "View Video", "AbpCommunityTitleContent": "ABP Community - Open Source ABP Framework", - "CommunitySlogan": "A unique community platform for ABP Lovers" + "CommunitySlogan": "A unique community platform for ABP Lovers", + "RaffleIsNotActive": "Raffle is not active", + "YouAreAlreadyJoinedToThisRaffle": "You are already joined to this raffle", + "InvalidSubscriptionCode": "Invalid subscription code", + "Raffle:{0}": "Raffle: {0}", + "Join": "Join", + "Leave": "Leave", + "LoginToJoin": "Login to join", + "ToEnd:": "To end:", + "ToStart:": "To start:", + "days": "days", + "hrs": "hrs", + "min": "min", + "sec": "sec", + "Winners:": "Winners:", + "To{0}LuckyWinners": "to {0} lucky winner(s)", + "ActiveRaffles": "Active Raffles", + "UpcomingRaffles": "Upcoming Raffles", + "CompletedRaffles": "Completed Raffles", + "NoActiveRaffleTitle": "No active raffle is available at the moment.", + "NoActiveRaffleDescription": "No active raffle is available at the moment.", + "RaffleSubscriptionCodeInputMessage": "This raffle requires a registration code. Please enter the registration code below:", + "RaffleSubscriptionCodeInputErrorMessage": "The registration code is incorrect. Please try again.", + "GoodJob!": "Good Job!", + "RaffleJoinSuccessMessage": "You are successfully registered tor the raffle. You will be informed via email if you win the prize!", + "RaffleLoginAndRegisterMessage": "You should sign in to join a raffle. You can create an account for free if you haven't registered yet.", + "Ok": "Ok", + "SeeDetails": "See Details", + "WaitingForDraw": "Waiting for draw" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/en.json index ae3354617b..36cad167bd 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/en.json @@ -3,6 +3,7 @@ "texts": { "Buy": "Buy", "SeeBookDetails": "See Book Details", - "MasteringAbpFrameworkEBookDescription": "This book will help you gain a complete understanding of the framework and modern web application development techniques." + "MasteringAbpFrameworkEBookDescription": "This book will help you gain a complete understanding of the framework and modern web application development techniques.", + "Feedback": "Feedback" } } \ No newline at end of file diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/POST.md b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/POST.md new file mode 100644 index 0000000000..a68bc106a5 --- /dev/null +++ b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/POST.md @@ -0,0 +1,236 @@ +# Moving Background Job Execution To A Separate Application + +In this article, I will show you how to move the background job execution to a separate application. + +Here are some benefits of doing this: + +* If your background jobs consume high system resources (CPU, RAM or Disk), then you can deploy that background application to a dedicated server so it won't affect your application's performance. +* You can scale your background job application independently from your web application. For example, you can deploy multiple instances of your background job application to a Kubernetes cluster and scale it easily. + +Here are some disadvantages of doing this: + +* You need to deploy and maintain at least two applications instead of one. +* You need to implement a mechanism to share the common code between your applications. For example, you can create a shared project and add it to your applications as a project reference. + +## Source code + +You can find the source code of the application at [abpframework/abp-samples](https://github.com/abpframework/abp-samples/tree/master/SeparateBackgroundJob). + +You can check the PR to see the changes step by step: [abpframework/abp-samples#250](https://github.com/abpframework/abp-samples/pull/250) + +## Creating the Web Application + +First, we need to create a new web application using the ABP CLI: + +```bash +abp new SeparateBackgroundJob -t app +``` + +* Create a shared project named `SeparateBackgroundJob.Common.Shared` to share the `BackgroundJob` and `BackgroundJobArgs` classes between the web and job executor applications. +* Install the `Volo.Abp.BackgroundJobs.Abstractions` package to the `SeparateBackgroundJob.Common.Shared` project. + +Add the `SeparateBackgroundJobCommonSharedModule` class to the `SeparateBackgroundJob.Common.Shared` project: + +```csharp +[DependsOn(typeof(AbpBackgroundJobsAbstractionsModule))] +public class SeparateBackgroundJobCommonSharedModule : AbpModule +{ +} +``` + +Add the `MyReportJob` and `MyReportJobArgs` classes to the `SeparateBackgroundJob.Common.Shared` project: + +```csharp +public class MyReportJob : AsyncBackgroundJob, ITransientDependency +{ + public override Task ExecuteAsync(MyReportJobArgs args) + { + Logger.LogInformation("Executing MyReportJob with args: {0}", args.Content); + return Task.CompletedTask; + } +} + +public class MyReportJobArgs +{ + public string? Content { get; set; } +} +``` + +Add the `SeparateBackgroundJob.Common.Shared` project reference to the `SeparateBackgroundJob.Domain` project and add `SeparateBackgroundJobCommonSharedModule` to the `DependsOn` attribute of the `SeparateBackgroundJobDomainModule` class: + +```csharp +[DependsOn( + typeof(SeparateBackgroundJobDomainSharedModule), + typeof(AbpAuditLoggingDomainModule), + typeof(AbpBackgroundJobsDomainModule), + typeof(AbpFeatureManagementDomainModule), + typeof(AbpIdentityDomainModule), + typeof(AbpOpenIddictDomainModule), + typeof(AbpPermissionManagementDomainOpenIddictModule), + typeof(AbpPermissionManagementDomainIdentityModule), + typeof(AbpSettingManagementDomainModule), + typeof(AbpTenantManagementDomainModule), + typeof(AbpEmailingModule), + typeof(SeparateBackgroundJobCommonSharedModule) //Add this line +)] +public class SeparateBackgroundJobDomainModule : AbpModule +``` + +Open the `Index.cshtml` and replace the content with the following code: + +```csharp +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using SeparateBackgroundJob.Localization +@using Volo.Abp.Users +@model SeparateBackgroundJob.Web.Pages.IndexModel +@inject IHtmlLocalizer L +@inject ICurrentUser CurrentUser + +@section styles { + +} + +@section scripts { + +} + +
+ + + + Add NEW BACKGROUND JOB + + + +
+
+
+ +
+
+
+ +
+
+
+
+
+``` + +Open the `Index.cshtml.cs` and replace the content with the following code: + +```csharp +public class IndexModel : SeparateBackgroundJobPageModel +{ + private readonly IBackgroundJobManager _backgroundJobManager; + + [BindProperty(SupportsGet = true)] + public string? ReportContent { get; set; } + + public IndexModel(IBackgroundJobManager backgroundJobManager) + { + _backgroundJobManager = backgroundJobManager; + } + + public void OnGet() + { + + } + + public async Task OnPostAsync() + { + await _backgroundJobManager.EnqueueAsync(new MyReportJobArgs + { + Content = ReportContent + }); + + Alerts.Success("Job is queued!"); + } +} +``` + +Run the application and navigate to the home page. You should see the following page: + +![1](images/1.png) + +When you enter some text and click the **Add** button, the job will be queued and executed in the web application: + +## Creating the Console Application + +Now we split the background job execution to a separate console application. + +Open the `SeparateBackgroundJobWebModule` class to disable the background job execution in the web application: + +```csharp +public class SeparateBackgroundJobWebModule : AbpModule +{ + .... + + public override void ConfigureServices(ServiceConfigurationContext context) + { + ... + + //Disable background job execution in the web application + Configure(options => + { + options.IsJobExecutionEnabled = false; + }); + } + + ... +} +``` + +* Create a new console application using the ABP CLI: + +```bash +abp new BackgroundJobExecutor -t console +``` + +* Add the `BackgroundJobExecutor` project to the solution of the web application. +* Add the `SeparateBackgroundJob.Common.Shared` project reference to the `BackgroundJobExecutor` project. +* Install the `Volo.Abp.BackgroundJobs.EntityFrameworkCore` and `Volo.Abp.EntityFrameworkCore.SqlServer` packages to the `BackgroundJobExecutor` project. + +Update the `BackgroundJobExecutorModule` class as follows: + +```csharp +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpBackgroundJobsEntityFrameworkCoreModule), + typeof(AbpEntityFrameworkCoreSqlServerModule), + typeof(SeparateBackgroundJobCommonSharedModule) +)] +public class BackgroundJobExecutorModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.UseSqlServer(); + }); + } + + .... +} +``` + +Open the `appsettings.json` file to configure the [connection string](https://docs.abp.io/en/abp/latest/Connection-Strings#configure-the-connection-strings): + +```json +{ + "ConnectionStrings": { + "AbpBackgroundJobs": "Server=(LocalDb)\\MSSQLLocalDB;Database=SeparateBackgroundJob;Trusted_Connection=True" + } +} +``` + +> You must use the same connection string for the web application, `AbpBackgroundJobs` is the default connection string name for the background job module. + +The solution structure should look like this: + +![solution](images/solution.png) + +Now, run the web and console application. When you enter some text and click the **Add** button, the job will be queued and executed in the console application: + +![2](images/2.png) diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/1.png b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/1.png new file mode 100644 index 0000000000..37089353eb Binary files /dev/null and b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/1.png differ diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/2.png b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/2.png new file mode 100644 index 0000000000..0e56eee637 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/2.png differ diff --git a/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/solution.png b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/solution.png new file mode 100644 index 0000000000..ab7abe9a89 Binary files /dev/null and b/docs/en/Community-Articles/2023-09-20-Moving-Background-Job-Execution-To-A-Separate-Application/images/solution.png differ diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Zxcvbn/ZxcvbnScriptContributor.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Zxcvbn/ZxcvbnScriptContributor.cs new file mode 100644 index 0000000000..8c02fc2be2 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Packages/Volo/Abp/AspNetCore/Mvc/UI/Packages/Zxcvbn/ZxcvbnScriptContributor.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; + +namespace Volo.Abp.AspNetCore.Mvc.UI.Packages.Zxcvbn; + +public class ZxcvbnScriptContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/libs/zxcvbn/zxcvbn.js"); + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs index 731b21ea03..a42cbae457 100644 --- a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpAspNetCoreIntegratedTestBase.cs @@ -42,6 +42,7 @@ public abstract class AbpAspNetCoreIntegratedTestBase : AbpTestB protected virtual IHostBuilder CreateHostBuilder() { return Host.CreateDefaultBuilder() + .AddAppSettingsSecretsJson() .ConfigureWebHostDefaults(webBuilder => { if (typeof(TStartupModule).IsAssignableTo()) diff --git a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpWebApplicationFactoryIntegratedTest.cs b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpWebApplicationFactoryIntegratedTest.cs index c7b5f48ebe..9a6422ca97 100644 --- a/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpWebApplicationFactoryIntegratedTest.cs +++ b/framework/src/Volo.Abp.AspNetCore.TestBase/Volo/Abp/AspNetCore/TestBase/AbpWebApplicationFactoryIntegratedTest.cs @@ -27,7 +27,9 @@ public abstract class AbpWebApplicationFactoryIntegratedTest : WebAppl protected override IHost CreateHost(IHostBuilder builder) { - builder.ConfigureServices(ConfigureServices); + builder + .AddAppSettingsSecretsJson() + .ConfigureServices(ConfigureServices); return base.CreateHost(builder); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj index a6bb742585..ee064c4b67 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj +++ b/framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj @@ -23,6 +23,7 @@ + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index a672b0b563..5b00d15c9e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -8,12 +8,14 @@ using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using StackExchange.Redis; using Volo.Abp.Cli.Args; using Volo.Abp.Cli.Bundling; using Volo.Abp.Cli.Commands.Services; using Volo.Abp.Cli.LIbs; using Volo.Abp.Cli.ProjectBuilding; using Volo.Abp.Cli.ProjectBuilding.Building; +using Volo.Abp.Cli.ProjectBuilding.Templates.App; using Volo.Abp.Cli.ProjectModification; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; @@ -89,6 +91,8 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien var projectArgs = await GetProjectBuildArgsAsync(commandLineArgs, template, projectName); + await CheckCreatingRequirements(projectArgs); + var result = await TemplateProjectBuilder.BuildAsync( projectArgs ); @@ -97,6 +101,8 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien Logger.LogInformation($"'{projectName}' has been successfully created to '{projectArgs.OutputFolder}'"); + await CheckCreatedRequirements(projectArgs); + ConfigureNpmPackagesForTheme(projectArgs); await CreateOpenIddictPfxFilesAsync(projectArgs); await RunGraphBuildForMicroserviceServiceTemplate(projectArgs); @@ -120,6 +126,46 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien OpenRelatedWebPage(projectArgs, template, isTiered, commandLineArgs); } + private Task CheckCreatingRequirements(ProjectBuildArgs projectArgs) + { + return Task.CompletedTask; + } + + private async Task CheckCreatedRequirements(ProjectBuildArgs projectArgs) + { + var errors = new List(); + + if (projectArgs.ExtraProperties.ContainsKey("PreRequirements:Redis")) + { + var isConnected = false; + try + { + var redis = await ConnectionMultiplexer.ConnectAsync("127.0.0.1", options => options.ConnectTimeout = 3000); + isConnected = redis.IsConnected; + } + catch (Exception e) + { + // ignored + } + finally + { + if (!isConnected) + { + errors.Add("\t* Redis is not installed or not running on your computer."); + } + } + } + + if (errors.Any()) + { + Logger.LogWarning("NOTICE: The following tools are required to run your solution."); + foreach (var error in errors) + { + Logger.LogWarning(error); + } + } + } + public string GetUsageInfo() { var sb = new StringBuilder(); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs index cf697fd899..4eff9df5e6 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs @@ -484,6 +484,11 @@ public abstract class ProjectCreationCommandBase protected Task CreateOpenIddictPfxFilesAsync(ProjectBuildArgs projectArgs) { + if (!projectArgs.ExtraProperties.ContainsKey(nameof(RandomizeAuthServerPassPhraseStep))) + { + return Task.CompletedTask; + } + var module = projectArgs.ExtraProperties[nameof(RandomizeAuthServerPassPhraseStep)]; if (string.IsNullOrWhiteSpace(module)) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs index 88bdc27973..d33aa103ba 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; +using Volo.Abp.Cli.ProjectBuilding.Templates; namespace Volo.Abp.Cli.ProjectBuilding.Building; @@ -28,7 +29,14 @@ public abstract class TemplateInfo public virtual IEnumerable GetCustomSteps(ProjectBuildContext context) { - return Array.Empty(); + var steps = new List(); + ConfigureCheckPreRequirements(context, steps); + return steps; + } + + protected void ConfigureCheckPreRequirements(ProjectBuildContext context, List steps) + { + steps.Add(new CheckRedisPreRequirements()); } public bool IsPro() diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs index ca5f5ceb61..edf8728305 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Building.Steps; @@ -20,7 +21,7 @@ public abstract class AppNoLayersTemplateBase : AppTemplateBase public override IEnumerable GetCustomSteps(ProjectBuildContext context) { - var steps = new List(); + var steps = base.GetCustomSteps(context).ToList(); switch (context.BuildArgs.DatabaseProvider) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs index e8522f6f19..5c9b4f4864 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateBase.cs @@ -28,7 +28,7 @@ public abstract class AppTemplateBase : TemplateInfo public override IEnumerable GetCustomSteps(ProjectBuildContext context) { - var steps = new List(); + var steps = base.GetCustomSteps(context).ToList(); ConfigureTenantSchema(context, steps); SwitchDatabaseProvider(context, steps); @@ -165,7 +165,11 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new RemoveFolderStep("/angular")); } - if (context.BuildArgs.MobileApp != MobileApp.ReactNative) + if(context.BuildArgs.MobileApp == MobileApp.ReactNative) + { + context.Symbols.Add("mobile:react-native"); + } + else { steps.Add(new RemoveFolderStep(MobileApp.ReactNative.GetFolderName().EnsureStartsWith('/'))); } @@ -174,6 +178,7 @@ public abstract class AppTemplateBase : TemplateInfo { steps.Add(new MauiChangeApplicationIdGuidStep()); steps.Add(new MauiChangePortStep()); + context.Symbols.Add("mobile:maui"); } else { @@ -192,10 +197,12 @@ public abstract class AppTemplateBase : TemplateInfo context.BuildArgs.ExtraProperties.ContainsKey("separate-auth-server")) { steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Public")); + context.Symbols.Add("ui:mvc-public-host"); } else { steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.Web.Public.Host")); + context.Symbols.Add("ui:mvc-public"); } } } @@ -399,6 +406,7 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.HttpApi.Host")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.AuthServer")); steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds", "MyCompanyName.MyProjectName.HttpApi.Host")); + context.Symbols.Add("HostWithIds"); steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44305")); } } @@ -424,6 +432,7 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.IdentityServer")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.AuthServer")); steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds", "MyCompanyName.MyProjectName.HttpApi.Host")); + context.Symbols.Add("HostWithIds"); steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44305")); } @@ -517,6 +526,7 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.IdentityServer")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.AuthServer")); steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds", "MyCompanyName.MyProjectName.HttpApi.Host")); + context.Symbols.Add("HostWithIds"); steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44305")); } @@ -554,6 +564,7 @@ public abstract class AppTemplateBase : TemplateInfo steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.IdentityServer")); steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.AuthServer")); steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.HttpApi.HostWithIds", "MyCompanyName.MyProjectName.HttpApi.Host")); + context.Symbols.Add("HostWithIds"); steps.Add(new AppTemplateChangeConsoleTestClientPortSettingsStep("44305")); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/CheckRedisPreRequirements.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/CheckRedisPreRequirements.cs new file mode 100644 index 0000000000..aee6da8f99 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/CheckRedisPreRequirements.cs @@ -0,0 +1,17 @@ +using System; +using System.Linq; +using Volo.Abp.Cli.ProjectBuilding.Building; + +namespace Volo.Abp.Cli.ProjectBuilding.Templates; + +public class CheckRedisPreRequirements : ProjectBuildPipelineStep +{ + public override void Execute(ProjectBuildContext context) + { + var modules = context.Files.Where(f => f.Name.EndsWith("Module.cs", StringComparison.OrdinalIgnoreCase)); + if (modules.Any(module => module.Content.Contains("Redis:Configuration"))) + { + context.BuildArgs.ExtraProperties["PreRequirements:Redis"] = "true"; + } + } +} diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs index 13674458ee..e5ce4a0f84 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceServiceTemplateBase.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using JetBrains.Annotations; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Building.Steps; @@ -33,14 +34,14 @@ public abstract class MicroserviceServiceTemplateBase : TemplateInfo public override IEnumerable GetCustomSteps(ProjectBuildContext context) { - var steps = new List(); + var steps = base.GetCustomSteps(context).ToList(); DeleteUnrelatedUiProject(context, steps); SetRandomPortForHostProject(context, steps); RandomizeStringEncryption(context, steps); RandomizeAuthServerPassPhrase(context, steps); ChangeConnectionString(context, steps); - + return steps; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs index b8d320fb45..cb7722da10 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Microservice/MicroserviceTemplateBase.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Building.Steps; @@ -19,7 +20,7 @@ public abstract class MicroserviceTemplateBase : TemplateInfo public override IEnumerable GetCustomSteps(ProjectBuildContext context) { - var steps = new List(); + var steps = base.GetCustomSteps(context).ToList(); DeleteUnrelatedProjects(context, steps); RandomizeStringEncryption(context, steps); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs index 5229bb167f..428c1061a1 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using JetBrains.Annotations; using Volo.Abp.Cli.ProjectBuilding.Building; using Volo.Abp.Cli.ProjectBuilding.Building.Steps; @@ -21,7 +22,7 @@ public abstract class ModuleTemplateBase : TemplateInfo public override IEnumerable GetCustomSteps(ProjectBuildContext context) { - var steps = new List(); + var steps = base.GetCustomSteps(context).ToList(); DeleteUnrelatedProjects(context, steps); RandomizeSslPorts(context, steps); diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs index f31feff873..88bf37982e 100644 --- a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs @@ -18,11 +18,12 @@ public static class ConfigurationHelper var builder = new ConfigurationBuilder() .SetBasePath(options.BasePath!) - .AddJsonFile(options.FileName + ".json", optional: options.Optional, reloadOnChange: options.ReloadOnChange); + .AddJsonFile(options.FileName + ".json", optional: options.Optional, reloadOnChange: options.ReloadOnChange) + .AddJsonFile(options.FileName + ".secrets.json", optional: true, reloadOnChange: options.ReloadOnChange); if (!options.EnvironmentName.IsNullOrEmpty()) { - builder = builder.AddJsonFile($"{options.FileName}.{options.EnvironmentName}.json", optional: options.Optional, reloadOnChange: options.ReloadOnChange); + builder = builder.AddJsonFile($"{options.FileName}.{options.EnvironmentName}.json", optional: true, reloadOnChange: options.ReloadOnChange); } if (options.EnvironmentName == "Development") diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs index 5923949b0e..a7d2c4f9d3 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/AbpFluentValidationConventionalRegistrar.cs @@ -24,6 +24,7 @@ public class AbpFluentValidationConventionalRegistrar : DefaultConventionalRegis { return new List() { + type, typeof(IValidator<>).MakeGenericType(GetFirstGenericArgumentOrNull(type, 1)!) }; } diff --git a/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/JQuery/JQueryProxyScriptGenerator.cs b/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/JQuery/JQueryProxyScriptGenerator.cs index b5973eed8a..18af3e0661 100644 --- a/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/JQuery/JQueryProxyScriptGenerator.cs +++ b/framework/src/Volo.Abp.Http/Volo/Abp/Http/ProxyScripting/Generators/JQuery/JQueryProxyScriptGenerator.cs @@ -114,7 +114,21 @@ public class JQueryProxyScriptGenerator : IProxyScriptGenerator, ITransientDepen if (versionParam != null) { var version = FindBestApiVersion(action); - script.AppendLine($" var {ProxyScriptingJsFuncHelper.NormalizeJsVariableName(versionParam.Name)} = api_version ? api_version : '{version}';"); + if (parameterList.Contains("api_version")) + { + script.AppendLine($" var {ProxyScriptingJsFuncHelper.NormalizeJsVariableName(versionParam.Name)} = api_version ? api_version : '{version}';"); + } + else + { + var apiVersion = action.Parameters.FirstOrDefault(p => + p.BindingSourceId.IsIn(ParameterBindingSources.ModelBinding, ParameterBindingSources.Query) && + p.Name == "api-version"); + if (apiVersion != null && parameterList.Contains(apiVersion.NameOnMethod)) + { + var apiVersionVariable = ProxyScriptingJsFuncHelper.GetParamNameInJsFunc(apiVersion); + script.AppendLine($" {apiVersionVariable} = {apiVersionVariable} ? {apiVersionVariable} : '{version}';"); + } + } } script.AppendLine(" return abp.ajax($.extend(true, {"); diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs index 37e6b07b8f..46e16bc292 100644 --- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs +++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs @@ -103,6 +103,17 @@ public class ApplicationService_FluentValidation_Tests : AbpIntegratedTest>(); + validator.GetType().ShouldBe(typeof(MyMethodInputValidator)); + + validator = ServiceProvider.GetService(); + validator.GetType().ShouldBe(typeof(MyMethodInputValidator)); + } + [DependsOn(typeof(AbpAutofacModule))] [DependsOn(typeof(AbpFluentValidationModule))] public class TestModule : AbpModule diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js index a101635d73..04ac2a6fa8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/create.js @@ -253,12 +253,13 @@ $(function () { initEditor(); var editor; - + var addWidgetButton; function initEditor() { var $editorContainer = $("#ContentEditor"); var inputName = $editorContainer.data('input-id'); var $editorInput = $('#' + inputName); var initialValue = $editorInput.val(); + addWidgetButton = createAddWidgetButton(); editor = new toastui.Editor({ el: $editorContainer[0], @@ -279,7 +280,7 @@ $(function () { ['code', 'codeblock'], // Using Option: Customize the last button [{ - el: createAddWidgetButton(), + el: addWidgetButton, command: 'bold', tooltip: 'Add Widget' }] @@ -334,20 +335,28 @@ $(function () { editor.insertText(txt); }); + var $previewArea; $('.tab-item').on('click', function () { if ($(this).attr("aria-label") == 'Preview' && editor.isMarkdownMode()) { + if(!$previewArea){ + $previewArea = $("#ContentEditor .toastui-editor-md-preview"); + $previewArea.replaceWith(""); + } + + $previewArea.attr("srcdoc", ''); + + addWidgetButton.disabled = true; let content = editor.getMarkdown(); localStorage.setItem('content', content); $.post("/CmsKitCommonWidgets/ContentPreview", { content: content }, function (result) { - editor.setHTML(result); - - var highllightedText = $('#ContentEditor').find('.toastui-editor-md-preview-highlight'); - highllightedText.removeClass('toastui-editor-md-preview-highlight'); + $previewArea = $("#previewArea"); + $previewArea.attr("srcdoc", result); }); } else if ($(this).attr("aria-label") == 'Write') { + addWidgetButton.disabled = false; var retrievedObject = localStorage.getItem('content'); editor.setMarkdown(retrievedObject); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js index d14194ecb5..d22121f8c9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/BlogPosts/update.js @@ -164,12 +164,15 @@ $(function () { initEditor(); var editor; + var addWidgetButton; function initEditor() { var $editorContainer = $("#ContentEditor"); var inputName = $editorContainer.data('input-id'); var $editorInput = $('#' + inputName); var initialValue = $editorInput.val(); + addWidgetButton = createAddWidgetButton(); + editor = new toastui.Editor({ el: $editorContainer[0], usageStatistics: false, @@ -189,7 +192,7 @@ $(function () { ['code', 'codeblock'], // Using Option: Customize the last button [{ - el: createAddWidgetButton(), + el: addWidgetButton, command: 'bold', tooltip: 'Add Widget' }] @@ -255,20 +258,28 @@ $(function () { editor.insertText(txt); }); + var $previewArea; $('.tab-item').on('click', function () { if ($(this).attr("aria-label") == 'Preview' && editor.isMarkdownMode()) { + if(!$previewArea){ + $previewArea = $("#ContentEditor .toastui-editor-md-preview"); + $previewArea.replaceWith(""); + } + + $previewArea.attr("srcdoc", ''); + + addWidgetButton.disabled = true; let content = editor.getMarkdown(); localStorage.setItem('content', content); $.post("/CmsKitCommonWidgets/ContentPreview", { content: content }, function (result) { - editor.setHTML(result); - - var highllightedText = $('#ContentEditor').find('.toastui-editor-md-preview-highlight'); - highllightedText.removeClass('toastui-editor-md-preview-highlight'); + $previewArea = $("#previewArea"); + $previewArea.attr("srcdoc", result); }); } else if ($(this).attr("aria-label") == 'Write') { + addWidgetButton.disabled = false; var retrievedObject = localStorage.getItem('content'); editor.setMarkdown(retrievedObject); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/DefaultContentDto.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/DefaultContentDto.cs index fb4b81d79b..5bddbbe470 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/DefaultContentDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/DefaultContentDto.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using JetBrains.Annotations; namespace Volo.CmsKit.Contents; @@ -7,4 +8,11 @@ namespace Volo.CmsKit.Contents; public class DefaultContentDto : IContent { public List ContentFragments { get; set; } + + public bool AllowHtmlTags { get; set; } = true; + + public bool PreventXSS { get; set; } = true; + + [CanBeNull] + public string ReferralLink { get; set; } = null; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/IContent.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/IContent.cs index 93165db1ae..543b67dc74 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/IContent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Application.Contracts/Volo/CmsKit/Contents/IContent.cs @@ -4,5 +4,11 @@ namespace Volo.CmsKit.Contents; public interface IContent { - public List ContentFragments { get; set; } + List ContentFragments { get; set; } + + bool AllowHtmlTags { get; set; } + + bool PreventXSS { get; set; } + + string ReferralLink { get; set; } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs index 2251f6d0cd..f71f9aeebf 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/ContentPreviewViewComponent.cs @@ -25,7 +25,9 @@ public class ContentPreviewViewComponent : AbpViewComponent return View("~/Pages/CmsKit/Components/ContentPreview/Default.cshtml", new DefaultContentDto { - ContentFragments = fragments + ContentFragments = fragments, + AllowHtmlTags = true, + PreventXSS = false }); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/Default.cshtml index 450eb46f20..82c3bc36f0 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/ContentPreview/Default.cshtml @@ -8,8 +8,5 @@ Layout = ThemeManager.CurrentTheme.GetEmptyLayout(); } - - - @await Component.InvokeAsync(typeof(ContentFragmentViewComponent), Model) - - \ No newline at end of file +
@await Component.InvokeAsync(typeof(ContentFragmentViewComponent), Model)
+ diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentFragment.cshtml b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentFragment.cshtml index 3ac2080529..80834dd7fc 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentFragment.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Pages/CmsKit/Components/Contents/ContentFragment.cshtml @@ -14,7 +14,7 @@ { if (contentFragment.Type == ContentConsts.Markdown) { - @Html.Raw(await MarkdownRenderer.RenderAsync(contentFragment.GetProperty("Content"))) + @Html.Raw(await MarkdownRenderer.RenderAsync(contentFragment.GetProperty("Content"), Model.ContentDto.AllowHtmlTags, Model.ContentDto.PreventXSS, Model.ContentDto.ReferralLink)) } else if (contentFragment.Type == ContentConsts.Widget) { diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Blogs/BlogConsts.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Blogs/BlogConsts.cs index 3c57836221..a811d870b6 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Blogs/BlogConsts.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Blogs/BlogConsts.cs @@ -3,5 +3,8 @@ public class BlogConsts { public static int MaxNameLength { get; set; } = 64; + public static int MaxSlugLength { get; set; } = 64; + + public const string PreventXssFeatureName = "CmsKit.BlogPost.PreventXssFeature"; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/BlogPostScrollIndexFeature.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/BlogPostScrollIndexFeature.cs index 9f03f973e1..132f215d93 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/BlogPostScrollIndexFeature.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalFeatures/BlogPostScrollIndexFeature.cs @@ -3,7 +3,6 @@ using Volo.Abp.GlobalFeatures; namespace Volo.CmsKit.GlobalFeatures; - [GlobalFeatureName(Name)] public class BlogPostScrollIndexFeature : GlobalFeature { diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json index 3119bf618c..747bb8c53a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "التقييمات", "CmsKit.Reactions": "تفاعلات", "CmsKit.Tags": "العلامات", + "CmsKit.BlogPost.PreventXssFeature": "منع XSS", "CmsKit:0002": "المحتوى موجود بالفعل!", "CmsKit:0003": "الكيان {0} غير قابل للعلامة.", "CmsKit:Blog:0001": "slug المحدد ({Slug}) موجود بالفعل!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json index 8ae9479b06..a38883b40f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Hodnocení", "CmsKit.Reactions": "Reakce", "CmsKit.Tags": "Tagy", + "CmsKit.BlogPost.PreventXssFeature": "Zabraňte XSS", "CmsKit:0002": "Obsah již existuje!", "CmsKit:0003": "Entitu {0} nelze označit.", "CmsKit:Blog:0001": "Daný slimák ({Slug}) již existuje!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json index 857f7f1e1a..9fbecee488 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Bewertungen", "CmsKit.Reactions": "Reaktionen", "CmsKit.Tags": "Stichworte", + "CmsKit.BlogPost.PreventXssFeature": "XSS-Prävention", "CmsKit:0002": "Inhalt ist bereits vorhanden!", "CmsKit:0003": "Die Entität {0} kann nicht mit Tags versehen werden.", "CmsKit:Blog:0001": "Die angegebene Schnecke ({Slug}) existiert bereits!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json index 7a838b120a..73986c9912 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Βαθμολογία", "CmsKit.Reactions": "Αντιδράσεις", "CmsKit.Tags": "Ετικέτες", + "CmsKit.BlogPost.PreventXssFeature": "Αποτροπή XSS", "CmsKit:0002": "Το περιεχόμενο υπάρχει ήδη!", "CmsKit:0003": "Η οντότητα {0} δεν μπορεί να επισημανθεί.", "CmsKit:Blog:0001": "Το δεδομένο slug ({Slug}) υπάρχει ήδη!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json index 327f924753..a5adbf0a05 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json @@ -1,228 +1,229 @@ { "culture": "en", - "texts": { - "AddSubMenuItem": "Add Sub Menu Item", - "AreYouSure": "Are You Sure?", - "BlogDeletionConfirmationMessage": "The blog '{0}' will be deleted. Are you sure?", - "BlogFeatureNotAvailable": "This feature is not available now. Enable with 'GlobalFeatureManager' to use it.", - "BlogId": "Blog", - "BlogPostDeletionConfirmationMessage": "The blog post '{0}' will be deleted. Are you sure?", - "BlogPosts": "Blog Posts", - "Blogs": "Blogs", - "ChoosePreference": "Choose Preference...", - "Cms": "CMS", - "CmsKit.Comments": "Comments", - "CmsKit.Ratings": "Ratings", - "CmsKit.Reactions": "Reactions", - "CmsKit.Tags": "Tags", - "CmsKit:0002": "Content already exists!", - "CmsKit:0003": "The entity {0} is not taggable.", - "CmsKit:Blog:0001": "The given slug ({Slug}) already exists!", - "CmsKit:BlogPost:0001": "The given slug already exists!", - "CmsKit:Comments:0001": "The entity {EntityType} is not commentable.", - "CmsKit:Media:0001": "'{Name}' is not a valid media name.", - "CmsKit:Media:0002": "The entity can't have media.", - "CmsKit:Page:0001": "The given url ({Slug}) already exists. Please try with different url.", - "CmsKit:Rating:0001": "The entity {EntityType} can't be rated.", - "CmsKit:Reaction:0001": "The entity {EntityType} can't have reactions.", - "CmsKit:Tag:0002": "The entity is not taggable!", - "CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.", - "CommentDeletionConfirmationMessage": "This comment and all replies will be deleted!", - "Comments": "Comments", - "Content": "Content", - "ContentDeletionConfirmationMessage": "Are you sure to delete this content?", - "Contents": "Contents", - "CoverImage": "Cover Image", - "CreateBlogPostPage": "New Blog Post", - "CreationTime": "Creation Time", - "Delete": "Delete", - "Detail": "Detail", - "Details": "Details", - "DisplayName": "Display Name", - "DoYouPreferAdditionalEmails": "Do you prefer additional emails?", - "Edit": "Edit", - "EndDate": "End Date", - "EntityId": "Entity Id", - "EntityType": "Entity Type", - "ExportCSV": "Export CSV", - "Features": "Features", - "GenericDeletionConfirmationMessage": "Are you sure to delete '{0}'?", - "IsActive": "Active", - "LastModification": "Last Modification", - "LastModificationTime": "Last Modification Time", - "LoginToAddComment": "Login to add comment", - "LoginToRate": "Login to rate", - "LoginToReact": "Login to react", - "LoginToReply": "Login to reply", - "MainMenu": "Main Menu", - "MakeMainMenu": "Make Main Menu", - "Menu:CMS": "CMS", - "Menus": "Menus", - "MenuDeletionConfirmationMessage": "The menu '{0}' will be deleted. Are you sure?", - "MenuItemDeletionConfirmationMessage": "Are sure to delete this menu item?", - "MenuItemMoveConfirmMessage": "Are you sure you want to move '{0}' under '{1}'?", - "MenuItems": "Menu Items", - "Message": "Message", - "MessageDeletionConfirmationMessage": "This comment will be deleted completely.", - "NewBlog": "New Blog", - "NewBlogPost": "New Blog Post", - "NewMenu": "New Menu", - "NewMenuItem": "New Root Menu Item", - "NewPage": "New Page", - "NewTag": "New Tag", - "NoMenuItems": "There is no menu item yet!", - "OK": "OK", - "PageDeletionConfirmationMessage": "Are you sure to delete this page?", - "PageId": "Page", - "Pages": "Pages", - "PageSlugInformation": "Slug is used on url. Your url will be '/{{slug}}'.", - "Permission:BlogManagement": "Blog Management", - "Permission:BlogManagement.Create": "Create", - "Permission:BlogManagement.Delete": "Delete", - "Permission:BlogManagement.Features": "Features", - "Permission:BlogManagement.Update": "Update", - "Permission:BlogPostManagement": "Blog Post Management", - "Permission:BlogPostManagement.Create": "Create", - "Permission:BlogPostManagement.Delete": "Delete", - "Permission:BlogPostManagement.Update": "Update", - "Permission:BlogPostManagement.Publish": "Publish", - "Permission:CmsKit": "CmsKit Admin", - "Permission:Comments": "Comment Management", - "Permission:Comments.Delete": "Delete", - "Permission:Contents": "Content Management", - "Permission:Contents.Create": "Create Content", - "Permission:Contents.Delete": "Delete Content", - "Permission:Contents.Update": "Update Content", - "Permission:MediaDescriptorManagement": "Media Management", - "Permission:MediaDescriptorManagement:Create": "Create", - "Permission:MediaDescriptorManagement:Delete": "Delete", - "Permission:MenuItemManagement": "Menu Item Management", - "Permission:MenuItemManagement.Create": "Create", - "Permission:MenuItemManagement.Delete": "Delete", - "Permission:MenuItemManagement.Update": "Update", - "Permission:MenuManagement": "Menu Management", - "Permission:MenuManagement.Create": "Create", - "Permission:MenuManagement.Delete": "Delete", - "Permission:MenuManagement.Update": "Update", - "Permission:Menus": "Menu Management", - "Permission:Menus.Create": "Create", - "Permission:Menus.Delete": "Delete", - "Permission:Menus.Update": "Update", - "Permission:PageManagement": "Page Management", - "Permission:PageManagement:Create": "Create", - "Permission:PageManagement:Delete": "Delete", - "Permission:PageManagement:Update": "Update", - "Permission:PageManagement:SetAsHomePage": "Set As Home Page", - "Permission:TagManagement": "Tag Management", - "Permission:TagManagement.Create": "Create", - "Permission:TagManagement.Delete": "Delete", - "Permission:TagManagement.Update": "Update", - "Permission:GlobalResources": "Global Resources", - "Permission:CmsKitPublic": "CmsKit Public", - "Permission:Comments.DeleteAll": "Delete All", - "PickYourReaction": "Pick your reaction", - "Rating": "Rating", - "RatingUndoMessage": "Your rating will be undo.", - "Reactions": "Reactions", - "Read": "Read", - "RepliesToThisComment": "Replies to this comment", - "Reply": "Reply", - "ReplyTo": "Reply to", - "SamplePageMessage": "A sample page for the Pro module", - "SaveChanges": "Save Changes", - "Script": "Script", - "SelectAll": "Select All", - "Send": "Send", - "SendMessage": "Send Message", - "SelectedAuthor": "Author", - "ShortDescription": "Short description", - "Slug": "Slug", - "Source": "Source", - "SourceUrl": "Source Url", - "Star": "Star", - "StartDate": "Start Date", - "Style": "Style", - "Subject": "Subject", - "SubjectPlaceholder": "Please type a subject", - "Submit": "Submit", - "Subscribe": "Subscribe", - "SuccessfullySaved": "Successfully saved!", - "TagDeletionConfirmationMessage": "Are you sure to delete '{0}' tag?", - "Tags": "Tags", - "Text": "Text", - "ThankYou": "Thank you", - "Title": "Title", - "Undo": "Undo", - "Update": "Update", - "UpdatePreferenceSuccessMessage": "Your preferences have been saved.", - "UpdateYourEmailPreferences": "Update your email preferences", - "UnMakeMainMenu": "Unmake Main Menu", - "UploadFailedMessage": "Upload failed.", - "UserId": "User Id", - "Username": "Username", - "YourComment": "Your comment", - "YourEmailAddress": "Your e-mail address", - "YourFullName": "Your full name", - "YourMessage": "Your Message", - "YourReply": "Your reply", - "MarkdownSupported": "Markdown supported.", - "GlobalResources": "Global Resources", - "SavedSuccessfully": "Saved successfully", - "CmsKit.BlogPost.Status.0": "Draft", - "CmsKit.BlogPost.Status.1": "Published", - "CmsKit.BlogPost.Status.2": "Waiting for review", - "BlogPostPublishConfirmationMessage": "Are you sure to publish the blog post \"{0}\"?", - "SuccessfullyPublished": "Successfully published!", - "Draft": "Draft", - "Publish": "Publish", - "BlogPostDraftConfirmationMessage": "Are you sure to set the blog post \"{0}\" as draft?", - "BlogPostSendToReviewConfirmationMessage": "Are you sure to send the blog post \"{0}\" to admin review for publishing?", - "SaveAsDraft": "Save as draft", - "SendToReview": "Send to review", - "SendToReviewToPublish": "Send to review to publish", - "BlogPostSendToReviewSuccessMessage": "The blog post \"{0}\" has been sent to admin review for publishing.", - "HasBlogPostWaitingForReviewMessage": "You have a blog post waiting for review. Click to list.", - "SelectAStatus": "Select a status", - "Status": "Status", - "CmsKit.BlogPost.ScrollIndex": "Quick navigation bar in blog posts", - "Add": "Add", - "AddWidget": "Add Widget", - "PleaseConfigureWidgets": "Please configure widgets", - "SelectAnAuthor": "Select an Author", - "InThisDocument": "In This Document", - "GoToTop": "Go To Top", - "SetAsHomePage": "Change Home Page Status", - "CompletedSettingAsHomePage": "Set as home page", - "IsHomePage": "Is Home Page", - "RemovedSettingAsHomePage": "Removed setting the home page", - "Feature:CmsKitGroup": "Cms Kit", - "Feature:BlogEnable": "Blogpost", - "Feature:BlogEnableDescription": "CMS Kit's blogpost system that allows create blogs and posts dynamically in the application.", - "Feature:CommentEnable": "Commenting", - "Feature:CommentEnableDescription": "CMS Kit's comment system allows commenting on entities such as BlogPost.", - "Feature:GlobalResourceEnable": "Global resourcing", - "Feature:GlobalResourceEnableDescription": "CMS Kit's global resoruces feature that allows managing global styles & scripts.", - "Feature:MenuEnable": "Menu", - "Feature:MenuEnableDescription": "CMS Kit's dynamic menu system that allows adding/removing application menus dynamically.", - "Feature:PageEnable": "Paging", - "Feature:PageEnableDescription": "CMS Kit's page system that allows creating static pages with specific URL.", - "Feature:RatingEnable": "Rating", - "Feature:RatingEnableDescription": "CMS Kit's rating system that allows users to rate entities such as BlogPost.", - "Feature:ReactionEnable": "Reaction", - "Feature:ReactionEnableDescription": "CMS Kit's reaction system that allows users to send reactions to entities such as BlogPost, Comments, etc.", - "Feature:TagEnable": "Taging", - "Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost.", - "DeleteBlogPostMessage": "The blog will be deleted. Are you sure?", - "CaptchaCode": "Captcha code", - "CommentTextRequired": "Comment is required", - "CaptchaCodeErrorMessage": "The answer you entered for the CAPTCHA was not correct. Please try again", - "CaptchaCodeMissingMessage": "The captcha code is missing!", - "UnAllowedExternalUrlMessage": "You included an unallowed external URL. Please try again without the external URL.", - "URL": "URL", - "PopularTags": "Popular Tags", - "RemoveCoverImageConfirmationMessage": "Are you sure you want to remove the cover image?", - "RemoveCoverImage": "Remove cover image", - "CssClass": "CSS Class", - "TagsHelpText": "Tags should be comma-separated (e.g.: tag1, tag2, tag3)" - } + "texts": { + "AddSubMenuItem": "Add Sub Menu Item", + "AreYouSure": "Are You Sure?", + "BlogDeletionConfirmationMessage": "The blog '{0}' will be deleted. Are you sure?", + "BlogFeatureNotAvailable": "This feature is not available now. Enable with 'GlobalFeatureManager' to use it.", + "BlogId": "Blog", + "BlogPostDeletionConfirmationMessage": "The blog post '{0}' will be deleted. Are you sure?", + "BlogPosts": "Blog Posts", + "Blogs": "Blogs", + "ChoosePreference": "Choose Preference...", + "Cms": "CMS", + "CmsKit.Comments": "Comments", + "CmsKit.Ratings": "Ratings", + "CmsKit.Reactions": "Reactions", + "CmsKit.Tags": "Tags", + "CmsKit:0002": "Content already exists!", + "CmsKit:0003": "The entity {0} is not taggable.", + "CmsKit:Blog:0001": "The given slug ({Slug}) already exists!", + "CmsKit:BlogPost:0001": "The given slug already exists!", + "CmsKit:Comments:0001": "The entity {EntityType} is not commentable.", + "CmsKit:Media:0001": "'{Name}' is not a valid media name.", + "CmsKit:Media:0002": "The entity can't have media.", + "CmsKit:Page:0001": "The given url ({Slug}) already exists. Please try with different url.", + "CmsKit:Rating:0001": "The entity {EntityType} can't be rated.", + "CmsKit:Reaction:0001": "The entity {EntityType} can't have reactions.", + "CmsKit:Tag:0002": "The entity is not taggable!", + "CommentAuthorizationExceptionMessage": "Those comments are not allowed for public display.", + "CommentDeletionConfirmationMessage": "This comment and all replies will be deleted!", + "Comments": "Comments", + "Content": "Content", + "ContentDeletionConfirmationMessage": "Are you sure to delete this content?", + "Contents": "Contents", + "CoverImage": "Cover Image", + "CreateBlogPostPage": "New Blog Post", + "CreationTime": "Creation Time", + "Delete": "Delete", + "Detail": "Detail", + "Details": "Details", + "DisplayName": "Display Name", + "DoYouPreferAdditionalEmails": "Do you prefer additional emails?", + "Edit": "Edit", + "EndDate": "End Date", + "EntityId": "Entity Id", + "EntityType": "Entity Type", + "ExportCSV": "Export CSV", + "Features": "Features", + "GenericDeletionConfirmationMessage": "Are you sure to delete '{0}'?", + "IsActive": "Active", + "LastModification": "Last Modification", + "LastModificationTime": "Last Modification Time", + "LoginToAddComment": "Login to add comment", + "LoginToRate": "Login to rate", + "LoginToReact": "Login to react", + "LoginToReply": "Login to reply", + "MainMenu": "Main Menu", + "MakeMainMenu": "Make Main Menu", + "Menu:CMS": "CMS", + "Menus": "Menus", + "MenuDeletionConfirmationMessage": "The menu '{0}' will be deleted. Are you sure?", + "MenuItemDeletionConfirmationMessage": "Are sure to delete this menu item?", + "MenuItemMoveConfirmMessage": "Are you sure you want to move '{0}' under '{1}'?", + "MenuItems": "Menu Items", + "Message": "Message", + "MessageDeletionConfirmationMessage": "This comment will be deleted completely.", + "NewBlog": "New Blog", + "NewBlogPost": "New Blog Post", + "NewMenu": "New Menu", + "NewMenuItem": "New Root Menu Item", + "NewPage": "New Page", + "NewTag": "New Tag", + "NoMenuItems": "There is no menu item yet!", + "OK": "OK", + "PageDeletionConfirmationMessage": "Are you sure to delete this page?", + "PageId": "Page", + "Pages": "Pages", + "PageSlugInformation": "Slug is used on url. Your url will be '/{{slug}}'.", + "Permission:BlogManagement": "Blog Management", + "Permission:BlogManagement.Create": "Create", + "Permission:BlogManagement.Delete": "Delete", + "Permission:BlogManagement.Features": "Features", + "Permission:BlogManagement.Update": "Update", + "Permission:BlogPostManagement": "Blog Post Management", + "Permission:BlogPostManagement.Create": "Create", + "Permission:BlogPostManagement.Delete": "Delete", + "Permission:BlogPostManagement.Update": "Update", + "Permission:BlogPostManagement.Publish": "Publish", + "Permission:CmsKit": "CmsKit Admin", + "Permission:Comments": "Comment Management", + "Permission:Comments.Delete": "Delete", + "Permission:Contents": "Content Management", + "Permission:Contents.Create": "Create Content", + "Permission:Contents.Delete": "Delete Content", + "Permission:Contents.Update": "Update Content", + "Permission:MediaDescriptorManagement": "Media Management", + "Permission:MediaDescriptorManagement:Create": "Create", + "Permission:MediaDescriptorManagement:Delete": "Delete", + "Permission:MenuItemManagement": "Menu Item Management", + "Permission:MenuItemManagement.Create": "Create", + "Permission:MenuItemManagement.Delete": "Delete", + "Permission:MenuItemManagement.Update": "Update", + "Permission:MenuManagement": "Menu Management", + "Permission:MenuManagement.Create": "Create", + "Permission:MenuManagement.Delete": "Delete", + "Permission:MenuManagement.Update": "Update", + "Permission:Menus": "Menu Management", + "Permission:Menus.Create": "Create", + "Permission:Menus.Delete": "Delete", + "Permission:Menus.Update": "Update", + "Permission:PageManagement": "Page Management", + "Permission:PageManagement:Create": "Create", + "Permission:PageManagement:Delete": "Delete", + "Permission:PageManagement:Update": "Update", + "Permission:PageManagement:SetAsHomePage": "Set As Home Page", + "Permission:TagManagement": "Tag Management", + "Permission:TagManagement.Create": "Create", + "Permission:TagManagement.Delete": "Delete", + "Permission:TagManagement.Update": "Update", + "Permission:GlobalResources": "Global Resources", + "Permission:CmsKitPublic": "CmsKit Public", + "Permission:Comments.DeleteAll": "Delete All", + "PickYourReaction": "Pick your reaction", + "Rating": "Rating", + "RatingUndoMessage": "Your rating will be undo.", + "Reactions": "Reactions", + "Read": "Read", + "RepliesToThisComment": "Replies to this comment", + "Reply": "Reply", + "ReplyTo": "Reply to", + "SamplePageMessage": "A sample page for the Pro module", + "SaveChanges": "Save Changes", + "Script": "Script", + "SelectAll": "Select All", + "Send": "Send", + "SendMessage": "Send Message", + "SelectedAuthor": "Author", + "ShortDescription": "Short description", + "Slug": "Slug", + "Source": "Source", + "SourceUrl": "Source Url", + "Star": "Star", + "StartDate": "Start Date", + "Style": "Style", + "Subject": "Subject", + "SubjectPlaceholder": "Please type a subject", + "Submit": "Submit", + "Subscribe": "Subscribe", + "SuccessfullySaved": "Successfully saved!", + "TagDeletionConfirmationMessage": "Are you sure to delete '{0}' tag?", + "Tags": "Tags", + "Text": "Text", + "ThankYou": "Thank you", + "Title": "Title", + "Undo": "Undo", + "Update": "Update", + "UpdatePreferenceSuccessMessage": "Your preferences have been saved.", + "UpdateYourEmailPreferences": "Update your email preferences", + "UnMakeMainMenu": "Unmake Main Menu", + "UploadFailedMessage": "Upload failed.", + "UserId": "User Id", + "Username": "Username", + "YourComment": "Your comment", + "YourEmailAddress": "Your e-mail address", + "YourFullName": "Your full name", + "YourMessage": "Your Message", + "YourReply": "Your reply", + "MarkdownSupported": "Markdown supported.", + "GlobalResources": "Global Resources", + "SavedSuccessfully": "Saved successfully", + "CmsKit.BlogPost.Status.0": "Draft", + "CmsKit.BlogPost.Status.1": "Published", + "CmsKit.BlogPost.Status.2": "Waiting for review", + "BlogPostPublishConfirmationMessage": "Are you sure to publish the blog post \"{0}\"?", + "SuccessfullyPublished": "Successfully published!", + "Draft": "Draft", + "Publish": "Publish", + "BlogPostDraftConfirmationMessage": "Are you sure to set the blog post \"{0}\" as draft?", + "BlogPostSendToReviewConfirmationMessage": "Are you sure to send the blog post \"{0}\" to admin review for publishing?", + "SaveAsDraft": "Save as draft", + "SendToReview": "Send to review", + "SendToReviewToPublish": "Send to review to publish", + "BlogPostSendToReviewSuccessMessage": "The blog post \"{0}\" has been sent to admin review for publishing.", + "HasBlogPostWaitingForReviewMessage": "You have a blog post waiting for review. Click to list.", + "SelectAStatus": "Select a status", + "Status": "Status", + "CmsKit.BlogPost.ScrollIndex": "Quick navigation bar in blog posts", + "CmsKit.BlogPost.PreventXssFeature": "Prevent XSS", + "Add": "Add", + "AddWidget": "Add Widget", + "PleaseConfigureWidgets": "Please configure widgets", + "SelectAnAuthor": "Select an Author", + "InThisDocument": "In This Document", + "GoToTop": "Go To Top", + "SetAsHomePage": "Change Home Page Status", + "CompletedSettingAsHomePage": "Set as home page", + "IsHomePage": "Is Home Page", + "RemovedSettingAsHomePage": "Removed setting the home page", + "Feature:CmsKitGroup": "Cms Kit", + "Feature:BlogEnable": "Blogpost", + "Feature:BlogEnableDescription": "CMS Kit's blogpost system that allows create blogs and posts dynamically in the application.", + "Feature:CommentEnable": "Commenting", + "Feature:CommentEnableDescription": "CMS Kit's comment system allows commenting on entities such as BlogPost.", + "Feature:GlobalResourceEnable": "Global resourcing", + "Feature:GlobalResourceEnableDescription": "CMS Kit's global resoruces feature that allows managing global styles & scripts.", + "Feature:MenuEnable": "Menu", + "Feature:MenuEnableDescription": "CMS Kit's dynamic menu system that allows adding/removing application menus dynamically.", + "Feature:PageEnable": "Paging", + "Feature:PageEnableDescription": "CMS Kit's page system that allows creating static pages with specific URL.", + "Feature:RatingEnable": "Rating", + "Feature:RatingEnableDescription": "CMS Kit's rating system that allows users to rate entities such as BlogPost.", + "Feature:ReactionEnable": "Reaction", + "Feature:ReactionEnableDescription": "CMS Kit's reaction system that allows users to send reactions to entities such as BlogPost, Comments, etc.", + "Feature:TagEnable": "Taging", + "Feature:TagEnableDescription": "CMS Kit's tag system that allows tagging entities such as BlogPost.", + "DeleteBlogPostMessage": "The blog will be deleted. Are you sure?", + "CaptchaCode": "Captcha code", + "CommentTextRequired": "Comment is required", + "CaptchaCodeErrorMessage": "The answer you entered for the CAPTCHA was not correct. Please try again", + "CaptchaCodeMissingMessage": "The captcha code is missing!", + "UnAllowedExternalUrlMessage": "You included an unallowed external URL. Please try again without the external URL.", + "URL": "URL", + "PopularTags": "Popular Tags", + "RemoveCoverImageConfirmationMessage": "Are you sure you want to remove the cover image?", + "RemoveCoverImage": "Remove cover image", + "CssClass": "CSS Class", + "TagsHelpText": "Tags should be comma-separated (e.g.: tag1, tag2, tag3)" + } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json index 8e8750e530..df713377fa 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Calificaciones", "CmsKit.Reactions": "Reacciones", "CmsKit.Tags": "Etiquetas", + "CmsKit.BlogPost.PreventXssFeature": "Prevenir ataques XSS", "CmsKit:0002": "¡El contenido ya existe!", "CmsKit:0003": "La entidad {0} no se puede etiquetar.", "CmsKit:Blog:0001": "¡La babosa dada ({Slug}) ya existe!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json index 855b6d091d..57ea83c2d3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json @@ -181,6 +181,7 @@ "HasBlogPostWaitingForReviewMessage": "شما یک پست وبلاگ دارید که منتظر بررسی است. برای لیست کلیک کنید.", "SelectAStatus": "انتخاب وضعیت", "Status": "وضعیت", - "CmsKit.BlogPost.ScrollIndex": "نوار پیمایش سریع در پست های وبلاگ" + "CmsKit.BlogPost.ScrollIndex": "نوار پیمایش سریع در پست های وبلاگ", + "CmsKit.BlogPost.PreventXssFeature": "جلوگیری از XSS" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json index 48f961cd71..2cbecff6f2 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json @@ -185,6 +185,7 @@ "SelectAStatus": "Valitse tila", "Status": "Tila", "CmsKit.BlogPost.ScrollIndex": "Pikanavigointipalkki blogikirjoituksissa", + "CmsKit.BlogPost.PreventXssFeature": "Estä XSS", "Add": "Lisää", "AddWidget": "Lisää widget", "PleaseConfigureWidgets": "Määritä widgetit", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json index 5c789e996e..ad7df5cef7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Évaluations", "CmsKit.Reactions": "Réactions", "CmsKit.Tags": "Mots clés", + "CmsKit.BlogPost.PreventXssFeature": "Empêcher les attaques XSS", "CmsKit:0002": "Le contenu existe déjà!", "CmsKit:0003": "L'entité {0} ne peut pas être taguée.", "CmsKit:Blog:0001": "Le slug donné ({Slug}) existe déjà!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json index 8f69f2e25f..3b7700b490 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "रेटिंग्स", "CmsKit.Reactions": "प्रतिक्रियाओं", "CmsKit.Tags": "टैग", + "CmsKit.BlogPost.PreventXssFeature": "XSS रोकें", "CmsKit:0002": "सामग्री पहले से मौजूद है!", "CmsKit:0003": "इकाई {0} टैग करने योग्य नहीं है।", "CmsKit:Blog:0001": "दिया गया स्लग ({Slug}) पहले से मौजूद है!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json index 5497c9ec98..c262b42adf 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json @@ -182,6 +182,7 @@ "SelectAStatus": "Válasszon állapotot", "Status": "Állapot", "CmsKit.BlogPost.ScrollIndex": "Gyors navigációs sáv a blogbejegyzésekben", + "CmsKit.BlogPost.PreventXssFeature": "XSS megelőzése", "Add": "Hozzáadás", "AddWidget": "Widget hozzáadása", "PleaseConfigureWidgets": "Kérjük, állítsa be a widgeteket", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json index 7107434304..762dd4f994 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Skor", "CmsKit.Reactions": "Viðbrögð", "CmsKit.Tags": "Tög", + "CmsKit.BlogPost.PreventXssFeature": "Fyrirbyggja XSS árásir", "CmsKit:0002": "Efni nú þegar til!", "CmsKit:0003": "Ekki hægt að tagga einingu {0}", "CmsKit:Blog:0001": "Uppgefin snigill ({Slug}) er þegar til!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json index 60c8d13744..95923c8937 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Valutazioni", "CmsKit.Reactions": "Reazioni", "CmsKit.Tags": "Tag", + "CmsKit.BlogPost.PreventXssFeature": "Prevenzione XSS", "CmsKit:0002": "Il contenuto esiste già!", "CmsKit:0003": "L'entità {0} non è codificabile.", "CmsKit:Blog:0001": "Lo slug specificato ({Slug}) esiste già!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json index 39779d1d57..1e0e6ee98d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Beoordelingen", "CmsKit.Reactions": "Reacties", "CmsKit.Tags": "Tags", + "CmsKit.BlogPost.PreventXssFeature": "XSS-functie voorkomen", "CmsKit:0002": "Inhoud bestaat al!", "CmsKit:0003": "De entiteit {0} kan niet worden getagd.", "CmsKit:Blog:0001": "De opgegeven slug ({Slug}) bestaat al!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json index 5a2ed06a5d..afd3447867 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Oceny", "CmsKit.Reactions": "Reakcje", "CmsKit.Tags": "Tagi", + "CmsKit.BlogPost.PreventXssFeature": "Zapobiegaj atakom XSS", "CmsKit:0002": "Treść już istnieje!", "CmsKit:0003": "Jednostka {0} nie może być otagowana.", "CmsKit:Blog:0001": "Podany ślimak ({Slug}) już istnieje!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json index be7cbe0775..3b49284b58 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Avaliações", "CmsKit.Reactions": "Reações", "CmsKit.Tags": "Tag", + "CmsKit.BlogPost.PreventXssFeature": "Prevenir recurso XSS", "CmsKit:0002": "O conteúdo já existe!", "CmsKit:0003": "A entidade {0} não pode ser etiquetada.", "CmsKit:Blog:0001": "O slug fornecido ({Slug}) já existe!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json index 9cd519bb53..6f434903d1 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Evaluări", "CmsKit.Reactions": "Reacţii", "CmsKit.Tags": "Etichete", + "CmsKit.BlogPost.PreventXssFeature": "Prevenirea Xss", "CmsKit:0002": "Conţinutul există deja!", "CmsKit:0003": "Entitatea {0} nu este etichetabilă.", "CmsKit:Blog:0001": "Slugul ({Slug}) există deja!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json index f95ee910e4..39fcd1f102 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Рейтинги", "CmsKit.Reactions": "Реакции", "CmsKit.Tags": "Теги", + "CmsKit.BlogPost.PreventXssFeature": "Защита от XSS", "CmsKit:0002": "Контент уже существует!", "CmsKit:0003": "Сущность {0} не может быть помечена.", "CmsKit:Blog:0001": "Указанный слаг ({Slug}) уже существует!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json index 2cf9410ca9..95620abc23 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Hodnotenia", "CmsKit.Reactions": "Reakcie", "CmsKit.Tags": "Tagy", + "CmsKit.BlogPost.PreventXssFeature": "Zabraňte XSS", "CmsKit:0002": "Obsah už existuje!", "CmsKit:0003": "Entite {0} nie je možné priradiť tag.", "CmsKit:Blog:0001": "Zadaný slug ({Slug}) už existuje!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json index 22f252ea51..588f9c67a2 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Ocene", "CmsKit.Reactions": "Reakcije", "CmsKit.Tags": "Oznake", + "CmsKit.BlogPost.PreventXssFeature": "Prepreči XSS", "CmsKit:0002": "Vsebina že obstaja!", "CmsKit:0003": "Entiteta {0} ni mogoče označiti.", "CmsKit:Blog:0001": "Podani polž ({Slug}) že obstaja!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json index ff1ab72ae2..265ed8c18e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json @@ -187,6 +187,7 @@ "RemoveCoverImageConfirmationMessage": "Kapak resmini kaldırmak istediğinize emin misiniz?", "RemoveCoverImage": "Kapak resmini kaldır", "CmsKit.BlogPost.ScrollIndex": "Blog yazılarında hızlı gezinme çubuğu", + "CmsKit.BlogPost.PreventXssFeature": "XSS önleme özelliği", "Add": "Ekle", "AddWidget": "Widget Ekle", "PleaseConfigureWidgets": "Lütfen widget'leri yapılandırın", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json index a581da6362..17f9ecaf5c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "Xếp hạng", "CmsKit.Reactions": "Phản ứng", "CmsKit.Tags": "Thẻ", + "CmsKit.BlogPost.PreventXssFeature": "Ngăn chặn XSS", "CmsKit:0002": "Nội dung đã tồn tại!", "CmsKit:0003": "Thực thể {0} không thể gắn thẻ.", "CmsKit:Blog:0001": "Sên đã cho ({Slug}) đã tồn tại!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json index a827923981..7a98fd4e22 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json @@ -185,6 +185,7 @@ "SelectAStatus": "选择一个状态", "Status": "状态", "CmsKit.BlogPost.ScrollIndex": "博客文章快速导航栏", + "CmsKit.BlogPost.PreventXssFeature": "防止XSS攻击", "Add": "添加", "AddWidget": "添加组件", "PleaseConfigureWidgets": "请配置组件", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json index 91a742deba..303b0cc1ad 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json @@ -15,6 +15,7 @@ "CmsKit.Ratings": "評分", "CmsKit.Reactions": "反應", "CmsKit.Tags": "標籤", + "CmsKit.BlogPost.PreventXssFeature": "防止XSS攻擊", "CmsKit:0002": "內容已經存在!", "CmsKit:0003": "實體 {0} 不可標記.", "CmsKit:Blog:0001": "給定的slug ({Slug}) 已經存在!", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/DefaultBlogFeatureProvider.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/DefaultBlogFeatureProvider.cs index 1eec1100f2..b24e992cf3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/DefaultBlogFeatureProvider.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/DefaultBlogFeatureProvider.cs @@ -11,12 +11,13 @@ public class DefaultBlogFeatureProvider : IDefaultBlogFeatureProvider, ITransien public virtual Task> GetDefaultFeaturesAsync(Guid blogId) { return Task.FromResult(new List - { - new BlogFeature(blogId, CommentsFeature.Name), - new BlogFeature(blogId, ReactionsFeature.Name), - new BlogFeature(blogId, RatingsFeature.Name), - new BlogFeature(blogId, TagsFeature.Name), - new BlogFeature(blogId, BlogPostScrollIndexFeature.Name) - }); + { + new BlogFeature(blogId, CommentsFeature.Name), + new BlogFeature(blogId, ReactionsFeature.Name), + new BlogFeature(blogId, RatingsFeature.Name), + new BlogFeature(blogId, TagsFeature.Name), + new BlogFeature(blogId, BlogPostScrollIndexFeature.Name), + new BlogFeature(blogId, BlogConsts.PreventXssFeatureName) + }); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml index d4e09e9b61..8829df73c5 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/Commenting/Default.cshtml @@ -204,7 +204,7 @@ { @foreach (var reply in comment.Replies) { -
+
@GetCommentTitle(reply.Author, reply.CreationTime).Invoke(null) diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml index c45dde17cb..319d6ad2f2 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml @@ -69,7 +69,9 @@

@(await Component.InvokeAsync(typeof(ContentFragmentViewComponent), new DefaultContentDto { - ContentFragments = Model.ViewModel.ContentFragments + ContentFragments = Model.ViewModel.ContentFragments, + AllowHtmlTags = true, + PreventXSS = Model.PreventXssFeature.IsEnabled, }))

@if (Model.ViewModel.LastModificationTime != null) @@ -137,19 +139,19 @@ } @if (isScrollIndexEnabled) { -

-
@L["InThisDocument"]
- +
+
@L["InThisDocument"]
+ - }
diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs index a503ff0794..3e174164cf 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Blogs/BlogPost.cshtml.cs @@ -29,6 +29,8 @@ public class BlogPostModel : CmsKitPublicPageModelBase public BlogFeatureDto BlogPostScrollIndexFeature { get; private set; } + public BlogFeatureDto PreventXssFeature { get; private set; } + protected IBlogPostPublicAppService BlogPostPublicAppService { get; } protected IBlogFeatureAppService BlogFeatureAppService { get; } @@ -81,6 +83,8 @@ public class BlogPostModel : CmsKitPublicPageModelBase BlogPostScrollIndexFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, GlobalFeatures.BlogPostScrollIndexFeature.Name); } + PreventXssFeature = await BlogFeatureAppService.GetOrDefaultAsync(ViewModel.BlogId, BlogConsts.PreventXssFeatureName); + return Page(); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml index 44ac5332b6..4237eb5c31 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/Public/CmsKit/Pages/Index.cshtml @@ -7,23 +7,30 @@ @section styles{ - - + @if (!Model.ViewModel.Style.IsNullOrEmpty()) + { + + } } @section scripts{ - + @if (!Model.ViewModel.Script.IsNullOrEmpty()) + { + + } } @(await Component.InvokeAsync(typeof(ContentFragmentViewComponent), new DefaultContentDto { - ContentFragments = Model.ViewModel.ContentFragments + ContentFragments = Model.ViewModel.ContentFragments, + PreventXSS = false, + AllowHtmlTags = true, })) diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index bbcda3d38e..63bd64639b 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -34,7 +34,7 @@ "build:schematics": "cd scripts && yarn && yarn build:schematics && cd ..", "dev:schematics": "tsc -p packages/schematics/tsconfig.json -w", "mock:schematics": "cd scripts/mock-schematic && yarn && yarn start", - "debug:schematics": "./node_modules/.bin/ng g ./packages/schematics/src/collection.json:proxy-add --module __default --apiName __default --source __default --target __default --url https://localhost:44305 --serviceType application --entryPoint __default ", + "debug:schematics": "./node_modules/.bin/nx g ./packages/schematics/src/collection.json:proxy-add --module identity --apiName __default --source __default --target __default --url https://localhost:44305 --serviceType application --entryPoint __default ", "debug:schematics-dist": "./node_modules/.bin/ng g ./dist/packages/schematics/collection.json:proxy-add --module __default --apiName __default --source __default --target __default --url http://localhost:4300 --service-type application --entryPoint __default", "ci": "yarn affected:lint && yarn affected:build && yarn affected:test", "lerna": "lerna", diff --git a/npm/ng-packs/packages/generators/generators.json b/npm/ng-packs/packages/generators/generators.json index 8910e6fdba..4f41032144 100644 --- a/npm/ng-packs/packages/generators/generators.json +++ b/npm/ng-packs/packages/generators/generators.json @@ -9,6 +9,11 @@ "factory": "./src/generators/update-version/generator", "schema": "./src/generators/update-version/schema.json", "description": "update-version generator" + }, + "change-theme": { + "factory": "./src/generators/change-theme/generator", + "schema": "./src/generators/change-theme/schema.json", + "description": "change-theme generator" } } } diff --git a/npm/ng-packs/packages/generators/src/generators/change-theme/generator.spec.ts b/npm/ng-packs/packages/generators/src/generators/change-theme/generator.spec.ts new file mode 100644 index 0000000000..940c5dbe3b --- /dev/null +++ b/npm/ng-packs/packages/generators/src/generators/change-theme/generator.spec.ts @@ -0,0 +1,20 @@ +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import { Tree, readProjectConfiguration } from '@nx/devkit'; + +import { changeThemeGenerator } from './generator'; +import { ChangeThemeGeneratorSchema } from './schema'; + +describe('change-theme generator', () => { + let tree: Tree; + const options: ChangeThemeGeneratorSchema = { name: 'test' }; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + }); + + it('should run successfully', async () => { + await changeThemeGenerator(tree, options); + const config = readProjectConfiguration(tree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/npm/ng-packs/packages/generators/src/generators/change-theme/generator.ts b/npm/ng-packs/packages/generators/src/generators/change-theme/generator.ts new file mode 100644 index 0000000000..d912d11e87 --- /dev/null +++ b/npm/ng-packs/packages/generators/src/generators/change-theme/generator.ts @@ -0,0 +1,26 @@ +import { Tree } from '@nx/devkit'; +import { wrapAngularDevkitSchematic } from '@nx/devkit/ngcli-adapter'; +import { ChangeThemeGeneratorSchema } from './schema'; +import { ThemeOptionsEnum } from './theme-options.enum'; + +export async function changeThemeGenerator(host: Tree, schema: ChangeThemeGeneratorSchema) { + const schematicPath = schema.localPath || '@abp/ng.schematics'; + + const runAngularLibrarySchematic = wrapAngularDevkitSchematic( + schema.localPath ? `${host.root}${schematicPath}` : schematicPath, + 'change-theme', + ); + + await runAngularLibrarySchematic(host, { + ...schema, + }); + + return () => { + const destTheme = Object.values(ThemeOptionsEnum).find( + (theme, index) => index + 1 === schema.name, + ); + console.log(`✅️ Switched to Theme ${destTheme}`); + }; +} + +export default changeThemeGenerator; diff --git a/npm/ng-packs/packages/generators/src/generators/change-theme/index.ts b/npm/ng-packs/packages/generators/src/generators/change-theme/index.ts new file mode 100644 index 0000000000..05ffcdcc9b --- /dev/null +++ b/npm/ng-packs/packages/generators/src/generators/change-theme/index.ts @@ -0,0 +1,3 @@ +export * from './theme-options.enum'; +export * from './schema'; +export * from './generator'; diff --git a/npm/ng-packs/packages/generators/src/generators/change-theme/schema.d.ts b/npm/ng-packs/packages/generators/src/generators/change-theme/schema.d.ts new file mode 100644 index 0000000000..50caed37f0 --- /dev/null +++ b/npm/ng-packs/packages/generators/src/generators/change-theme/schema.d.ts @@ -0,0 +1,5 @@ +export interface ChangeThemeGeneratorSchema { + name: number; + targetOption: string; + localPath?: string; +} diff --git a/npm/ng-packs/packages/generators/src/generators/change-theme/schema.json b/npm/ng-packs/packages/generators/src/generators/change-theme/schema.json new file mode 100644 index 0000000000..e09d479f1b --- /dev/null +++ b/npm/ng-packs/packages/generators/src/generators/change-theme/schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "SchematicsABPThemeChanger", + "title": "ABP Theme Style Generator API Schema", + "type": "object", + "properties": { + "name": { + "description": "The name of theme will change.", + "type": "number", + "$default": { + "$source": "argv", + "index": 0 + }, + "enum": [1, 2, 3, 4], + "x-prompt": { + "message": "Which theme would you like to use?", + "type": "list", + "items": [ + { "value": 1, "label": "Basic" }, + { "value": 2, "label": "Lepton" }, + { "value": 3, "label": "LeptonXLite" }, + { "value": 4, "label": "LeptonX" } + ] + } + }, + "targetProject": { + "description": "The name of the project will change the style.The project type must be 'application'", + "type": "string", + "x-prompt": "Please enter the project name", + "$default": { + "$source": "argv", + "index": 1 + } + }, + "localPath": { + "description": "If set value schematics will work on given path", + "type": "string" + } + }, + "required": ["name", "targetProject"] +} diff --git a/npm/ng-packs/packages/generators/src/generators/change-theme/theme-options.enum.ts b/npm/ng-packs/packages/generators/src/generators/change-theme/theme-options.enum.ts new file mode 100644 index 0000000000..a64487ed8f --- /dev/null +++ b/npm/ng-packs/packages/generators/src/generators/change-theme/theme-options.enum.ts @@ -0,0 +1,8 @@ +// this enum create by https://raw.githubusercontent.com/abpframework/abp/rel-7.4/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Theme.cs + +export enum ThemeOptionsEnum { + Basic = 1, + Lepton = 2, + LeptonXLite = 3, + LeptonX = 4, +} diff --git a/npm/ng-packs/packages/generators/src/index.ts b/npm/ng-packs/packages/generators/src/index.ts index 9a6fb02c00..a2ce5894d3 100644 --- a/npm/ng-packs/packages/generators/src/index.ts +++ b/npm/ng-packs/packages/generators/src/index.ts @@ -1 +1,3 @@ -export * from './generators/generate-proxy' \ No newline at end of file +export * from './generators/change-theme'; +export * from './generators/generate-proxy'; +export * from './generators/update-version'; diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts index 959a3128db..30a29ed7dc 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts @@ -1,10 +1,17 @@ -import { Rule, SchematicsException } from '@angular-devkit/schematics'; -import { isLibrary, updateWorkspace, WorkspaceDefinition } from '../../utils'; -import { allStyles, styleMap } from './style-map'; -import { ProjectDefinition } from '@angular-devkit/core/src/workspace'; import { JsonArray, JsonValue } from '@angular-devkit/core'; +import { Rule, SchematicsException, Tree, chain } from '@angular-devkit/schematics'; +import { ProjectDefinition } from '@angular-devkit/core/src/workspace'; +import * as ts from 'typescript'; +import { allStyles, importMap, styleMap } from './style-map'; import { ChangeThemeOptions } from './model'; +import { Change, InsertChange, isLibrary, updateWorkspace, WorkspaceDefinition } from '../../utils'; import { ThemeOptionsEnum } from './theme-options.enum'; +import { + addImportToModule, + findNodes, + getDecoratorMetadata, + getMetadataField, +} from '../../utils/angular/ast-utils'; export default function (_options: ChangeThemeOptions): Rule { return async () => { @@ -14,9 +21,12 @@ export default function (_options: ChangeThemeOptions): Rule { throw new SchematicsException('The theme name does not selected'); } - return updateWorkspace(storedWorkspace => { - updateProjectStyle(selectedProject, storedWorkspace, targetThemeName); - }); + return chain([ + updateWorkspace(storedWorkspace => { + updateProjectStyle(selectedProject, storedWorkspace, targetThemeName); + }), + updateAppModule(selectedProject, targetThemeName), + ]); }; } @@ -48,6 +58,138 @@ function updateProjectStyle( targetOption.styles = [...newStyles, ...sanitizedStyles] as JsonArray; } +function updateAppModule(selectedProject: string, targetThemeName: ThemeOptionsEnum): Rule { + return (host: Tree) => { + const angularJSON = host.read('angular.json'); + if (!angularJSON) { + throw new SchematicsException('The angular.json does not found'); + } + + const workspace = JSON.parse(angularJSON.toString()); + const project = workspace.projects[selectedProject]; + + if (!project || !project.sourceRoot) { + throw new SchematicsException('The target project does not found'); + } + + const appModulePath = project.sourceRoot + '/app/app.module.ts'; + + return chain([ + removeImportPath(appModulePath, targetThemeName), + removeImportFromNgModuleMetadata(appModulePath, targetThemeName), + insertImports(appModulePath, targetThemeName), + ]); + }; +} + +function removeImportPath(appModulePath: string, selectedTheme: ThemeOptionsEnum): Rule { + return (host: Tree) => { + const recorder = host.beginUpdate(appModulePath); + const sourceText = host.read(appModulePath)?.toString('utf-8'); + const source = ts.createSourceFile( + appModulePath, + sourceText!, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TS, + ); + const impMap = Array.from(importMap.values()) + .filter(f => f !== importMap.get(selectedTheme)) + .reduce((acc, val) => [...acc, ...val], []); + + const nodes = findNodes(source, ts.isImportDeclaration); + const filteredNodes = nodes.filter(n => impMap.some(f => n.getFullText().match(f.path))); + if (!filteredNodes || filteredNodes.length < 1) { + return; + } + + filteredNodes.map(importPath => + recorder.remove(importPath.getStart(), importPath.getWidth() + 1), + ); + + host.commitUpdate(recorder); + return host; + }; +} + +function removeImportFromNgModuleMetadata( + appModulePath: string, + selectedTheme: ThemeOptionsEnum, +): Rule { + return (host: Tree) => { + const recorder = host.beginUpdate(appModulePath); + const sourceText = host.read(appModulePath)?.toString('utf-8'); + const source = ts.createSourceFile( + appModulePath, + sourceText!, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TS, + ); + const impMap = Array.from(importMap.values()) + .filter(f => f !== importMap.get(selectedTheme)) + .reduce((acc, val) => [...acc, ...val], []); + + const node = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0] || {}; + if (!node) { + throw new SchematicsException('The app module does not found'); + } + + const matchingProperties = getMetadataField(node as ts.ObjectLiteralExpression, 'imports'); + + const assignment = matchingProperties[0] as ts.PropertyAssignment; + const assignmentInit = assignment.initializer as ts.ArrayLiteralExpression; + + const elements = assignmentInit.elements; + if (!elements || elements.length < 1) { + return; + } + + const filteredElements = elements.filter(f => + impMap.some(s => f.getText().match(s.importName)), + ); + if (!filteredElements || filteredElements.length < 1) { + return; + } + + filteredElements.map(willRemoveModule => + recorder.remove(willRemoveModule.getStart(), willRemoveModule.getWidth() + 1), + ); + host.commitUpdate(recorder); + return host; + }; +} + +function insertImports(appModulePath: string, selectedTheme: ThemeOptionsEnum): Rule { + return (host: Tree) => { + const recorder = host.beginUpdate(appModulePath); + const sourceText = host.read(appModulePath)?.toString('utf-8'); + const source = ts.createSourceFile( + appModulePath, + sourceText!, + ts.ScriptTarget.Latest, + true, + ts.ScriptKind.TS, + ); + const selected = importMap.get(selectedTheme); + + const changes: Change[] = []; + selected!.map(({ importName, path }) => + changes.push(...addImportToModule(source, appModulePath, importName, path)), + ); + + if (changes.length > 0) { + for (const change of changes) { + if (change instanceof InsertChange) { + recorder.insertLeft(change.pos, change.toAdd); + } + } + } + host.commitUpdate(recorder); + return host; + }; +} + export function getProjectTargetOptions( project: ProjectDefinition, buildTarget: string, diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts index 91ef14a673..99b018703b 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts @@ -8,6 +8,11 @@ export type StyleDefinition = } | string; +export type ImportDefinition = { + path: string; + importName: string; +}; + export const styleMap = new Map(); styleMap.set(ThemeOptionsEnum.Basic, [ @@ -241,3 +246,49 @@ styleMap.set(ThemeOptionsEnum.LeptonXLite, [ ]); // the code written by Github co-pilot. thank go-pilot. You are the best sidekick. export const allStyles = Array.from(styleMap.values()).reduce((acc, val) => [...acc, ...val], []); + +export const importMap = new Map(); + +importMap.set(ThemeOptionsEnum.Basic, [ + { + path: '@abp/ng.theme.basic', + importName: 'ThemeBasicModule.forRoot()', + }, +]); + +importMap.set(ThemeOptionsEnum.Lepton, [ + { + path: '@volo/abp.ng.theme.lepton', + importName: 'ThemeLeptonModule.forRoot()', + }, +]); + +importMap.set(ThemeOptionsEnum.LeptonXLite, [ + { + path: '@abp/ng.theme.lepton-x', + importName: 'ThemeLeptonXModule.forRoot()', + }, + { + path: '@abp/ng.theme.lepton-x/layouts', + importName: 'SideMenuLayoutModule.forRoot()', + }, + { + path: '@abp/ng.theme.lepton-x/account', + importName: 'AccountLayoutModule.forRoot()', + }, +]); + +importMap.set(ThemeOptionsEnum.LeptonX, [ + { + path: '@volosoft/abp.ng.theme.lepton-x', + importName: 'ThemeLeptonXModule.forRoot()', + }, + { + path: '@volosoft/abp.ng.theme.lepton-x/layouts', + importName: 'SideMenuLayoutModule.forRoot()', + }, + { + path: '@volosoft/abp.ng.theme.lepton-x/account', + importName: 'AccountLayoutModule.forRoot()', + }, +]); diff --git a/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts b/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts index bda343f07b..55477b41d3 100644 --- a/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts +++ b/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts @@ -446,7 +446,6 @@ export function addSymbolToNgModuleMetadata( toInsert = `, ${symbolName}`; } } - if (importPath !== null) { return [ new InsertChange(ngModulePath, position, toInsert), diff --git a/npm/packs/zxcvbn/README.md b/npm/packs/zxcvbn/README.md new file mode 100644 index 0000000000..8416714abe --- /dev/null +++ b/npm/packs/zxcvbn/README.md @@ -0,0 +1,129 @@ +## ℹ️ Description + +ABP Framework is a complete open-source infrastructure to create modern web applications by following the best practices and conventions of software development. This package is a part of the [ABP Framework](https://abp.io) and contains client-side files. +For more information, check out the below links: + +🔗Official Website: https://abp.io + +🔗Commercial Website: https://commercial.abp.io + +🔗Commercial Demo: https://commercial.abp.io/demo + +🔗GitHub Repository: https://github.com/abpframework/abp + +🔗Official Theme: https://www.LeptonTheme.com + +🔗Documentation: https://docs.abp.io + +🔗Community: https://community.abp.io + +🔗Blog: https://blog.abp.io + +🔗Books: https://abp.io/books + +🔗Twitter: https://twitter.com/abpframework + +🔗Discord: https://community.abp.io/discord + +🔗Stackoverflow: https://stackoverflow.com/questions/tagged/abp + +🔗YouTube: https://www.youtube.com/@Volosoft + + +## 🤔 Why ABP Platform? + +Why should you use the ABP.IO Platform instead of creating a new solution from scratch? + +You can find the answer here 👉🏻 [Why ABP Platform?](https://docs.abp.io/en/commercial/latest/why-abp-io-platform) + +## 🚀 Key Features of the ABP Framework + +🟡 Modularity + +🟡 Multi-Tenancy + +🟡 Bootstrap Tag Helpers + +🟡 Dynamic Forms + +🟡 Authentication + +🟡 Authorization + +🟡 Distributed Event Bus + +🟡 BLOB Storing + +🟡 Text Templating + +🟡 Tooling: ABP CLI + +🟡 Cross-Cutting Concerns + +🟡 Bundling & Minification + +🟡 Virtual File System + +🟡 Theming + +🟡 Background Jobs + +🟡 DDD Infrastructure + +🟡 Auto REST APIs + +🟡 Dynamic Client Proxies + +🟡 Multiple Database Providers + +🟡 Data filtering + +🟡 Test Infrastructure + +🟡 Audit Logging + +🟡 Object to Object Mapping + +🟡 Email & SMS Abstractions + +🟡 Localization + +🟡 Setting Management + +🟡 Extension Methods + +🟡 Aspect Oriented Programming + +🟡 Dependency Injection + + +## 🧐 How It Works? + +The following page explains how you use the ABP.IO Platform as a .NET developer 👉 [How it works?](https://commercial.abp.io/how-it-works) + + +### 📘 Supported Database Providers + +🔵 Entity Framework Core + +🔵 MongoDB + +🔵 Dapper + + +### 🎴 Supported UI Frameworks + +🔵 Angular + +🔵 Razor Pages + +🔵 Blazor Web Assembly + +🔵 Blazor Server + +🔵 MAUI with Blazor Hybrid + + +## 📫 Bug & Support + +Support for open-source ABP Framework client-side packages is available at [GitHub Issues](https://github.com/abpframework/abp/issues), and the commercial support is available at [support.abp.io](https://support.abp.io). diff --git a/npm/packs/zxcvbn/abp.resourcemapping.js b/npm/packs/zxcvbn/abp.resourcemapping.js new file mode 100644 index 0000000000..4e5c004c05 --- /dev/null +++ b/npm/packs/zxcvbn/abp.resourcemapping.js @@ -0,0 +1,5 @@ +module.exports = { + mappings: { + "@node_modules/zxcvbn/dist/zxcvbn.js": "@libs/zxcvbn/" + } +} \ No newline at end of file diff --git a/npm/packs/zxcvbn/package.json b/npm/packs/zxcvbn/package.json new file mode 100644 index 0000000000..33a406d942 --- /dev/null +++ b/npm/packs/zxcvbn/package.json @@ -0,0 +1,32 @@ +{ + "version": "7.4.0-rc.3", + "name": "@abp/zxcvbn", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@abp/core": "~7.4.0-rc.3", + "zxcvbn" : "^4.4.2" + }, + "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", + "homepage": "https://abp.io", + "repository": { + "type": "git", + "url": "https://github.com/abpframework/abp.git" + }, + "license": "LGPL-3.0", + "keywords": [ + "aspnetcore", + "boilerplate", + "framework", + "web", + "best-practices", + "angular", + "maui", + "blazor", + "mvc", + "csharp", + "webapp" + ] + } + \ No newline at end of file diff --git a/templates/app-nolayers/angular/package.json b/templates/app-nolayers/angular/package.json index 80fb808cd1..b3c7e2be5a 100644 --- a/templates/app-nolayers/angular/package.json +++ b/templates/app-nolayers/angular/package.json @@ -20,7 +20,7 @@ "@abp/ng.setting-management": "~7.4.0-rc.3", "@abp/ng.tenant-management": "~7.4.0-rc.3", "@abp/ng.theme.shared": "~7.4.0-rc.3", - "@abp/ng.theme.lepton-x": "~2.4.0-rc.2", + "@abp/ng.theme.lepton-x": "~2.4.0-rc.3", "@angular/animations": "~16.0.0", "@angular/common": "~16.0.0", "@angular/compiler": "~16.0.0", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs index f5160169d4..2f625c6d4e 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs @@ -287,6 +287,7 @@ public class MyProjectNameHostModule : AbpModule if (env.IsDevelopment()) { + app.UseWebAssemblyDebugging(); app.UseDeveloperExceptionPage(); } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs index b76933ce94..e3e7afe999 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs @@ -304,6 +304,7 @@ public class MyProjectNameHostModule : AbpModule if (env.IsDevelopment()) { + app.UseWebAssemblyDebugging(); app.UseDeveloperExceptionPage(); } diff --git a/templates/app/angular/package.json b/templates/app/angular/package.json index 620495d9f0..70a6c8e56b 100644 --- a/templates/app/angular/package.json +++ b/templates/app/angular/package.json @@ -20,7 +20,7 @@ "@abp/ng.setting-management": "~7.4.0-rc.3", "@abp/ng.tenant-management": "~7.4.0-rc.3", "@abp/ng.theme.shared": "~7.4.0-rc.3", - "@abp/ng.theme.lepton-x": "~2.4.0-rc.2", + "@abp/ng.theme.lepton-x": "~2.4.0-rc.3", "@angular/animations": "~16.0.0", "@angular/common": "~16.0.0", "@angular/compiler": "~16.0.0", diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs index 104fe9fed6..2a5a34c7e5 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs @@ -35,6 +35,7 @@ using Volo.Abp.OpenIddict; using Volo.Abp.UI.Navigation.Urls; using Volo.Abp.UI; using Volo.Abp.VirtualFileSystem; +using Volo.Abp.Account.Localization; namespace MyCompanyName.MyProjectName; @@ -90,7 +91,8 @@ public class MyProjectNameAuthServerModule : AbpModule options.Resources .Get() .AddBaseTypes( - typeof(AbpUiResource) + typeof(AbpUiResource), + typeof(AccountResource) ); }); diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml index 55b17f3453..fb4d0ba9ce 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/Pages/Index.cshtml @@ -16,6 +16,14 @@ Layout = Theme.GetEmptyLayout(); } +@section styles { + +} +
@@ -30,37 +38,30 @@

@BrandingProvider.AppName

}
+
- - -
-
- -
-
- @if (CurrentUser.IsAuthenticated) - { - - @L["Welcome"] @CurrentUser.UserName - - @CurrentUser.Email - - } - else - { - @L["Login"] - } -
- + +
+
+ @if (CurrentUser.IsAuthenticated) + { + + } + else + { + @L["Login"] + } +
- + +
@@ -78,16 +79,17 @@
-
- - @if (Model.Applications != null) - { - foreach (var application in Model.Applications) + + @if (Model.Applications != null) + { +
+ + + @foreach (var application in Model.Applications) { - @if (!application.LogoUri.IsNullOrEmpty()) {
@@ -96,16 +98,13 @@ }

@application.DisplayName

- @application.ClientUri - + @application.ClientUri } - } - + + }
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json index 5332ea7677..1797992d04 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json @@ -9,24 +9,32 @@ // "OpenIddict": { "Applications": { + // "MyProjectName_Web": { "ClientId": "MyProjectName_Web", "ClientSecret": "1q2w3e*", "RootUrl": "https://localhost:44302" }, + // + // "MyProjectName_Blazor": { "ClientId": "MyProjectName_Blazor", "RootUrl": "https://localhost:44307" }, + // + // "MyProjectName_App": { "ClientId": "MyProjectName_App", "RootUrl": "http://localhost:4200" }, + // + // "MyProjectName_BlazorServerTiered": { "ClientId": "MyProjectName_BlazorServerTiered", "ClientSecret": "1q2w3e*", "RootUrl": "https://localhost:44309" }, + // "MyProjectName_Swagger": { "ClientId": "MyProjectName_Swagger", "RootUrl": "https://localhost:44305" diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs index ccf35ec026..a1af7f6b6a 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs @@ -79,6 +79,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep var configurationSection = _configuration.GetSection("OpenIddict:Applications"); + // //Web Client var webClientId = configurationSection["MyProjectName_Web:ClientId"]; if (!webClientId.IsNullOrWhiteSpace()) @@ -103,7 +104,9 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc" ); } + // + // //Console Test / Angular Client var consoleAndAngularClientId = configurationSection["MyProjectName_App:ClientId"]; if (!consoleAndAngularClientId.IsNullOrWhiteSpace()) @@ -127,7 +130,9 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep postLogoutRedirectUri: consoleAndAngularClientRootUrl ); } + // + // // Blazor Client var blazorClientId = configurationSection["MyProjectName_Blazor:ClientId"]; if (!blazorClientId.IsNullOrWhiteSpace()) @@ -147,7 +152,9 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback" ); } + // + // // Blazor Server Tiered Client var blazorServerTieredClientId = configurationSection["MyProjectName_BlazorServerTiered:ClientId"]; if (!blazorServerTieredClientId.IsNullOrWhiteSpace()) @@ -170,7 +177,9 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep postLogoutRedirectUri: $"{blazorServerTieredRootUrl}signout-callback-oidc" ); } + // + // // Swagger Client var swaggerClientId = configurationSection["MyProjectName_Swagger:ClientId"]; if (!swaggerClientId.IsNullOrWhiteSpace()) @@ -189,6 +198,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep clientUri: swaggerRootUrl ); } + // } private async Task CreateApplicationAsync( diff --git a/templates/console/src/MyCompanyName.MyProjectName/Program.cs b/templates/console/src/MyCompanyName.MyProjectName/Program.cs index 92f3bf49a1..79d12b850f 100644 --- a/templates/console/src/MyCompanyName.MyProjectName/Program.cs +++ b/templates/console/src/MyCompanyName.MyProjectName/Program.cs @@ -36,9 +36,8 @@ public class Program services.AddApplicationAsync(options => { options.Services.ReplaceConfiguration(services.GetConfiguration()); - options.Services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog()); }); - }).AddAppSettingsSecretsJson().UseAutofac().UseConsoleLifetime(); + }).AddAppSettingsSecretsJson().UseSerilog().UseAutofac().UseConsoleLifetime(); var host = builder.Build(); await host.Services.GetRequiredService().InitializeAsync(host.Services);