diff --git a/Directory.Packages.props b/Directory.Packages.props
index a91c3e8a1a..c39ba6790b 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -103,26 +103,26 @@
-
+
-
+
-
-
-
-
-
+
+
+
+
+
-
+
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
index f8eb001da2..33138747c8 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
@@ -238,6 +238,7 @@
"Packages": "Packages",
"Trainings": "Trainings",
"MeetTheABPCommunity": "Meet the ABP ",
- "DisplayName:CommunityIndexPagePoll": "Community Index Page Poll"
+ "DisplayName:CommunityIndexPagePoll": "Community Index Page Poll",
+ "ReturnOfInvestment": "Return Of Investment"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
index 9f83bb1ede..4c7c9ffec3 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
@@ -1142,6 +1142,44 @@
"DisplayName:CardHolderName": "Name on Card",
"CreditCardNumberLengthWarning": "Invalid card number",
"ExpirationWarning": "Invalid expiration date",
- "CreateCreditCardModal_Description": "When saving your debit/credit card, a temporary $1 charge will be authorized for verification and promptly refunded."
+ "CreateCreditCardModal_Description": "When saving your debit/credit card, a temporary $1 charge will be authorized for verification and promptly refunded.",
+ "ReturnOfInvestmentTitle": "Return of Investment",
+ "ReduceYourDevelopmentCostsDescription": "Reduce your development costs by more than 50% with the ABP Framework. How? Keep reading...",
+ "SettingUpTheArchitectureTitle": "Setting Up the Architecture",
+ "DoingEverythingFromScratch": "Doing everything from scratch",
+ "SettingUpTheArchitecture_Description1": "Organize code base and solution structure",
+ "SettingUpTheArchitecture_Description2": "Determine, install and configure essential 3rd-party libraries",
+ "SettingUpTheArchitecture_Description3": "Setup automated integration and unit test infrastructure",
+ "SettingUpTheArchitecture_Description4": "Determine and document code standards, train the development team",
+ "UsingTheABPFramework": "Using the ABP Framework",
+ "UseABPSettingUpTheArchitecture_Description": "Use ABP's startup solution templates",
+ "ReduceCostsWithABP": "Reduce Costs with ABP by",
+ "ReduceCostsBy": "80% to 100%",
+ "DesigningTheUserInterfaceTitle": "Designing the User Interface",
+ "DesigningTheUserInterface_Description1": "Create or buy a UI theme",
+ "DesigningTheUserInterface_Description2": "Adapt the UI theme to the solution",
+ "DesigningTheUserInterface_Description3": "Build the essential UI parts (layout, menu, header, footer with responsive design)",
+ "DesigningTheUserInterface_Description4": "Ensure the design consistency across application pages",
+ "UseABPDesigningTheUserInterface_Description": "Use ABP's LeptonX UI Theme",
+ "DevelopingApplicationFeaturesTitle": "Developing the Application Features",
+ "DevelopingApplicationFeatures_Description1": "Develop your own business logic",
+ "DevelopingApplicationFeatures_Description2": "Develop every page one by one",
+ "DevelopingApplicationFeatures_Description3": "Develop common business modules yourself",
+ "DevelopingApplicationFeatures_Description4": "Develop the authentication system (single sign on, 2 factor auth, social logins, reset password, email activation, etc...)",
+ "DevelopingApplicationFeatures_Description5": "Apply cross-cutting concerns in every use case (DB transactions, authorization, validation, exception handling, etc...)",
+ "DevelopingApplicationFeatures_Description6": "Develop common base classes and utility services",
+ "DevelopingApplicationFeatures_Description7": "Develop common non-business requirements (audit logging, soft-delete, background jobs, permission system, etc.)",
+ "UseABPDevelopingApplicationFeatures_Description1": "Develop your own business logic",
+ "UseABPDevelopingApplicationFeatures_Description2": "Use ABP Suite to automatically generate CRUD-like pages",
+ "UseABPDevelopingApplicationFeatures_Description3": "Directly use ABP's pre-built common application modules and customize based on your unique requirements",
+ "ReduceCostsBy_2": "40% to 60%",
+ "WhyABPIoPlatform": "Why ABP.IO Platform?",
+ "WhyShouldYouUsetheABPIOPlatform": "Why should you use the ABP.IO Platform instead of creating a new solution from scratch?",
+ "ExploreMore": "Explore More",
+ "DocumentIntroducesDescription": "If you want to learn more details about why should you use the ABP.IO Platform instead of creating a new solution from scratch, read the following document: ",
+ "ReturnOfInvestmentPageAbout": "This page covers the fundamental steps of developing a software solution and explains how the ABP.IO Platform reduces your development costs at each step.",
+ "LearnMore": "Learn More",
+ "ReturnOfInvestment": "Return of Investment",
+ "ReturnOfInvestment_Description": "Learn how to reduce your development costs by more than %50."
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json
index 3e0789ce36..3a9d58167f 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json
@@ -467,6 +467,7 @@
"Title": "العنوان",
"TitlePlaceholder": "مطور برامج، مدير تكنولوجيا المعلومات، إلخ.",
"Characters": "الأحرف",
- "ABPTestimonialDescription": "ABP Framework: دعونا نسمع شهادتك"
+ "ABPTestimonialDescription": "ABP Framework: دعونا نسمع شهادتك",
+ "LeaveUsReview": "ترك لنا المراجعة"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json
index 8e6d88a6f9..5432cbefd5 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json
@@ -467,6 +467,7 @@
"Title": "Titul",
"TitlePlaceholder": "Vývojář softwaru, CTO atd.",
"Characters": "znaky",
- "ABPTestimonialDescription": "ABP Framework: Pojďme slyšet vaši referenci"
+ "ABPTestimonialDescription": "ABP Framework: Pojďme slyšet vaši referenci",
+ "LeaveUsReview": "Zanechte nám recenzi"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json
index 8d2e9aa519..f8f840a142 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json
@@ -467,6 +467,7 @@
"Title": "Titel",
"TitlePlaceholder": "Softwareentwickler, CTO usw.",
"Characters": "zeichen",
- "ABPTestimonialDescription": "ABP Framework: Lass uns deine Bewertung hören"
+ "ABPTestimonialDescription": "ABP Framework: Lass uns deine Bewertung hören",
+ "LeaveUsReview": "Hinterlassen Sie uns eine Bewertung"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json
index a7f4dd4f62..f0f5dbd496 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en-GB.json
@@ -271,6 +271,7 @@
"DDDBookEmailBody": "Thank you.
To download your book, click here.",
"SubscribeToNewsletter": "Subscribe to the newsletter to get information about happenings in the ABP.IO Platform, like new releases, posts, offers, and more.",
"FirstEdition": "First Edition",
- "SelectUITheme": "Select UI Theme"
+ "SelectUITheme": "Select UI Theme",
+ "LeaveUsReview": "Leave us review"
}
}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
index 19fbda3790..ddf9d646bc 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
@@ -478,6 +478,7 @@
"PasswordLength": "The field Password must be a string with a maximum length of 32.",
"PasswordRequired": "The Password field is required.",
"AddressLength": "The field Address must be a string with a maximum length of 255.",
- "GenderRequired": "The Gender field is required."
+ "GenderRequired": "The Gender field is required.",
+ "LeaveUsReview": "Leave us review"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json
index 2473197573..fbe8ab3a1e 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json
@@ -467,6 +467,7 @@
"Title": "Título",
"TitlePlaceholder": "Desarrollador de software, CTO, etc.",
"Characters": "caracteres",
- "ABPTestimonialDescription": "ABP Framework: Escuchemos tu testimonio"
+ "ABPTestimonialDescription": "ABP Framework: Escuchemos tu testimonio",
+ "LeaveUsReview": "Déjanos tu reseña"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json
index 2f25c77ce8..5454a6c485 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json
@@ -467,6 +467,7 @@
"Title": "Titteli",
"TitlePlaceholder": "Ohjelmistokehittäjä, CTO, jne.",
"Characters": "hahmot",
- "ABPTestimonialDescription": "ABP Framework: Kuunnellaanpa sinun suosittelua"
+ "ABPTestimonialDescription": "ABP Framework: Kuunnellaanpa sinun suosittelua",
+ "LeaveUsReview": "Jätä meille arvostelu"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json
index fa01f12ecc..eb17992bf7 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json
@@ -467,6 +467,7 @@
"Title": "Titre",
"TitlePlaceholder": "Développeur de logiciels, CTO, etc.",
"Characters": "caractères",
- "ABPTestimonialDescription": "ABP Framework : Écoutons votre témoignage"
+ "ABPTestimonialDescription": "ABP Framework : Écoutons votre témoignage",
+ "LeaveUsReview": "Laissez-nous votre avis"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json
index b1df00ef53..e049190196 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json
@@ -467,6 +467,7 @@
"Title": "शीर्षक",
"TitlePlaceholder": "सॉफ़्टवेयर डेवेलपर, सीटीओ, आदि।",
"Characters": "अक्षर",
- "ABPTestimonialDescription": "ABP Framework: आइए आपका प्रशंसापत्र सुनें"
+ "ABPTestimonialDescription": "ABP Framework: आइए आपका प्रशंसापत्र सुनें",
+ "LeaveUsReview": "हमें समीक्षा छोड़ें"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json
index fe90b4dc7e..3a169c1aff 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json
@@ -467,6 +467,7 @@
"Title": "Naslov",
"TitlePlaceholder": "Razvojni inženjer, CTO, itd.",
"Characters": "znakovi",
- "ABPTestimonialDescription": "ABP Framework: Hajde da čujemo tvoje iskustvo"
+ "ABPTestimonialDescription": "ABP Framework: Hajde da čujemo tvoje iskustvo",
+ "LeaveUsReview": "Ostavite nam recenziju"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json
index 41655fe1dd..e77d99e5ac 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json
@@ -467,6 +467,7 @@
"Title": "Cím",
"TitlePlaceholder": "Szoftvertervező, CTO, stb.",
"Characters": "karakterek",
- "ABPTestimonialDescription": "ABP Framework: Halljuk az Ön beszámolóját"
+ "ABPTestimonialDescription": "ABP Framework: Halljuk az Ön beszámolóját",
+ "LeaveUsReview": "Hagyjon véleményt nekünk"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json
index f9c6f8b179..0da65b363a 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json
@@ -467,6 +467,7 @@
"Title": "Titill",
"TitlePlaceholder": "Hugbúnaðarþróunarmiðill, CTO o.s.frv.",
"Characters": "stafir",
- "ABPTestimonialDescription": "ABP Framework: Við skulum heyra vitnisburð þinn"
+ "ABPTestimonialDescription": "ABP Framework: Við skulum heyra vitnisburð þinn",
+ "LeaveUsReview": "Skildu eftir okkur umsögn"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json
index c9e082259b..3feb80b6da 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json
@@ -468,5 +468,6 @@
"TitlePlaceholder": "Sviluppatore di software, CTO ecc.",
"Characters": "caratteri",
"ABPTestimonialDescription": "ABP Framework: Ascoltiamo la tua testimonianza",
+ "LeaveUsReview": "Lasciaci una recensione"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json
index 5e923a140e..6cc299f032 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json
@@ -467,6 +467,7 @@
"Title": "Titel",
"TitlePlaceholder": "Softwareontwikkelaar, CTO enz.",
"Characters": "tekens",
- "ABPTestimonialDescription": "ABP Framework: Laten we uw getuigenis horen"
+ "ABPTestimonialDescription": "ABP Framework: Laten we uw getuigenis horen",
+ "LeaveUsReview": "Laat ons een beoordeling achter"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json
index f276cf6082..8b4da70fad 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json
@@ -467,6 +467,7 @@
"Title": "Tytuł",
"TitlePlaceholder": "Programista, CTO itp.",
"Characters": "znaki",
- "ABPTestimonialDescription": "Struktura ABP: Posłuchajmy Twojej opinii"
+ "ABPTestimonialDescription": "Struktura ABP: Posłuchajmy Twojej opinii",
+ "LeaveUsReview": "Zostaw nam recenzję"
}
-}
\ No newline at end of file
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json
index ee7ca3161b..6b6d7d4a89 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json
@@ -467,6 +467,7 @@
"Title": "Título",
"TitlePlaceholder": "Desenvolvedor de software, CTO etc.",
"Characters": "caracteres",
- "ABPTestimonialDescription": "Estrutura ABP: vamos ouvir seu depoimento"
+ "ABPTestimonialDescription": "Estrutura ABP: vamos ouvir seu depoimento",
+ "LeaveUsReview": "Deixe-nos uma avaliação"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json
index 9822f54642..ee67921a5a 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json
@@ -467,6 +467,7 @@
"Title": "Titlu",
"TitlePlaceholder": "Dezvoltator software, CTO etc.",
"Characters": "caractere",
- "ABPTestimonialDescription": "Cadrul ABP: Haideți să vă ascultăm mărturia"
+ "ABPTestimonialDescription": "Cadrul ABP: Haideți să vă ascultăm mărturia",
+ "LeaveUsReview": "Lasă-ne o recenzie"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json
index 2b94373e76..a2de5e0520 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json
@@ -465,6 +465,7 @@
"Title": "Заголовок",
"TitlePlaceholder": "Разработчик программного обеспечения, технический директор и т. д.",
"Characters": "Символы",
- "ABPTestimonialDescription": "ABP Framework: давайте послушаем ваш отзыв"
+ "ABPTestimonialDescription": "ABP Framework: давайте послушаем ваш отзыв",
+ "LeaveUsReview": "Оставьте нам отзыв"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json
index ca72d2cf19..861ae3ad7e 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json
@@ -467,6 +467,7 @@
"Title": "Názov",
"TitlePlaceholder": "Vývojár softvéru, CTO atď.",
"Characters": "znaky",
- "ABPTestimonialDescription": "Rámec ABP: Vypočujme si vaše svedectvo"
+ "ABPTestimonialDescription": "Rámec ABP: Vypočujme si vaše svedectvo",
+ "LeaveUsReview": "Zanechajte nám recenziu"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json
index e9366a8db9..5673f8e5b3 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json
@@ -467,6 +467,7 @@
"Title": "Naslov",
"TitlePlaceholder": "Razvijalec programske opreme, tehnični direktor itd.",
"Characters": "znaki",
- "ABPTestimonialDescription": "Ogrodje ABP: poslušajmo vaše pričevanje"
+ "ABPTestimonialDescription": "Ogrodje ABP: poslušajmo vaše pričevanje",
+ "LeaveUsReview": "Pustite nam oceno"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json
index dde8ab7072..a309e0bbdb 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json
@@ -427,7 +427,7 @@
"PasswordLength": "Şifre alanı maksimum 32 karakter olmalıdır.",
"PasswordRequired": "Şifre alanı zorunludur.",
"AddressLength": "Adres alanı maksimum uzunluğu 255 karakter olmalıdır.",
- "GenderRequired": "Cinsiyet alanı zorunludur."
-
+ "GenderRequired": "Cinsiyet alanı zorunludur.",
+ "LeaveUsReview": "Yorumunuzu paylaşın"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json
index b8ad4565be..76a93b26bb 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json
@@ -467,6 +467,7 @@
"Title": "Tiêu đề",
"TitlePlaceholder": "Nhà phát triển phần mềm, CTO, v.v.",
"Characters": "Ký tự",
- "ABPTestimonialDescription": "Khung ABP: Hãy nghe lời chứng thực của bạn"
+ "ABPTestimonialDescription": "Khung ABP: Hãy nghe lời chứng thực của bạn",
+ "LeaveUsReview": "Để lại cho chúng tôi xem xét"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
index 88d56a6303..c595374c85 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
@@ -469,6 +469,7 @@
"Title": "标题",
"TitlePlaceholder": "软件开发人员、CTO等",
"Characters": "字符",
- "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言"
+ "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言",
+ "LeaveUsReview": "给我们留下评论"
}
}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json
index dc396ce8b9..83396cf8c2 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json
@@ -469,6 +469,7 @@
"Title": "标题",
"TitlePlaceholder": "软件开发人员、CTO等",
"Characters": "字符",
- "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言"
+ "ABPTestimonialDescription": "ABP 框架:让我们听听您的感言",
+ "LeaveUsReview": "给我们留下评论"
}
}
\ No newline at end of file
diff --git a/docs/en/API/Auto-API-Controllers.md b/docs/en/API/Auto-API-Controllers.md
index 0ffbc644a8..a81da00b98 100644
--- a/docs/en/API/Auto-API-Controllers.md
+++ b/docs/en/API/Auto-API-Controllers.md
@@ -12,9 +12,9 @@ Basic configuration is simple. Just configure `AbpAspNetCoreMvcOptions` and use
[DependsOn(BookStoreApplicationModule)]
public class BookStoreWebModule : AbpModule
{
- public override void ConfigureServices(ServiceConfigurationContext context)
+ public override void PreConfigureServices(ServiceConfigurationContext context)
{
- Configure(options =>
+ PreConfigure(options =>
{
options
.ConventionalControllers
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md
new file mode 100644
index 0000000000..24f55474ad
--- /dev/null
+++ b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md
@@ -0,0 +1,239 @@
+# ABP.IO Platform 8.1 RC Has Been Released
+
+Today, we are happy to release the [ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) version **8.1 RC** (Release Candidate). This blog post introduces the new features and important changes in this new version.
+
+Try this version and provide feedback for a more stable version of ABP v8.1! Thanks to all of you.
+
+## Get Started with the 8.1 RC
+
+Follow the steps below to try version 8.1.0 RC today:
+
+1) **Upgrade** the ABP CLI to version `8.1.0-rc.1` using a command line terminal:
+
+````bash
+dotnet tool update Volo.Abp.Cli -g --version 8.1.0-rc.1
+````
+
+**or install** it if you haven't before:
+
+````bash
+dotnet tool install Volo.Abp.Cli -g --version 8.1.0-rc.1
+````
+
+2) Create a **new application** with the `--preview` option:
+
+````bash
+abp new BookStore --preview
+````
+
+See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options.
+
+> You can also use the [Get Started](https://abp.io/get-started) page to generate a CLI command to create a new application.
+
+You can use any IDE that supports .NET 8.x, like [Visual Studio 2022](https://visualstudio.microsoft.com/downloads/).
+
+## Migration Guides
+
+There are a few breaking changes in this version that may affect your application.
+Please see the following migration documents, if you are upgrading from v8.x or earlier:
+
+* [ABP Framework 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/abp/8.1/Migration-Guides/Abp-8_1)
+* [ABP Commercial 8.0 to 8.1 Migration Guide](https://docs.abp.io/en/commercial/8.1/migration-guides/v8_1)
+
+## What's New with ABP Framework 8.1?
+
+In this section, I will introduce some major features released in this version.
+Here is a brief list of titles explained in the next sections:
+
+* Introducing the `ExposeKeyedServiceAttribute`
+* Custom Menu Component Support for MVC UI
+* Introducing the `DisableAbpFeaturesAttribute`
+
+### Introducing the `ExposeKeyedServiceAttribute`
+
+[Keyed dependency injection (DI) services](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0#keyed-services) were added to the built-in DI container as a new feature with .NET 8.0. This is an important feature, which allows for registering and retrieving DI services using keys/names.
+
+In this version, we have introduced the `ExposeKeyedServiceAttribute` to allow you to automatically register keyed services by conventions:
+
+```csharp
+[ExposeKeyedService("taxCalculator")]
+[ExposeKeyedService("calculator")]
+public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency
+{
+}
+```
+
+In the example above, the `TaxCalculator` class exposes the `ITaxCalculator` interface with the key `taxCalculator` and the `ICalculator` interface with the key `calculator`.
+
+Thanks to that, then you can use the [`FromKeyedServicesAttribute`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.fromkeyedservicesattribute?view=dotnet-plat-ext-8.0) to resolve a certain keyed service in the constructor:
+
+```csharp
+public class MyClass
+{
+ //...
+ public MyClass([FromKeyedServices("taxCalculator")] ITaxCalculator taxCalculator)
+ {
+ TaxCalculator = taxCalculator;
+ }
+}
+```
+
+> Notice that the `ExposeKeyedServiceAttribute` only exposes the keyed services. So, you can not inject the `ITaxCalculator` or `ICalculator` interfaces in your application without using the `FromKeyedServicesAttribute` as shown in the example above.
+
+> If you want to learn more about the keyed dependency injection services, please refer to [Microsoft's documentation](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0#keyed-services) and [ABP Framework's Dependency Injection document](https://docs.abp.io/en/abp/8.1/Dependency-Injection#exposekeyedservice-attribute).
+
+### Custom Menu Component Support for MVC UI
+
+In this version, we have introduced the **custom menu component support**, which allows you to use a custom component for a certain menu item.
+
+You can use the `UseComponent` extension method while defining menu items to use your custom component for the related menu item:
+
+```csharp
+context.Menu.Items.Add(
+ new ApplicationMenuItem("Custom.1", "My Custom Menu", "#")
+ .UseComponent(typeof(MyMenuComponent)));
+```
+
+Then, for the related menu item, your custom component will be rendered on the UI.
+
+### Introducing the `DisableAbpFeaturesAttribute`
+
+In this version, we have introduced the `DisableAbpFeaturesAttribute` to allow you to disable interceptors, middlewares, and MVC filters for a specific controller.
+
+For example, you may want to disable interceptors for a certain controller, but you may also don't want to disable middlewares and mvc filters, in that case, you can use the `DisableAbpFeaturesAttribute` as follows:
+
+```csharp
+[Route("api/my-endpoint")]
+[DisableAbpFeatures(DisableInterceptors = true, DisableMiddleware = false, DisableMvcFilters = false)]
+public class MyController : AbpController
+{
+
+}
+```
+
+This can be useful if you have some APIs that are used frequently but you don't need all the features of ABP Framework.
+
+> **Note:** If you want to disable all interceptors, middlewares, and filters for a certain controller, then you can use the `[DisableAbpFeatures]` without the need to specify the parameters, they are disabled by default.
+
+## What's New with ABP Commercial 8.1?
+
+We've also worked on ABP Commercial to align the features and changes made in the ABP Framework. The following sections introduce a few new features coming with ABP Commercial 8.1.
+
+### Suite: New Features
+
+In this version, we mostly worked on ABP Suite and implemented some wanted features, such as *bulk delete*, *filterable properties*, *customizable page title*, *allowing establishing relationships with installed ABP modules' entities* and *supporting the `BasicAggregateRoot` as the base class*.
+
+#### Bulk Delete
+
+From this version on, ABP Suite allows you to perform bulk deletion of records based on specified criteria.
+
+
+
+To enable *bulk delete support*, you should enable the *Bulk delete* option in the CRUD page generation page, along with the *Create user interface* option (they are enabled by default). When you enable the *bulk delete support*, you will see the checkboxes for each line in the datatable:
+
+
+
+By selecting these checkboxes, you can delete all records in the current datatable (10 records by default), or delete all records in the database (by selecting *select all xx items* selection), or delete any records you want by selecting them one by one.
+
+> **Note:** This feature has already been implemented for MVC & Blazor UIs, but not implemented for Angular UI yet. We aim to implement it for Angular UI with *v8.1.0-rc.2*.
+
+#### Filterable Properties
+
+ABP Suite has been generating advanced filters for entities for a while and before this version, if you enabled the *create user interface* option, then all of the properties that you specified were included in the advanced filter section automatically.
+
+In this version, we have introduced the **filterable properties** feature to allow you to select which properties should be filterable and which are not:
+
+
+
+Now, you have full control to select which properties should be included as filter inputs and shown on the advanced filters section on your generated pages.
+
+In other words, once, you select a property as *not filterable*, then the property will not be included in the filter inputs and in the advanced filter section. Also, if there are not any filterable properties for an entity, then the advanced filters section will not be generated.
+
+#### Customizable Page Title
+
+In this version on, ABP Suite allows you to specify the page title for the current entity.
+
+
+
+You just need to specify the *page title* on the CRUD page generation page for a specific entity and then it will be used as a localization key in the application (and also will be localized - for example, if you specify it as 'MyPageTitle', then it will be localized in English as 'My Page Title'), so you can localize it for different languages later on.
+
+#### Allowing Establishing Relationships with Installed ABP Modules' Entities
+
+In this version, ABP Suite allows you to establish one-to-many relationship with pre-installed ABP Modules. You can add any entity from pre-installed ABP modules as a navigation property, by checking the **Include entities from ABP modules** checkbox in the navigation property model and choosing the related module entity as in the following figure:
+
+
+
+In the example above, the `IdentityUser` entity is selected as the navigation property but you can also choose any entity from the installed ABP modules in the navigation property model.
+
+> **Note:** Ensure that your solution is built properly before establishing relationship between your own entity and a module entity because ABP Suite scans assemblies and finds which ABP modules you are using and lists their entities in the navigation property model if you have checked the **Include entities from ABP modules** checkbox.
+
+#### Support `BasicAggregateRoot` Base Class
+
+In this version on, ABP Suite allows you to choose the `BasicAggregateRoot` as the base class while generating an entity:
+
+
+
+> You can choose the [BasicAggregateRoot](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/BasicAggregateRoot.cs) if you want to create an aggregate root without the `IHasExtraProperties` and `IHasConcurrencyStamp` interfaces implemented (extra properties & concurrency check).
+
+### ABP Studio v0.6.5 Has Been Released!
+
+We have just released v0.6.5 for ABP Studio and with this version, we fixed many minor bugs reported by you, started supporting running multiple ABP Studio instances, and added important features, such as adding a public website to the new microservice template, and so on...
+
+In addition to all of this, we continue to enrich ABP Studio's documentation as always and you can read them at [https://docs.abp.io/en/commercial/latest/studio/overview](https://docs.abp.io/en/commercial/latest/studio/overview).
+
+Please try ABP Studio v0.6.5 and [provide feedback](https://support.abp.io/QA/Questions/6416/ABP-Studio-Bugs--Issues) to help us release more stable versions. Thanks in advance!
+
+## Community News
+
+### .NET Conf China 2023 Watch Party
+
+
+
+ABP.IO was thrilled to sponsor the first .NET Community event in 2024 held in Shenzen on January 14, 2024.
+
+The event included four wonderful technical lectures to reveal big data and AI's potential opportunities and innovations. It was a transfer of knowledge and a platform for communication and cooperation among technology enthusiasts and we are happy to be attended.
+
+> If you want to learn more about the .NET Conf China 2023 Watch Party event, please check [the blog post](https://blog.abp.io/abp/2024-First-Community-Event).
+
+### Volosoft Attended NDC London 2024
+
+
+
+Core team members of the ABP Framework, [Halil Ibrahim Kalkan](https://twitter.com/hibrahimkalkan), [Alper Ebicoglu](https://twitter.com/alperebicoglu), [Engincan Veske](https://twitter.com/EngincanVeske), and [Bige Beşikci Yaman](https://twitter.com/bigedediki) attended [NDC London 2024](https://ndclondon.com/) from the 31st of January to the 2nd of February.
+
+It was the 5th time in a row we were a proud sponsor of NDC London. It, now, basically feels like home spending 3 days in Queen Elizabeth Centre II with NDC London for the [ABP.IO](https://abp.io/) team to be there.
+
+These 3 days with the team were all about chatting and having fun with amazing attendees and speakers. We met with talented and passionate software developers and introduced the [open source ABP Framework](https://github.com/abpframework/abp) - web application framework built on ASP.NET Core and [ABP Commercial](https://commercial.abp.io/) - the complete web application development platform built on open source ABP Framework - to them.
+
+> We shared our insights and key highlights from the NDC London 2024 event, which you can find at [https://blog.abp.io/abp/NDC-London-2024-ABP.IO-Key-Highlights](https://blog.abp.io/abp/NDC-London-2024-ABP.IO-Key-Highlights).
+
+### New ABP Community Articles
+
+There are exciting articles contributed by the ABP community as always. I will highlight some of them here:
+
+* [Every Programmer Should Know #2: Optimistic Concurrency Control](https://community.abp.io/posts/every-programmer-should-know-2-optimistic-concurrency-control-sms9xs9n) by [Berkan Sasmaz](https://github.com/berkansasmaz)
+* [Global Error Handling in Angular](https://community.abp.io/posts/global-error-handling-in-angular-gjcb2f1e) by [Sinan Öztürk](https://github.com/Sinan997)
+* [ABP Framework goes Azure](https://community.abp.io/posts/abp-framework-goes-azure-ub4u5ax5) by [Bart Van Hoey](https://github.com/bartvanhoey)
+* [ABP Supports .NET8](https://community.abp.io/posts/abp-supports-.net8-e4gve6ih) by [Alper Ebicoglu](https://community.abp.io/members/alper)
+* [Engincan Veske](https://github.com/EngincanV) has created **three** new community articles:
+ * [ABP Now Supports Keyed Services!](https://community.abp.io/posts/abp-now-supports-keyed-services-6k92wz7h)
+ * [Mutation Testing in C# with Stryker](https://community.abp.io/posts/mutation-testing-in-c-with-stryker-tp6u599h)
+ * [ABP Suite: Best CRUD Page Generation Tool for .NET](https://community.abp.io/posts/abp-suite-best-crud-page-generation-tool-for-.net-cmm9xs3n)
+* [Ahmed Tarek](https://github.com/AhmedTarekHasan) has created **nine** new community articles:
+ * [📑 Cover IO Based Apps With Unit Tests in .NET C# 🧪](https://community.abp.io/posts/-cover-io-based-apps-with-unit-tests-in-.net-c--zp6kip2r)
+ * [Better Enhanced Repository Pattern Implementation in .NET C#](https://community.abp.io/posts/better-enhanced-repository-pattern-implementation-in-.net-c-hpkbxr3l)
+ * [When Not To Use DI, IoC, and IoC Containers in .NET C#](https://community.abp.io/posts/when-not-to-use-di-ioc-and-ioc-containers-in-.net-c-n769hq8u)
+ * [⏰ Best Practice for Using Timers in .NET C# ⏳](https://community.abp.io/posts/-best-practice-for-using-timers-in-.net-c--3cqvew5o)
+ * [How to Fully Cover .NET C# Console Application With Unit Tests](https://community.abp.io/posts/how-to-fully-cover-.net-c-console-application-with-unit-tests-3h248yhe)
+ * [Web Scraping in .NET C#](https://community.abp.io/posts/web-scraping-in-.net-c-6pkp1abi)
+ * [Step by step guide to develop a Fluent API from scratch in .NET C# using the Builder Design Pattern](https://community.abp.io/posts/step-by-step-guide-to-develop-a-fluent-api-from-scratch-in-.net-c-using-the-builder-design-pattern-sbww0vky)
+ * [A Best Practice for Designing Interfaces in .NET C#](https://community.abp.io/posts/a-best-practice-for-designing-interfaces-in-.net-c-9xqc4h8d)
+ * [Invariance, Covariance, and Contravariance in .NET C#](https://community.abp.io/posts/invariance-covariance-and-contravariance-in-.net-c-9blmuhme)
+
+Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community.
+
+## Conclusion
+
+This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/8.1/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v8.1 RC and provide feedback to help us release a more stable version.
+
+Thanks for being a part of this community!
\ No newline at end of file
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/basic-aggregate-root.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/basic-aggregate-root.png
new file mode 100644
index 0000000000..ed57443284
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/basic-aggregate-root.png differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete-datatable.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete-datatable.png
new file mode 100644
index 0000000000..8357cebb02
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete-datatable.png differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete.png
new file mode 100644
index 0000000000..2bdc1d8bcc
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/bulk-delete.png differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/cover-image.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/cover-image.png
new file mode 100644
index 0000000000..6d95e19c24
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/cover-image.png differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/dotnet-conf-china-2023-watch-party.jpg b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/dotnet-conf-china-2023-watch-party.jpg
new file mode 100644
index 0000000000..818bc10ce8
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/dotnet-conf-china-2023-watch-party.jpg differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/filterable-properties.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/filterable-properties.png
new file mode 100644
index 0000000000..4aff361825
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/filterable-properties.png differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/ndc-london-2024.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/ndc-london-2024.png
new file mode 100644
index 0000000000..cb03ca7462
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/ndc-london-2024.png differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/page-title.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/page-title.png
new file mode 100644
index 0000000000..1f767838db
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/page-title.png differ
diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/suite-include-entities-from-abp-modules.png b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/suite-include-entities-from-abp-modules.png
new file mode 100644
index 0000000000..6bb0920800
Binary files /dev/null and b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/suite-include-entities-from-abp-modules.png differ
diff --git a/docs/en/Getting-Started-Create-Solution.md b/docs/en/Getting-Started-Create-Solution.md
index 45689b45fc..96740abf89 100644
--- a/docs/en/Getting-Started-Create-Solution.md
+++ b/docs/en/Getting-Started-Create-Solution.md
@@ -8,6 +8,19 @@
"Tiered": ["Yes", "No"]
}
````
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Running the solution",
+ "Path": "Getting-Started-Running-Solution"
+ },
+ "Previous": {
+ "Name": "Setup Your Development Environment",
+ "Path": "Getting-Started-Setup-Environment"
+ }
+}
+````
> This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider. For other options, please change the preference on top of this document.
@@ -66,8 +79,4 @@ Configure(options =>
> Or you can delete that code since `Auto` is already the default behavior.
-{{ end }}
-
-## Next Step
-
-* [Running the solution](Getting-Started-Running-Solution.md)
\ No newline at end of file
+{{ end }}
\ No newline at end of file
diff --git a/docs/en/Getting-Started-Running-Solution-Single-Layer.md b/docs/en/Getting-Started-Running-Solution-Single-Layer.md
index 58783b8c3b..18b2316cf6 100644
--- a/docs/en/Getting-Started-Running-Solution-Single-Layer.md
+++ b/docs/en/Getting-Started-Running-Solution-Single-Layer.md
@@ -8,6 +8,16 @@
}
````
+````json
+//[doc-nav]
+{
+ "Previous": {
+ "Name": "Creating a new solution",
+ "Path": "Getting-Started-Create-Solution-Single-Layer"
+ }
+}
+````
+
> This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider. For other options, please change the preference on top of this document.
## Create the Database
diff --git a/docs/en/Getting-Started-Running-Solution.md b/docs/en/Getting-Started-Running-Solution.md
index d71c0a64da..f522016278 100644
--- a/docs/en/Getting-Started-Running-Solution.md
+++ b/docs/en/Getting-Started-Running-Solution.md
@@ -9,6 +9,16 @@
}
````
+````json
+//[doc-nav]
+{
+ "Previous": {
+ "Name": "Creating a new solution",
+ "Path": "Getting-Started-Create-Solution"
+ }
+}
+````
+
> This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider. For other options, please change the preference on top of this document.
## Create the Database
@@ -258,9 +268,4 @@ It may take a longer time for the first build. Once it finishes, it opens the An
{{ end }}
-Enter **admin** as the username and **1q2w3E*** as the password to login to the application. The application is up and running. You can start developing your application based on this startup template.
-
-## See Also
-
-* [Web Application Development Tutorial](Tutorials/Part-1.md)
-* [Application Startup Template](Startup-Templates/Application.md)
+Enter **admin** as the username and **1q2w3E*** as the password to login to the application. The application is up and running. You can start developing your application based on this startup template.
\ No newline at end of file
diff --git a/docs/en/Getting-Started-Setup-Environment-Single-Layer.md b/docs/en/Getting-Started-Setup-Environment-Single-Layer.md
index c9a308a850..6a1483d278 100644
--- a/docs/en/Getting-Started-Setup-Environment-Single-Layer.md
+++ b/docs/en/Getting-Started-Setup-Environment-Single-Layer.md
@@ -8,6 +8,16 @@
}
````
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Creating a new solution",
+ "Path": "Getting-Started-Create-Solution-Single-Layer"
+ }
+}
+````
+
> This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider. For other options, please change the preference on top of this document.
## Setup Your Development Environment
@@ -42,8 +52,4 @@ If you've already installed, you can update it using the following command:
````shell
dotnet tool update -g Volo.Abp.Cli
-````
-
-## Next Step
-
-* [Creating a new solution](Getting-Started-Create-Solution-Single-Layer.md)
\ No newline at end of file
+````
\ No newline at end of file
diff --git a/docs/en/Getting-Started-Setup-Environment.md b/docs/en/Getting-Started-Setup-Environment.md
index 12f7cd5890..2c1b7c4155 100644
--- a/docs/en/Getting-Started-Setup-Environment.md
+++ b/docs/en/Getting-Started-Setup-Environment.md
@@ -8,6 +8,15 @@
"Tiered": ["Yes", "No"]
}
````
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Creating a new solution",
+ "Path": "Getting-Started-Create-Solution"
+ }
+}
+````
> This document assumes that you prefer to use **{{ UI_Value }}** as the UI framework and **{{ DB_Value }}** as the database provider. For other options, please change the preference on top of this document.
@@ -46,8 +55,4 @@ If you've already installed, you can update it using the following command:
````shell
dotnet tool update -g Volo.Abp.Cli
-````
-
-## Next Step
-
-* [Creating a new solution](Getting-Started-Create-Solution.md)
\ No newline at end of file
+````
\ No newline at end of file
diff --git a/docs/en/Integration-Services.md b/docs/en/Integration-Services.md
index 98e3e593e5..6c31fb69bf 100644
--- a/docs/en/Integration-Services.md
+++ b/docs/en/Integration-Services.md
@@ -93,7 +93,7 @@ Configure(options =>
You can filter integration services (or non-integration services) while creating [Auto API Controllers](API/Auto-API-Controllers.md), using the `ApplicationServiceTypes` option of the `ConventionalControllerSetting` by configuring the `AbpAspNetCoreMvcOptions` as shown below:
```csharp
-Configure(options =>
+PreConfigure(options =>
{
options.ConventionalControllers.Create(
typeof(MyApplicationModule).Assembly,
diff --git a/docs/en/Migration-Guides/Abp-8_0.md b/docs/en/Migration-Guides/Abp-8_0.md
index 09e44b7ec8..0cba42d759 100644
--- a/docs/en/Migration-Guides/Abp-8_0.md
+++ b/docs/en/Migration-Guides/Abp-8_0.md
@@ -269,7 +269,7 @@ You can see the following list of NuGet libraries that have been upgraded with .
| OpenIddict.Validation.ServerIntegration | 4.8.0 | 5.0.0 |
| Oracle.EntityFrameworkCore | 7.21.8 | 8.21.121 |
| Polly | 7.2.3 | 8.2.0 |
-| Pomelo.EntityFrameworkCore.MySql | 7.0.0 | 8.0.0-beta.2 |
+| Pomelo.EntityFrameworkCore.MySql | 7.0.0 | 8.0.0 |
| Quartz | 3.4.0 | 3.7.0 |
| Quartz.Extensions.DependencyInjection | 3.4.0 | 3.7.0 |
| Quartz.Plugins.TimeZoneConverter | 3.4.0 | 3.7.0 |
diff --git a/docs/en/Migration-Guides/Abp-8_1.md b/docs/en/Migration-Guides/Abp-8_1.md
index 6f4c316d3f..f13ac8d209 100644
--- a/docs/en/Migration-Guides/Abp-8_1.md
+++ b/docs/en/Migration-Guides/Abp-8_1.md
@@ -83,3 +83,64 @@ public partial class Add_NormalizedName : Migration
See https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/managing?tabs=dotnet-core-cli#adding-raw-sql to learn how to add raw SQL to migrations.
+## Use `Asp.Versioning.Mvc` to replace `Microsoft.AspNetCore.Mvc.Versioning`
+
+The Microsoft.AspNetCore.Mvc.Versioning packages are now deprecated and superseded by Asp.Versioning.Mvc.
+See the announcement here: https://github.com/dotnet/aspnet-api-versioning/discussions/807
+
+The namespace of the `[ControllerName]` attribute has changed to `using Asp.Versioning`, Please update your code to use the new namespace.
+
+Related PR: https://github.com/abpframework/abp/pull/18380
+
+## New asynchronous methods for `IAppUrlProvider`
+
+The `IsRedirectAllowedUrl` method of `IAppUrlProvider` has been changed to `IsRedirectAllowedUrlAsync` and it is now an async method.
+You should update your usage of `IAppUrlProvider` to use the new method.
+
+Related PR: https://github.com/abpframework/abp/pull/18492
+
+## New attribute: `ExposeKeyedServiceAttribute`
+
+The new `ExposeKeyedServiceAttribute` is used to control which keyed services are provided by the related class. Example:
+
+````C#
+[ExposeKeyedService("taxCalculator")]
+[ExposeKeyedService("calculator")]
+public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency
+{
+}
+````
+
+In the example above, the `TaxCalculator` class exposes the `ITaxCalculator` interface with the key `taxCalculator` and the `ICalculator` interface with the key `calculator`. That means you can get keyed services from the `IServiceProvider` as shown below:
+
+````C#
+var taxCalculator = ServiceProvider.GetRequiredKeyedService("taxCalculator");
+var calculator = ServiceProvider.GetRequiredKeyedService("calculator");
+````
+
+Also, you can use the [`FromKeyedServicesAttribute`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.fromkeyedservicesattribute?view=dotnet-plat-ext-8.0) to resolve a certain keyed service in the constructor:
+
+```csharp
+public class MyClass
+{
+ //...
+ public MyClass([FromKeyedServices("taxCalculator")] ITaxCalculator taxCalculator)
+ {
+ TaxCalculator = taxCalculator;
+ }
+}
+```
+
+> Notice that the `ExposeKeyedServiceAttribute` only exposes the keyed services. So, you can not inject the `ITaxCalculator` or `ICalculator` interfaces in your application without using the `FromKeyedServicesAttribute` as shown in the example above. If you want to expose both keyed and non-keyed services, you can use the `ExposeServicesAttribute` and `ExposeKeyedServiceAttribute` attributes together as shown below:
+````C#
+[ExposeKeyedService("taxCalculator")]
+[ExposeKeyedService("calculator")]
+[ExposeServices(typeof(ITaxCalculator), typeof(ICalculator))]
+public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransientDependency
+{
+}
+````
+
+This is a small **Breaking Change** because `IOnServiceExposingContext` has changed. You should update your usage of `IOnServiceExposingContext` if you have related code.
+
+Related PR: https://github.com/abpframework/abp/pull/18819
diff --git a/docs/en/Migration-Guides/Index.md b/docs/en/Migration-Guides/Index.md
index e7dfa97f86..2206ac9002 100644
--- a/docs/en/Migration-Guides/Index.md
+++ b/docs/en/Migration-Guides/Index.md
@@ -2,6 +2,7 @@
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md).
+- [8.0 to 8.1](Abp-8_1.md)
- [7.x to 8.0](Abp-8_0.md)
- [7.3 to 7.4](Abp-7_4.md)
- [7.2 to 7.3](Abp-7_3.md)
diff --git a/docs/en/Modules/Docs.md b/docs/en/Modules/Docs.md
index 58dd811397..81a8c49ab2 100644
--- a/docs/en/Modules/Docs.md
+++ b/docs/en/Modules/Docs.md
@@ -367,7 +367,7 @@ You can use [ABP Framework](https://github.com/abpframework/abp/) GitHub documen
For `SQL` databases, you can use the below `T-SQL` command to insert the specified sample into your `DocsProjects` table:
```mssql
-INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939658', N'ABP framework (GitHub)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'GitHub', N'{"GitHubRootUrl":"https://github.com/abpframework/abp/tree/{version}/docs","GitHubAccessToken":"***","GitHubUserAgent":""}', N'/', N'dev', N'')
+INSERT [dbo].[DocsProjects] ([Id], [Name], [ShortName], [Format], [DefaultDocumentName], [NavigationDocumentName], [MinimumVersion], [DocumentStoreType], [ExtraProperties], [MainWebsiteUrl], [LatestVersionBranchName], [ParametersDocumentName], [ConcurrencyStamp]) VALUES (N'12f21123-e08e-4f15-bedb-ae0b2d939659', N'ABP framework (FileSystem)', N'abp', N'md', N'Index', N'docs-nav.json', NULL, N'FileSystem', N'{"Path":"C:\\Github\\abp\\docs"}', N'/', NULL, N'', N'12f21123e08e4f15bedbae0b2d939659')
```
Be aware that `GitHubAccessToken` is masked. It's a private token and you must get your own token and replace the `***` string.
diff --git a/docs/en/MongoDB.md b/docs/en/MongoDB.md
index 0faa6a7d26..df7f92e779 100644
--- a/docs/en/MongoDB.md
+++ b/docs/en/MongoDB.md
@@ -82,6 +82,34 @@ If you only need to configure the collection name, you can also use `[MongoColle
public IMongoCollection Questions => Collection();
````
+### Configure Indexes and CreateCollectionOptions for a Collection
+
+You can configure indexes and `CreateCollectionOptions` for your collections by overriding the `CreateModel` method. Example:
+
+````csharp
+protected override void CreateModel(IMongoModelBuilder modelBuilder)
+{
+ base.CreateModel(modelBuilder);
+
+ modelBuilder.Entity(b =>
+ {
+ b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary);
+ b.ConfigureIndexes(indexes =>
+ {
+ indexes.CreateOne(
+ new CreateIndexModel(
+ Builders.IndexKeys.Ascending("MyProperty"),
+ new CreateIndexOptions { Unique = true }
+ )
+ );
+ }
+ );
+ });
+}
+````
+
+This example sets a collation for the collection and creates a unique index for the `MyProperty` property.
+
### Configure the Connection String Selection
If you have multiple databases in your application, you can configure the connection string name for your DbContext using the `[ConnectionStringName]` attribute. Example:
diff --git a/docs/en/Road-Map.md b/docs/en/Road-Map.md
index 05e071371a..9dfbb86d41 100644
--- a/docs/en/Road-Map.md
+++ b/docs/en/Road-Map.md
@@ -1,33 +1,31 @@
# ABP Framework Road Map
-This document provides a road map, release schedule and planned features for the ABP Framework.
+This document provides a road map, release schedule, and planned features for the ABP Framework.
## Next Versions
-### v8.1
+### v8.2
-The next version will be 8.1 and planned to release the stable 8.1 version in February, 2024. We will be mostly working on the following topics:
+The next version will be 8.2 and planned to release the stable 8.2 version in June 2024. We will be mostly working on the following topics:
-* Blazor Full-Stack UI ([#16156](https://github.com/abpframework/abp/issues/16156))
-* Upgrade to OpenIddict 5.x ([#17605](https://github.com/abpframework/abp/issues/17605))
+* Blazor Full-Stack UI ([#18289](https://github.com/abpframework/abp/issues/18289))
* Angular Universal ([#15782](https://github.com/abpframework/abp/issues/15782))
-* Blazor - Forms & Validation Documentation ([#16400](https://github.com/abpframework/abp/issues/16400))
+* Upgrading React Native template to the latest major release 0.72.7 ([#18191](https://github.com/abpframework/abp/issues/18191))
* Deployment Documents Improvements ([#15034](https://github.com/abpframework/abp/issues/15034))
* Improvements on the existing features and provide more guides.
-See the [8.1 milestone](https://github.com/abpframework/abp/milestone/94) for all the issues we've planned to work on.
+See the [8.2 milestone](https://github.com/abpframework/abp/milestone/95) for all the issues we've planned to work on.
## Backlog Items
-The *Next Versions* section above shows the main focus of the planned versions. However, in each release we add new features to the core framework and the [application modules](Modules/Index.md).
+The *Next Versions* section above shows the main focus of the planned versions. However, in each release, we add new features to the core framework and the [application modules](Modules/Index.md).
Here is a list of major items in the backlog we are considering working on in the next versions.
-* [#6655](https://github.com/abpframework/abp/pull/6655) / Use Typescript for the MVC UI
+* [#86](https://github.com/abpframework/abp/issues/86) / GrapQL Integration
* [#236](https://github.com/abpframework/abp/issues/236) / Resource based authorization system
* [#2882](https://github.com/abpframework/abp/issues/2882) / Providing a gRPC integration infrastructure (while it is [already possible](https://github.com/abpframework/abp-samples/tree/master/GrpcDemo) to create or consume gRPC endpoints for your application, we plan to create endpoints for the [standard application modules](https://docs.abp.io/en/abp/latest/Modules/Index))
* [#57](https://github.com/abpframework/abp/issues/57) / Built-in CQRS infrastructure
-* [#2532](https://github.com/abpframework/abp/issues/2532) / CosmosDB integration with EF Core and MongoDB API
* [#4223](https://github.com/abpframework/abp/issues/4223) / WebHook system
* [#162](https://github.com/abpframework/abp/issues/162) / Azure ElasticDB Integration for multitenancy
* [#2296](https://github.com/abpframework/abp/issues/2296) / Feature toggling infrastructure
diff --git a/docs/en/Tutorials/Part-1.md b/docs/en/Tutorials/Part-1.md
index e5a8750f39..96b39066e9 100644
--- a/docs/en/Tutorials/Part-1.md
+++ b/docs/en/Tutorials/Part-1.md
@@ -6,6 +6,16 @@
"DB": ["EF","Mongo"]
}
````
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "The Book List Page",
+ "Path": "Tutorials/Part-2"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -510,8 +520,4 @@ If you try to execute the `[GET] /api/app/book` API to get a list of books, the
}
````
-That's pretty cool since we haven't written a single line of code to create the API controller, but now we have a fully working REST API!
-
-## The Next Part
-
-See the [next part](Part-2.md) of this tutorial.
+That's pretty cool since we haven't written a single line of code to create the API controller, but now we have a fully working REST API!
\ No newline at end of file
diff --git a/docs/en/Tutorials/Part-10.md b/docs/en/Tutorials/Part-10.md
index 601905f522..2c5accb6c0 100644
--- a/docs/en/Tutorials/Part-10.md
+++ b/docs/en/Tutorials/Part-10.md
@@ -6,6 +6,17 @@
"DB": ["EF","Mongo"]
}
````
+
+````json
+//[doc-nav]
+{
+ "Previous": {
+ "Name": "Authors: User Interface",
+ "Path": "Tutorials/Part-9"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
diff --git a/docs/en/Tutorials/Part-2.md b/docs/en/Tutorials/Part-2.md
index d22e4b5062..cbd3e0909c 100644
--- a/docs/en/Tutorials/Part-2.md
+++ b/docs/en/Tutorials/Part-2.md
@@ -6,6 +6,20 @@
"DB": ["EF","Mongo"]
}
````
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Creating, Updating and Deleting Books",
+ "Path": "Tutorials/Part-3"
+ },
+ "Previous": {
+ "Name": "Creating the Server Side",
+ "Path": "Tutorials/Part-1"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -668,7 +682,3 @@ You can run the application! The final UI of this part is shown below:
This is a fully working, server side paged, sorted and localized table of books.
{{end # UI }}
-
-## The Next Part
-
-Check the [next part](Part-3.md) of this tutorial.
diff --git a/docs/en/Tutorials/Part-3.md b/docs/en/Tutorials/Part-3.md
index bb00d71651..2e33d7b35c 100644
--- a/docs/en/Tutorials/Part-3.md
+++ b/docs/en/Tutorials/Part-3.md
@@ -6,6 +6,21 @@
"DB": ["EF","Mongo"]
}
````
+
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Integration Tests",
+ "Path": "Tutorials/Part-4"
+ },
+ "Previous": {
+ "Name": "The Book List Page",
+ "Path": "Tutorials/Part-2"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -1554,6 +1569,3 @@ Here's the complete code to create the book management CRUD page, that has been
{{end}}
-## The Next Part
-
-Check out the [next part](Part-4.md) of this tutorial.
diff --git a/docs/en/Tutorials/Part-4.md b/docs/en/Tutorials/Part-4.md
index 87bc512b5e..4172072c74 100644
--- a/docs/en/Tutorials/Part-4.md
+++ b/docs/en/Tutorials/Part-4.md
@@ -6,6 +6,21 @@
"DB": ["EF","Mongo"]
}
````
+
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Authorization",
+ "Path": "Tutorials/Part-5"
+ },
+ "Previous": {
+ "Name": "Creating, Updating and Deleting Books",
+ "Path": "Tutorials/Part-3"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -282,8 +297,4 @@ Open the **Test Explorer Window** (use Test -> Windows -> Test Explorer menu if

-Congratulations, the **green icons** indicates that the tests have been successfully passed!
-
-## The Next Part
-
-See the [next part](Part-5.md) of this tutorial.
+Congratulations, the **green icons** indicates that the tests have been successfully passed!
\ No newline at end of file
diff --git a/docs/en/Tutorials/Part-5.md b/docs/en/Tutorials/Part-5.md
index f306b7f4a2..aebb4bd8bc 100644
--- a/docs/en/Tutorials/Part-5.md
+++ b/docs/en/Tutorials/Part-5.md
@@ -6,6 +6,21 @@
"DB": ["EF","Mongo"]
}
````
+
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Authors: Domain Layer",
+ "Path": "Tutorials/Part-6"
+ },
+ "Previous": {
+ "Name": "Integration Tests",
+ "Path": "Tutorials/Part-4"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -562,8 +577,4 @@ private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
}
````
-{{end}}
-
-## The Next Part
-
-See the [next part](Part-6.md) of this tutorial.
+{{end}}
\ No newline at end of file
diff --git a/docs/en/Tutorials/Part-6.md b/docs/en/Tutorials/Part-6.md
index 2cb525b4a4..55b9d2689e 100644
--- a/docs/en/Tutorials/Part-6.md
+++ b/docs/en/Tutorials/Part-6.md
@@ -6,6 +6,21 @@
"DB": ["EF","Mongo"]
}
````
+
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Authors: Database Integration",
+ "Path": "Tutorials/Part-7"
+ },
+ "Previous": {
+ "Name": "Authorization",
+ "Path": "Tutorials/Part-5"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -263,8 +278,4 @@ We will implement this repository in the next part.
This part covered the domain layer of the authors functionality of the book store application. The main files created/updated in this part was highlighted in the picture below:
-
-
-## The Next Part
-
-See the [next part](Part-7.md) of this tutorial.
+
\ No newline at end of file
diff --git a/docs/en/Tutorials/Part-7.md b/docs/en/Tutorials/Part-7.md
index 41264789cc..9f0c51b5e9 100644
--- a/docs/en/Tutorials/Part-7.md
+++ b/docs/en/Tutorials/Part-7.md
@@ -6,6 +6,21 @@
"DB": ["EF","Mongo"]
}
````
+
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Authors: Application Layer",
+ "Path": "Tutorials/Part-8"
+ },
+ "Previous": {
+ "Name": "Authors: Domain Layer",
+ "Path": "Tutorials/Part-6"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -226,8 +241,4 @@ public class MongoDbAuthorRepository
> See the [MongoDB Integration document](../MongoDB.md) for more information on the MongoDB based repositories.
-{{end}}
-
-## The Next Part
-
-See the [next part](Part-8.md) of this tutorial.
+{{end}}
\ No newline at end of file
diff --git a/docs/en/Tutorials/Part-8.md b/docs/en/Tutorials/Part-8.md
index a1563f6b2c..5263cbc44e 100644
--- a/docs/en/Tutorials/Part-8.md
+++ b/docs/en/Tutorials/Part-8.md
@@ -6,6 +6,21 @@
"DB": ["EF","Mongo"]
}
````
+
+````json
+//[doc-nav]
+{
+ "Next": {
+ "Name": "Authors: User Interface",
+ "Path": "Tutorials/Part-9"
+ },
+ "Previous": {
+ "Name": "Authors: Database Integration",
+ "Path": "Tutorials/Part-7"
+ }
+}
+````
+
## About This Tutorial
In this tutorial series, you will build an ABP based web application named `Acme.BookStore`. This application is used to manage a list of books and their authors. It is developed using the following technologies:
@@ -589,7 +604,3 @@ public class MongoDBAuthorAppService_Tests : AuthorAppService_Tests **Tip**: If you run the `.DbMigrator` console application after defining a new permission, it automatically grants these new permissions to the admin role and you don't need to manually grant the permissions yourself.
-{{end}}
-
-## The Next Part
-
-See the [next part](Part-10.md) of this tutorial.
+{{end}}
\ No newline at end of file
diff --git a/docs/en/UI/Angular/Authorization.md b/docs/en/UI/Angular/Authorization.md
index 2e4a9af343..5fad925c9d 100644
--- a/docs/en/UI/Angular/Authorization.md
+++ b/docs/en/UI/Angular/Authorization.md
@@ -59,9 +59,9 @@ The `AuthErrorFilterService` is an abstract service that needs to be replaced wi
> By default, this service is replaced in the `@abp/ng.oauth` package
-**Usage**
+### Usage
-1.Create an auth-filter.provider
+#### 1.Create an auth-filter.provider
```js
import { APP_INITIALIZER, inject } from '@angular/core';
@@ -96,12 +96,11 @@ function configureAuthFilter() {
```
- `AuthErrorFilter:` is a model for filter object and it have 3 properties
-
- `id:` a unique key in the list for the filter object
- `executable:` a status for the filter object. If it's false then it won't work, yet it'll stay in the list
- `execute:` a function that stores the skip logic
- 2.Add to the FeatureConfigModule
+#### 2.Add to the FeatureConfigModule
```js
import { ModuleWithProviders, NgModule } from "@angular/core";
@@ -120,11 +119,11 @@ export class CustomersConfigModule {
Now it'll skip the clearing of OAuth storage keys for `LinkedUser` grant_type if any `OAuthErrorEvent` occurs
-**Replace with custom implementation**
+#### Replace with custom implementation
-- Use the `AbstractAuthErrorFilter` class for signs of process.
+Use the `AbstractAuthErrorFilter` class for signs of process.
-**Example**
+#### Example
`my-auth-error-filter.service.ts`
diff --git a/docs/en/UI/Angular/Localization.md b/docs/en/UI/Angular/Localization.md
index f7b0df8ba4..8b53a534e0 100644
--- a/docs/en/UI/Angular/Localization.md
+++ b/docs/en/UI/Angular/Localization.md
@@ -113,7 +113,7 @@ this.localizationService.get({
## UI Localizations
-Localizations can be determined on backend side. Angular UI gets the localizations from the `application-configuration` API's response. You can also determine localizations on the UI side.
+Localizations can be determined on backend side. Angular UI gets the localization resources from the `application-localization` API's response and merges these resources with `configuration state` in [`ConfigStateService`](Config-State-Service.md). You can also determine localizations on the UI side.
See an example:
diff --git a/docs/zh-Hans/API/Auto-API-Controllers.md b/docs/zh-Hans/API/Auto-API-Controllers.md
index c3f5d44d71..e284d05c3d 100644
--- a/docs/zh-Hans/API/Auto-API-Controllers.md
+++ b/docs/zh-Hans/API/Auto-API-Controllers.md
@@ -12,9 +12,9 @@ ABP可以按照惯例 **自动** 将你的应用程序服务配置为API控制
[DependsOn(BookStoreApplicationModule)]
public class BookStoreWebModule : AbpModule
{
- public override void ConfigureServices(ServiceConfigurationContext context)
+ public override void PreConfigureServices(ServiceConfigurationContext context)
{
- Configure(options =>
+ PreConfigure(options =>
{
options
.ConventionalControllers
diff --git a/docs/zh-Hans/MongoDB.md b/docs/zh-Hans/MongoDB.md
index 540793dd1f..1602c61a38 100644
--- a/docs/zh-Hans/MongoDB.md
+++ b/docs/zh-Hans/MongoDB.md
@@ -51,6 +51,34 @@ public class MyDbContext : AbpMongoDbContext
* 为每一个mongo集合添加一个公共的 `IMongoCollection` 属性.ABP默认使用这些属性创建默认的仓储
* 重写 `CreateModel` 方法,可以在方法中配置集合(如设置集合在数据库中的名字)
+### 为集合配置索引和 CreateCollectionOptions
+
+你可以在 `CreateModel` 方法中配置集合的索引和 `CreateCollectionOptions`:
+
+````csharp
+protected override void CreateModel(IMongoModelBuilder modelBuilder)
+{
+ base.CreateModel(modelBuilder);
+
+ modelBuilder.Entity(b =>
+ {
+ b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary);
+ b.ConfigureIndexes(indexes =>
+ {
+ indexes.CreateOne(
+ new CreateIndexModel(
+ Builders.IndexKeys.Ascending("MyProperty"),
+ new CreateIndexOptions { Unique = true }
+ )
+ );
+ }
+ );
+ });
+}
+````
+
+在这个例子中,我们设置了集合的排序规则和一个唯一的索引.
+
### 将 Db Context 注入到依赖注入中
在你的模块中使用 `AddAbpDbContext` 方法将Db Context注入到[依赖注入](Dependency-Injection.md)系统中.
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs
index 1bc7856ca6..dce80a3099 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcRemoteTenantStore.cs
@@ -40,9 +40,9 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
}
var tenantConfiguration = await Cache.GetAsync(cacheKey);
- if (tenantConfiguration == null)
+ if (tenantConfiguration?.Value == null)
{
- await TenantAppService.FindTenantByNameAsync(normalizedName);
+ var tenant = await TenantAppService.FindTenantByNameAsync(normalizedName);
tenantConfiguration = await Cache.GetAsync(cacheKey);
}
@@ -65,7 +65,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
}
var tenantConfiguration = await Cache.GetAsync(cacheKey);
- if (tenantConfiguration == null)
+ if (tenantConfiguration?.Value == null)
{
await TenantAppService.FindTenantByIdAsync(id);
tenantConfiguration = await Cache.GetAsync(cacheKey);
@@ -90,7 +90,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
}
var tenantConfiguration = Cache.Get(cacheKey);
- if (tenantConfiguration == null)
+ if (tenantConfiguration?.Value == null)
{
AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByNameAsync(normalizedName));
tenantConfiguration = Cache.Get(cacheKey);
@@ -115,7 +115,7 @@ public class MvcRemoteTenantStore : ITenantStore, ITransientDependency
}
var tenantConfiguration = Cache.Get(cacheKey);
- if (tenantConfiguration == null)
+ if (tenantConfiguration?.Value == null)
{
AsyncHelper.RunSync(async () => await TenantAppService.FindTenantByIdAsync(id));
tenantConfiguration = Cache.Get(cacheKey);
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs
index 2bbc604c95..7d654c4e80 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ApplicationLocalizationDto.cs
@@ -8,8 +8,11 @@ public class ApplicationLocalizationDto
{
public Dictionary Resources { get; set; }
+ public CurrentCultureDto CurrentCulture { get; set; }
+
public ApplicationLocalizationDto()
{
Resources = new Dictionary();
+ CurrentCulture = new CurrentCultureDto();
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs
index 054e626844..c9184d59b9 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.Contracts/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/CurrentCultureDto.cs
@@ -1,4 +1,5 @@
using System;
+using System.Globalization;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
@@ -22,4 +23,32 @@ public class CurrentCultureDto
public string NativeName { get; set; } = default!;
public DateTimeFormatDto DateTimeFormat { get; set; } = default!;
+
+ ///
+ /// Creates a new object based on the current CultureInfo.
+ ///
+ public static CurrentCultureDto Create()
+ {
+ return new CurrentCultureDto
+ {
+ Name = CultureInfo.CurrentUICulture.Name,
+ DisplayName = CultureInfo.CurrentUICulture.DisplayName,
+ EnglishName = CultureInfo.CurrentUICulture.EnglishName,
+ NativeName = CultureInfo.CurrentUICulture.NativeName,
+ IsRightToLeft = CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft,
+ CultureName = CultureInfo.CurrentUICulture.TextInfo.CultureName,
+ TwoLetterIsoLanguageName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName,
+ ThreeLetterIsoLanguageName = CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName,
+ DateTimeFormat = new DateTimeFormatDto
+ {
+ CalendarAlgorithmType = CultureInfo.CurrentUICulture.DateTimeFormat.Calendar.AlgorithmType.ToString(),
+ DateTimeFormatLong = CultureInfo.CurrentUICulture.DateTimeFormat.LongDatePattern,
+ ShortDatePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern,
+ FullDateTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern,
+ DateSeparator = CultureInfo.CurrentUICulture.DateTimeFormat.DateSeparator,
+ ShortTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortTimePattern,
+ LongTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern,
+ }
+ };
+ }
}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
index 7060597756..b4000d6cbc 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
@@ -258,7 +258,7 @@ var abp = abp || {};
var cells = $(nRow).children("td");
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
- if (cell._DT_CellIndex && cell._DT_CellIndex.row === iDisplayIndex && cell._DT_CellIndex.column === colIndex) {
+ if (cell._DT_CellIndex && cell._DT_CellIndex.column === colIndex) {
var $actionButton = $(cell).find(".abp-action-button");
if ($actionButton.length === 0) {
$(cell).empty().append($actionContainer);
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
index a2f2c1c989..7b68fca32d 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
@@ -215,6 +215,17 @@ public class AbpAspNetCoreMvcModule : AbpModule
context.Services.GetSingletonInstance(),
context.Services.GetSingletonInstance()
);
+
+ var preConfigureActions = context.Services.GetPreConfigureActions();
+
+ DynamicProxyIgnoreTypes.Add(preConfigureActions.Configure()
+ .ConventionalControllers
+ .ConventionalControllerSettings.SelectMany(x => x.ControllerTypes).ToArray());
+
+ Configure(options =>
+ {
+ preConfigureActions.Configure(options);
+ });
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
index e4c95fdcef..38d68aa96c 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
@@ -258,28 +258,7 @@ public class AbpApplicationConfigurationAppService : ApplicationService, IAbpApp
private static CurrentCultureDto GetCurrentCultureInfo()
{
- return new CurrentCultureDto
- {
- Name = CultureInfo.CurrentUICulture.Name,
- DisplayName = CultureInfo.CurrentUICulture.DisplayName,
- EnglishName = CultureInfo.CurrentUICulture.EnglishName,
- NativeName = CultureInfo.CurrentUICulture.NativeName,
- IsRightToLeft = CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft,
- CultureName = CultureInfo.CurrentUICulture.TextInfo.CultureName,
- TwoLetterIsoLanguageName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName,
- ThreeLetterIsoLanguageName = CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName,
- DateTimeFormat = new DateTimeFormatDto
- {
- CalendarAlgorithmType =
- CultureInfo.CurrentUICulture.DateTimeFormat.Calendar.AlgorithmType.ToString(),
- DateTimeFormatLong = CultureInfo.CurrentUICulture.DateTimeFormat.LongDatePattern,
- ShortDatePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern,
- FullDateTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern,
- DateSeparator = CultureInfo.CurrentUICulture.DateTimeFormat.DateSeparator,
- ShortTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortTimePattern,
- LongTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern,
- }
- };
+ return CurrentCultureDto.Create();
}
private async Task GetSettingConfigAsync()
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs
index 5a29f4fcd6..a76691ca06 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationLocalizationAppService.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Localization;
@@ -9,7 +10,7 @@ using Volo.Abp.Localization.External;
namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
-public class AbpApplicationLocalizationAppService :
+public class AbpApplicationLocalizationAppService :
ApplicationService,
IAbpApplicationLocalizationAppService
{
@@ -23,14 +24,14 @@ public class AbpApplicationLocalizationAppService :
ExternalLocalizationStore = externalLocalizationStore;
LocalizationOptions = localizationOptions.Value;
}
-
+
public virtual async Task GetAsync(ApplicationLocalizationRequestDto input)
{
if (!CultureHelper.IsValidCultureCode(input.CultureName))
{
throw new AbpException("The selected culture is not valid! Make sure you enter a valid culture name.");
}
-
+
using (CultureHelper.Use(input.CultureName))
{
var resources = LocalizationOptions
@@ -40,8 +41,10 @@ public class AbpApplicationLocalizationAppService :
await ExternalLocalizationStore.GetResourcesAsync()
).ToArray();
- var localizationConfig = new ApplicationLocalizationDto {
- Resources = new Dictionary(resources.Length)
+ var localizationConfig = new ApplicationLocalizationDto
+ {
+ Resources = new Dictionary(resources.Length),
+ CurrentCulture = CurrentCultureDto.Create()
};
foreach (var resource in resources)
@@ -51,7 +54,7 @@ public class AbpApplicationLocalizationAppService :
if (localizer != null)
{
Dictionary? staticLocalizedStrings = null;
-
+
if (input.OnlyDynamics)
{
staticLocalizedStrings = (await localizer.GetAllStringsAsync(
@@ -60,7 +63,7 @@ public class AbpApplicationLocalizationAppService :
includeDynamicContributors: false
)).ToDictionary(x => x.Name);
}
-
+
var localizedStringsWithDynamics = await localizer.GetAllStringsAsync(
includeParentCultures: true,
includeBaseLocalizers: false,
@@ -93,4 +96,4 @@ public class AbpApplicationLocalizationAppService :
return localizationConfig;
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
index b8885930b9..acdfa29bb0 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
@@ -93,60 +93,63 @@ public class AbpIoSourceCodeStore : ISourceCodeStore, ITransientDependency
version = latestVersion;
}
- var currentCliVersion = await CliVersionService.GetCurrentCliVersionAsync();
- var templateVersion = SemanticVersion.Parse(version);
-
- var outputWarning = false;
- if (!trustUserVersion)
+ if (type == SourceCodeTypes.Template)
{
- if (currentCliVersion.Major != templateVersion.Major || currentCliVersion.Minor != templateVersion.Minor)
- {
- // major and minor version are different
- outputWarning = true;
- }
- else if (currentCliVersion.Major == templateVersion.Major &&
- currentCliVersion.Minor == templateVersion.Minor &&
- currentCliVersion.Patch < templateVersion.Patch)
- {
- // major and minor version are same but patch version is lower
- outputWarning = true;
- }
- else if(currentCliVersion.Major == templateVersion.Major &&
- currentCliVersion.Minor == templateVersion.Minor &&
- currentCliVersion.Patch == templateVersion.Patch &&
- currentCliVersion.IsPrerelease && templateVersion.IsPrerelease)
+ var currentCliVersion = await CliVersionService.GetCurrentCliVersionAsync();
+ var templateVersion = SemanticVersion.Parse(version);
+
+ var outputWarning = false;
+ if (!trustUserVersion)
{
- // major and minor and patch version are same but prerelease version may be lower
- var cliRcVersion = currentCliVersion.ReleaseLabels.LastOrDefault();
- var templateRcVersion = templateVersion.ReleaseLabels.LastOrDefault();
- if (cliRcVersion != null && templateRcVersion != null)
+ if (currentCliVersion.Major != templateVersion.Major || currentCliVersion.Minor != templateVersion.Minor)
+ {
+ // major and minor version are different
+ outputWarning = true;
+ }
+ else if (currentCliVersion.Major == templateVersion.Major &&
+ currentCliVersion.Minor == templateVersion.Minor &&
+ currentCliVersion.Patch < templateVersion.Patch)
+ {
+ // major and minor version are same but patch version is lower
+ outputWarning = true;
+ }
+ else if(currentCliVersion.Major == templateVersion.Major &&
+ currentCliVersion.Minor == templateVersion.Minor &&
+ currentCliVersion.Patch == templateVersion.Patch &&
+ currentCliVersion.IsPrerelease && templateVersion.IsPrerelease)
{
- if (int.TryParse(cliRcVersion, out var cliRcVersionNumber) && int.TryParse(templateRcVersion, out var templateRcVersionNumber))
+ // major and minor and patch version are same but prerelease version may be lower
+ var cliRcVersion = currentCliVersion.ReleaseLabels.LastOrDefault();
+ var templateRcVersion = templateVersion.ReleaseLabels.LastOrDefault();
+ if (cliRcVersion != null && templateRcVersion != null)
{
- if (cliRcVersionNumber < templateRcVersionNumber)
+ if (int.TryParse(cliRcVersion, out var cliRcVersionNumber) && int.TryParse(templateRcVersion, out var templateRcVersionNumber))
{
- outputWarning = true;
+ if (cliRcVersionNumber < templateRcVersionNumber)
+ {
+ outputWarning = true;
+ }
}
}
}
}
- }
- if (outputWarning)
- {
- Logger.LogWarning(userSpecifiedVersion
- ? $"The specified template version ({templateVersion}) is different than the CLI version ({currentCliVersion}). This may cause compatibility issues."
- : $"The latest template version ({templateVersion}) is different than the CLI version ({currentCliVersion}). This may cause compatibility issues.");
- Logger.LogWarning("Please upgrade/downgrade the CLI version to the template version.");
- Logger.LogWarning($"> dotnet tool uninstall -g volo.abp.cli");
- Logger.LogWarning(!templateVersion.IsPrerelease
- ? $"> dotnet tool install -g volo.abp.cli --version \"{templateVersion.Major}.{templateVersion.Minor}.*\""
- : $"> dotnet tool install -g volo.abp.cli --version {templateVersion}");
-
- if (userSpecifiedVersion)
+ if (outputWarning)
{
- Logger.LogWarning($"We have changed the template version as the cli version.");
- Logger.LogWarning($"New version: {version}");
+ Logger.LogWarning(userSpecifiedVersion
+ ? $"The specified template version ({templateVersion}) is different than the CLI version ({currentCliVersion}). This may cause compatibility issues."
+ : $"The latest template version ({templateVersion}) is different than the CLI version ({currentCliVersion}). This may cause compatibility issues.");
+ Logger.LogWarning("Please upgrade/downgrade the CLI version to the template version.");
+ Logger.LogWarning($"> dotnet tool uninstall -g volo.abp.cli");
+ Logger.LogWarning(!templateVersion.IsPrerelease
+ ? $"> dotnet tool install -g volo.abp.cli --version \"{templateVersion.Major}.{templateVersion.Minor}.*\""
+ : $"> dotnet tool install -g volo.abp.cli --version {templateVersion}");
+
+ if (userSpecifiedVersion)
+ {
+ Logger.LogWarning($"We have changed the template version as the cli version.");
+ Logger.LogWarning($"New version: {version}");
+ }
}
}
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 2f7c0e269a..a70f1db649 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
@@ -131,6 +131,14 @@ public abstract class MicroserviceTemplateBase : TemplateInfo
private static void DeleteUnrelatedProjects(ProjectBuildContext context, List steps)
{
+ if (!context.BuildArgs.PublicWebSite)
+ {
+ steps.Add(new RemoveProjectFromSolutionStep("MyCompanyName.MyProjectName.PublicWeb", null, "apps/public-web/src/MyCompanyName.MyProjectName.PublicWeb"));
+ steps.Add(new RemoveFolderStep("/apps/public-web"));
+ steps.Add(new RemoveProjectFromTyeStep("public-web"));
+ steps.Add(new RemoveProjectFromPrometheusStep("public-web"));
+ }
+
//TODO: move common tasks to methods
switch (context.BuildArgs.UiFramework)
{
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs
index a24d888b43..d14f64a55b 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/DynamicProxyIgnoreTypes.cs
@@ -17,10 +17,23 @@ public static class DynamicProxyIgnoreTypes
private static HashSet IgnoredTypes { get; } = new HashSet();
public static void Add()
+ {
+ Add(typeof(T));
+ }
+
+ public static void Add(Type type)
+ {
+ lock (IgnoredTypes)
+ {
+ IgnoredTypes.AddIfNotContains(type);
+ }
+ }
+
+ public static void Add(params Type[] types)
{
lock (IgnoredTypes)
{
- IgnoredTypes.AddIfNotContains(typeof(T));
+ IgnoredTypes.AddIfNotContains(types);
}
}
diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/ProxyHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/ProxyHelper.cs
index 5b4f6c6349..203794a6d9 100644
--- a/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/ProxyHelper.cs
+++ b/framework/src/Volo.Abp.Core/Volo/Abp/DynamicProxy/ProxyHelper.cs
@@ -8,6 +8,14 @@ public static class ProxyHelper
{
private const string ProxyNamespace = "Castle.Proxies";
+ ///
+ /// Checks if given object is a dynamic proxy.
+ ///
+ public static bool IsProxy(object obj)
+ {
+ return obj.GetType().Namespace == ProxyNamespace;
+ }
+
///
/// Returns dynamic proxy target object if this is a proxied object, otherwise returns the given object.
/// It supports Castle Dynamic Proxies.
diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
index 05dd4527fc..b06ba191dd 100644
--- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
+++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
@@ -316,7 +316,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext,
break;
case EntityState.Modified:
ApplyAbpConceptsForModifiedEntity(entry);
- if (entry.Properties.Any(x => x.IsModified && x.Metadata.ValueGenerated == ValueGenerated.Never))
+ if (entry.Properties.Any(x => x.IsModified && (x.Metadata.ValueGenerated == ValueGenerated.Never || x.Metadata.ValueGenerated == ValueGenerated.OnAdd)))
{
if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted)
{
diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs
index 366a933d13..a8653bb54a 100644
--- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs
+++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs
@@ -46,6 +46,15 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc
return _clock.Normalize(d3);
}
+ var dateText = reader.GetString();
+ if (!dateText.IsNullOrWhiteSpace())
+ {
+ if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d4))
+ {
+ return _clock.Normalize(d4);
+ }
+ }
+
throw new JsonException("Can't get datetime from the reader!");
}
diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs
index da5983250d..e8a94892da 100644
--- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs
+++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs
@@ -46,6 +46,15 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient
return _clock.Normalize(d2);
}
+ var dateText = reader.GetString();
+ if (!dateText.IsNullOrWhiteSpace())
+ {
+ if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d3))
+ {
+ return _clock.Normalize(d3);
+ }
+ }
+
return null;
}
diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs
new file mode 100644
index 0000000000..c9340bddca
--- /dev/null
+++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasCreateCollectionOptions.cs
@@ -0,0 +1,9 @@
+using MongoDB.Bson;
+using MongoDB.Driver;
+
+namespace Volo.Abp.MongoDB;
+
+public interface IHasCreateCollectionOptions
+{
+ CreateCollectionOptions CreateCollectionOptions { get; }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs
new file mode 100644
index 0000000000..54c2970b93
--- /dev/null
+++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IHasMongoIndexManagerAction.cs
@@ -0,0 +1,10 @@
+using System;
+using MongoDB.Bson;
+using MongoDB.Driver;
+
+namespace Volo.Abp.MongoDB;
+
+public interface IHasMongoIndexManagerAction
+{
+ Action>? IndexesAction { get; set; }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs
index 673f1f4288..fd781aac20 100644
--- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs
+++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/IMongoEntityModelBuilder.cs
@@ -1,5 +1,7 @@
using System;
+using MongoDB.Bson;
using MongoDB.Bson.Serialization;
+using MongoDB.Driver;
namespace Volo.Abp.MongoDB;
@@ -10,6 +12,10 @@ public interface IMongoEntityModelBuilder
string CollectionName { get; set; }
BsonClassMap BsonMap { get; }
+
+ CreateCollectionOptions CreateCollectionOptions { get; }
+
+ void ConfigureIndexes(Action> action);
}
public interface IMongoEntityModelBuilder
@@ -19,4 +25,8 @@ public interface IMongoEntityModelBuilder
string CollectionName { get; set; }
BsonClassMap BsonMap { get; }
+
+ CreateCollectionOptions CreateCollectionOptions { get; }
+
+ void ConfigureIndexes(Action> action);
}
diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs
index e012e89072..14f46e1df7 100644
--- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs
+++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoEntityModelBuilder.cs
@@ -1,19 +1,28 @@
using MongoDB.Bson.Serialization;
using System;
+using MongoDB.Bson;
+using MongoDB.Driver;
namespace Volo.Abp.MongoDB;
public class MongoEntityModelBuilder :
IMongoEntityModel,
IHasBsonClassMap,
+ IHasCreateCollectionOptions,
+ IHasMongoIndexManagerAction,
IMongoEntityModelBuilder,
IMongoEntityModelBuilder
{
public Type EntityType { get; }
public string CollectionName { get; set; } = default!;
+
+ public Action>? IndexesAction { get; set; }
+
+ public CreateCollectionOptions CreateCollectionOptions { get; }
BsonClassMap IMongoEntityModelBuilder.BsonMap => _bsonClassMap;
+
BsonClassMap IMongoEntityModelBuilder.BsonMap => _bsonClassMap;
private readonly BsonClassMap _bsonClassMap;
@@ -23,10 +32,16 @@ public class MongoEntityModelBuilder :
EntityType = typeof(TEntity);
_bsonClassMap = new BsonClassMap();
_bsonClassMap.ConfigureAbpConventions();
+ CreateCollectionOptions = new CreateCollectionOptions();
}
public BsonClassMap GetMap()
{
return _bsonClassMap;
}
+
+ public void ConfigureIndexes(Action>? indexesAction)
+ {
+ IndexesAction = indexesAction;
+ }
}
diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs
index b7de3043ac..d7ad79f7d0 100644
--- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs
+++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/MongoModelBuilder.cs
@@ -74,7 +74,10 @@ public class MongoModelBuilder : IMongoModelBuilder
baseClasses.AddRange(entityModel.EntityType.GetBaseClasses(includeObject: false));
- CreateCollectionIfNotExists(dbContext, entityModel.CollectionName);
+ var createCollectionOptions = entityModel.As().CreateCollectionOptions;
+ var indexesAction = entityModel.As().IndexesAction;
+ CreateCollectionIfNotExists(dbContext, entityModel.CollectionName, createCollectionOptions);
+ CreateCollectionIndexes(dbContext, entityModel.CollectionName, indexesAction);
}
baseClasses = baseClasses.Distinct().ToList();
@@ -141,7 +144,7 @@ public class MongoModelBuilder : IMongoModelBuilder
typeof(MongoEntityModelBuilder<>).MakeGenericType(entityType)
)!
);
-
+
buildAction?.Invoke(model);
}
@@ -150,14 +153,24 @@ public class MongoModelBuilder : IMongoModelBuilder
return _entityModelBuilders.Values.Cast().ToImmutableList();
}
- protected virtual void CreateCollectionIfNotExists(AbpMongoDbContext dbContext, string collectionName)
+ protected virtual void CreateCollectionIfNotExists(AbpMongoDbContext dbContext, string collectionName, CreateCollectionOptions createCollectionOptions)
{
var filter = new BsonDocument("name", collectionName);
- var options = new ListCollectionNamesOptions { Filter = filter };
+ var options = new ListCollectionsOptions { Filter = filter };
+
+ if (!dbContext.Database.ListCollections(options).Any())
+ {
+ dbContext.Database.CreateCollection(collectionName, createCollectionOptions);
+ }
+ }
- if (!dbContext.Database.ListCollectionNames(options).Any())
+ protected virtual void CreateCollectionIndexes(AbpMongoDbContext dbContext, string collectionName, Action>? indexesAction = null)
+ {
+ var collection = dbContext.Database.GetCollection(collectionName);
+
+ if (collection != null)
{
- dbContext.Database.CreateCollection(collectionName);
+ indexesAction?.Invoke(collection.Indexes);
}
}
}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
index 6051ae6520..3f9c605f64 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
@@ -19,6 +19,7 @@ using Volo.Abp.Localization;
using Volo.Abp.MemoryDb;
using Volo.Abp.Modularity;
using Volo.Abp.TestApp;
+using Volo.Abp.TestApp.Application;
using Volo.Abp.Threading;
using Volo.Abp.Validation.Localization;
using Volo.Abp.VirtualFileSystem;
@@ -44,6 +45,21 @@ public class AbpAspNetCoreMvcTestModule : AbpModule
typeof(AbpAspNetCoreMvcTestModule).Assembly
);
});
+
+ context.Services.PreConfigure(options =>
+ {
+ options.ConventionalControllers.Create(typeof(TestAppModule).Assembly, opts =>
+ {
+ opts.UrlActionNameNormalizer = urlActionNameNormalizerContext =>
+ string.Equals(urlActionNameNormalizerContext.ActionNameInUrl, "phone", StringComparison.OrdinalIgnoreCase)
+ ? "phones"
+ : urlActionNameNormalizerContext.ActionNameInUrl;
+
+ opts.TypePredicate = type => type != typeof(ConventionalAppService);
+ });
+
+ options.ExposeIntegrationServices = true;
+ });
}
public override void ConfigureServices(ServiceConfigurationContext context)
@@ -79,19 +95,6 @@ public class AbpAspNetCoreMvcTestModule : AbpModule
});
});
- Configure(options =>
- {
- options.ConventionalControllers.Create(typeof(TestAppModule).Assembly, opts =>
- {
- opts.UrlActionNameNormalizer = urlActionNameNormalizerContext =>
- string.Equals(urlActionNameNormalizerContext.ActionNameInUrl, "phone", StringComparison.OrdinalIgnoreCase)
- ? "phones"
- : urlActionNameNormalizerContext.ActionNameInUrl;
- });
-
- options.ExposeIntegrationServices = true;
- });
-
Configure(options =>
{
options.FileSets.AddEmbedded();
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ConventionalController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ConventionalController_Tests.cs
new file mode 100644
index 0000000000..41602ff1e8
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ConventionalController_Tests.cs
@@ -0,0 +1,21 @@
+using Shouldly;
+using Volo.Abp.DynamicProxy;
+using Volo.Abp.TestApp.Application;
+using Xunit;
+
+namespace Volo.Abp.AspNetCore.Mvc;
+
+public class ConventionalController_Tests : AspNetCoreMvcTestBase
+{
+ [Fact]
+ public void Conventional_Controller_Should_Disable_DynamicProxy()
+ {
+ // PeopleAppService is a conventional controller
+ var peopleAppService = GetRequiredService();
+ ProxyHelper.IsProxy(peopleAppService).ShouldBeFalse();
+
+ // ConventionalAppService is not a conventional controller
+ var conventionalAppService = GetRequiredService();
+ ProxyHelper.IsProxy(conventionalAppService).ShouldBeTrue();
+ }
+}
diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpDateTimeConverter_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpDateTimeConverter_Tests.cs
new file mode 100644
index 0000000000..7b1a0d81ce
--- /dev/null
+++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpDateTimeConverter_Tests.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Globalization;
+using System.Text.Json;
+using System.Text.Json.Serialization.Metadata;
+using Shouldly;
+using Volo.Abp.Json.SystemTextJson.Modifiers;
+using Volo.Abp.Localization;
+using Xunit;
+
+namespace Volo.Abp.Json;
+
+public class AbpDatetimeToEnum_Tests : AbpJsonSystemTextJsonTestBase
+{
+ [Theory]
+ [InlineData("tr", "14.02.2024")]
+ [InlineData("en-US", "2/14/2024")]
+ [InlineData("en-GB", "14/02/2024")]
+ public void Test_Read(string culture, string datetime)
+ {
+ var options = new JsonSerializerOptions()
+ {
+ TypeInfoResolver = new DefaultJsonTypeInfoResolver()
+ {
+ Modifiers = { new AbpDateTimeConverterModifier().CreateModifyAction(ServiceProvider) }
+ }
+ };
+
+ using(CultureHelper.Use(culture))
+ {
+ var testClass = JsonSerializer.Deserialize($"{{\"DateTime\": \"{datetime}\", \"NullableDateTime\": \"{datetime}\"}}", options);
+ testClass.ShouldNotBeNull();
+ testClass.DateTime.ToString(CultureInfo.CurrentCulture).ShouldStartWith(datetime);
+ testClass.NullableDateTime.ShouldNotBeNull();
+ testClass.NullableDateTime.Value.ToString(CultureInfo.CurrentCulture).ShouldStartWith(datetime);
+ }
+
+ using(CultureHelper.Use(culture))
+ {
+ var testClass = JsonSerializer.Deserialize($"{{\"DateTime\": \"{datetime}\", \"NullableDateTime\": null}}", options);
+ testClass.ShouldNotBeNull();
+ testClass.DateTime.ToString(CultureInfo.CurrentCulture).ShouldStartWith(datetime);
+ testClass.NullableDateTime.ShouldBeNull();
+ }
+ }
+
+ class TestClass
+ {
+ public DateTime DateTime { get; set; }
+
+ public DateTime? NullableDateTime { get; set; }
+ }
+}
diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToBoolean_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToBoolean_Tests.cs
index c46a616db0..e595875c99 100644
--- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToBoolean_Tests.cs
+++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToBoolean_Tests.cs
@@ -3,13 +3,13 @@ using Shouldly;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Xunit;
-namespace Volo.Abp.Json
+namespace Volo.Abp.Json;
+
+public class AbpStringToBoolean_Tests
{
- public class AbpStringToBoolean_Tests
+ [Fact]
+ public void Test_Read()
{
- [Fact]
- public void Test_Read()
- {
var options = new JsonSerializerOptions()
{
Converters =
@@ -27,9 +27,9 @@ namespace Volo.Abp.Json
testClass.Enabled.ShouldBe(true);
}
- [Fact]
- public void Test_Write()
- {
+ [Fact]
+ public void Test_Write()
+ {
var options = new JsonSerializerOptions()
{
Converters =
@@ -46,9 +46,8 @@ namespace Volo.Abp.Json
testClassJson.ShouldBe("{\"Enabled\":true}");
}
- class TestClass
- {
- public bool Enabled { get; set; }
- }
+ class TestClass
+ {
+ public bool Enabled { get; set; }
}
-}
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs
index 8336b4ce7d..8d00afd109 100644
--- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs
+++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpStringToEnum_Tests.cs
@@ -5,69 +5,68 @@ using Shouldly;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Xunit;
-namespace Volo.Abp.Json
+namespace Volo.Abp.Json;
+
+public class AbpStringToEnum_Tests
{
- public class AbpStringToEnum_Tests
+ [Fact]
+ public void Test_Read()
{
- [Fact]
- public void Test_Read()
+ var options = new JsonSerializerOptions()
{
- var options = new JsonSerializerOptions()
+ Converters =
{
- Converters =
- {
- new AbpStringToEnumFactory()
- }
- };
+ new AbpStringToEnumFactory()
+ }
+ };
- var testClass = JsonSerializer.Deserialize("{\"Day\": \"Monday\"}", options);
- testClass.ShouldNotBeNull();
- testClass.Day.ShouldBe(DayOfWeek.Monday);
+ var testClass = JsonSerializer.Deserialize("{\"Day\": \"Monday\"}", options);
+ testClass.ShouldNotBeNull();
+ testClass.Day.ShouldBe(DayOfWeek.Monday);
- testClass = JsonSerializer.Deserialize("{\"Day\": 1}", options);
- testClass.ShouldNotBeNull();
- testClass.Day.ShouldBe(DayOfWeek.Monday);
+ testClass = JsonSerializer.Deserialize("{\"Day\": 1}", options);
+ testClass.ShouldNotBeNull();
+ testClass.Day.ShouldBe(DayOfWeek.Monday);
- var dictionary = JsonSerializer.Deserialize>("{\"Monday\":\"Mo\"}", options);
- dictionary.ShouldNotBeNull();
- dictionary.Keys.ShouldContain(DayOfWeek.Monday);
- dictionary.Values.ShouldContain("Mo");
+ var dictionary = JsonSerializer.Deserialize>("{\"Monday\":\"Mo\"}", options);
+ dictionary.ShouldNotBeNull();
+ dictionary.Keys.ShouldContain(DayOfWeek.Monday);
+ dictionary.Values.ShouldContain("Mo");
- dictionary = JsonSerializer.Deserialize>("{\"1\":\"Mo\"}", options);
- dictionary.ShouldNotBeNull();
- dictionary.Keys.ShouldContain(DayOfWeek.Monday);
- dictionary.Values.ShouldContain("Mo");
- }
+ dictionary = JsonSerializer.Deserialize>("{\"1\":\"Mo\"}", options);
+ dictionary.ShouldNotBeNull();
+ dictionary.Keys.ShouldContain(DayOfWeek.Monday);
+ dictionary.Values.ShouldContain("Mo");
+ }
- [Fact]
- public void Test_Write()
+ [Fact]
+ public void Test_Write()
+ {
+ var options = new JsonSerializerOptions()
{
- var options = new JsonSerializerOptions()
+ Converters =
{
- Converters =
- {
- new AbpStringToEnumFactory()
- }
- };
+ new AbpStringToEnumFactory()
+ }
+ };
- var testClassJson = JsonSerializer.Serialize(new TestClass()
- {
- Day = DayOfWeek.Monday
- });
+ var testClassJson = JsonSerializer.Serialize(new TestClass()
+ {
+ Day = DayOfWeek.Monday
+ });
- testClassJson.ShouldBe("{\"Day\":1}");
+ testClassJson.ShouldBe("{\"Day\":1}");
- testClassJson = JsonSerializer.Serialize(new Dictionary
- {
- {DayOfWeek.Monday, "Mo"}
- }, options);
+ testClassJson = JsonSerializer.Serialize(new Dictionary
+ {
+ {DayOfWeek.Monday, "Mo"}
+ }, options);
- testClassJson.ShouldBe("{\"Monday\":\"Mo\"}");
- }
+ testClassJson.ShouldBe("{\"Monday\":\"Mo\"}");
+ }
- class TestClass
- {
- public DayOfWeek Day { get; set; }
- }
+ class TestClass
+ {
+ public DayOfWeek Day { get; set; }
}
}
diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs
index 7c4bd0441d..0d5122228d 100644
--- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs
+++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs
@@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver.Linq;
using Shouldly;
+using Volo.Abp.Domain.Repositories;
using Volo.Abp.TestApp;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.TestApp.Testing;
@@ -64,4 +65,16 @@ public class Repository_Basic_Tests : Repository_Basic_Tests p.PersonId == person.Id && p.Number == "1234567890").ShouldBeTrue();
}
+
+ [Fact]
+ public async Task Filter_Case_Insensitive()
+ {
+ (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "ISTANBUL").ShouldBeNull();
+ (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull();
+ (await CityRepository.GetMongoQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull();
+
+ (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "douglas").ShouldNotBeNull();
+ (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "DOUGLAS").ShouldNotBeNull();
+ (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "Douglas").ShouldNotBeNull();
+ }
}
diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs
index 9bc2606878..fc1ef00cd4 100644
--- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs
+++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs
@@ -1,4 +1,5 @@
-using MongoDB.Driver;
+using MongoDB.Bson;
+using MongoDB.Driver;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext;
@@ -35,5 +36,10 @@ public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext,
{
b.CollectionName = "MyCities";
});
+
+ modelBuilder.Entity(b =>
+ {
+ b.CreateCollectionOptions.Collation = new Collation(locale:"en_US", strength: CollationStrength.Secondary);
+ });
}
}
diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/ConventionalAppService.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/ConventionalAppService.cs
new file mode 100644
index 0000000000..4d38d8989b
--- /dev/null
+++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/ConventionalAppService.cs
@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Volo.Abp.Application.Services;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Uow;
+
+namespace Volo.Abp.TestApp.Application;
+
+public class ConventionalAppService : IApplicationService, ITransientDependency
+{
+ [Authorize]
+ [UnitOfWork]
+ public virtual Task GetAsync()
+ {
+ return Task.CompletedTask;
+ }
+}
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json
index 3571399fb8..f0875fa504 100644
--- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json
@@ -3,9 +3,8 @@
"name": "asp.net",
"private": true,
"dependencies": {
- "@abp/aspnetcore.mvc.ui.theme.shared": "~8.0.3",
- "@abp/prismjs": "^~7.3.2",
- "@abp/highlight.js": "^~7.3.2"
- },
- "devDependencies": {}
+ "@abp/aspnetcore.mvc.ui.theme.shared": "~8.1.0-rc.1",
+ "@abp/prismjs": "~8.1.0-rc.1",
+ "@abp/highlight.js": "~8.1.0-rc.1"
+ }
}
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css
new file mode 100644
index 0000000000..d9ade752d8
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css
@@ -0,0 +1,4616 @@
+/*!
+ * Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
+ */
+.fa,
+.fas,
+.far,
+.fal,
+.fad,
+.fab {
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ display: inline-block;
+ font-style: normal;
+ font-variant: normal;
+ text-rendering: auto;
+ line-height: 1; }
+
+.fa-lg {
+ font-size: 1.33333em;
+ line-height: 0.75em;
+ vertical-align: -.0667em; }
+
+.fa-xs {
+ font-size: .75em; }
+
+.fa-sm {
+ font-size: .875em; }
+
+.fa-1x {
+ font-size: 1em; }
+
+.fa-2x {
+ font-size: 2em; }
+
+.fa-3x {
+ font-size: 3em; }
+
+.fa-4x {
+ font-size: 4em; }
+
+.fa-5x {
+ font-size: 5em; }
+
+.fa-6x {
+ font-size: 6em; }
+
+.fa-7x {
+ font-size: 7em; }
+
+.fa-8x {
+ font-size: 8em; }
+
+.fa-9x {
+ font-size: 9em; }
+
+.fa-10x {
+ font-size: 10em; }
+
+.fa-fw {
+ text-align: center;
+ width: 1.25em; }
+
+.fa-ul {
+ list-style-type: none;
+ margin-left: 2.5em;
+ padding-left: 0; }
+ .fa-ul > li {
+ position: relative; }
+
+.fa-li {
+ left: -2em;
+ position: absolute;
+ text-align: center;
+ width: 2em;
+ line-height: inherit; }
+
+.fa-border {
+ border: solid 0.08em #eee;
+ border-radius: .1em;
+ padding: .2em .25em .15em; }
+
+.fa-pull-left {
+ float: left; }
+
+.fa-pull-right {
+ float: right; }
+
+.fa.fa-pull-left,
+.fas.fa-pull-left,
+.far.fa-pull-left,
+.fal.fa-pull-left,
+.fab.fa-pull-left {
+ margin-right: .3em; }
+
+.fa.fa-pull-right,
+.fas.fa-pull-right,
+.far.fa-pull-right,
+.fal.fa-pull-right,
+.fab.fa-pull-right {
+ margin-left: .3em; }
+
+.fa-spin {
+ -webkit-animation: fa-spin 2s infinite linear;
+ animation: fa-spin 2s infinite linear; }
+
+.fa-pulse {
+ -webkit-animation: fa-spin 1s infinite steps(8);
+ animation: fa-spin 1s infinite steps(8); }
+
+@-webkit-keyframes fa-spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg); } }
+
+@keyframes fa-spin {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg); }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg); } }
+
+.fa-rotate-90 {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
+ -webkit-transform: rotate(90deg);
+ transform: rotate(90deg); }
+
+.fa-rotate-180 {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
+ -webkit-transform: rotate(180deg);
+ transform: rotate(180deg); }
+
+.fa-rotate-270 {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
+ -webkit-transform: rotate(270deg);
+ transform: rotate(270deg); }
+
+.fa-flip-horizontal {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
+ -webkit-transform: scale(-1, 1);
+ transform: scale(-1, 1); }
+
+.fa-flip-vertical {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
+ -webkit-transform: scale(1, -1);
+ transform: scale(1, -1); }
+
+.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical {
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
+ -webkit-transform: scale(-1, -1);
+ transform: scale(-1, -1); }
+
+:root .fa-rotate-90,
+:root .fa-rotate-180,
+:root .fa-rotate-270,
+:root .fa-flip-horizontal,
+:root .fa-flip-vertical,
+:root .fa-flip-both {
+ -webkit-filter: none;
+ filter: none; }
+
+.fa-stack {
+ display: inline-block;
+ height: 2em;
+ line-height: 2em;
+ position: relative;
+ vertical-align: middle;
+ width: 2.5em; }
+
+.fa-stack-1x,
+.fa-stack-2x {
+ left: 0;
+ position: absolute;
+ text-align: center;
+ width: 100%; }
+
+.fa-stack-1x {
+ line-height: inherit; }
+
+.fa-stack-2x {
+ font-size: 2em; }
+
+.fa-inverse {
+ color: #fff; }
+
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+readers do not read off random characters that represent icons */
+.fa-500px:before {
+ content: "\f26e"; }
+
+.fa-accessible-icon:before {
+ content: "\f368"; }
+
+.fa-accusoft:before {
+ content: "\f369"; }
+
+.fa-acquisitions-incorporated:before {
+ content: "\f6af"; }
+
+.fa-ad:before {
+ content: "\f641"; }
+
+.fa-address-book:before {
+ content: "\f2b9"; }
+
+.fa-address-card:before {
+ content: "\f2bb"; }
+
+.fa-adjust:before {
+ content: "\f042"; }
+
+.fa-adn:before {
+ content: "\f170"; }
+
+.fa-adversal:before {
+ content: "\f36a"; }
+
+.fa-affiliatetheme:before {
+ content: "\f36b"; }
+
+.fa-air-freshener:before {
+ content: "\f5d0"; }
+
+.fa-airbnb:before {
+ content: "\f834"; }
+
+.fa-algolia:before {
+ content: "\f36c"; }
+
+.fa-align-center:before {
+ content: "\f037"; }
+
+.fa-align-justify:before {
+ content: "\f039"; }
+
+.fa-align-left:before {
+ content: "\f036"; }
+
+.fa-align-right:before {
+ content: "\f038"; }
+
+.fa-alipay:before {
+ content: "\f642"; }
+
+.fa-allergies:before {
+ content: "\f461"; }
+
+.fa-amazon:before {
+ content: "\f270"; }
+
+.fa-amazon-pay:before {
+ content: "\f42c"; }
+
+.fa-ambulance:before {
+ content: "\f0f9"; }
+
+.fa-american-sign-language-interpreting:before {
+ content: "\f2a3"; }
+
+.fa-amilia:before {
+ content: "\f36d"; }
+
+.fa-anchor:before {
+ content: "\f13d"; }
+
+.fa-android:before {
+ content: "\f17b"; }
+
+.fa-angellist:before {
+ content: "\f209"; }
+
+.fa-angle-double-down:before {
+ content: "\f103"; }
+
+.fa-angle-double-left:before {
+ content: "\f100"; }
+
+.fa-angle-double-right:before {
+ content: "\f101"; }
+
+.fa-angle-double-up:before {
+ content: "\f102"; }
+
+.fa-angle-down:before {
+ content: "\f107"; }
+
+.fa-angle-left:before {
+ content: "\f104"; }
+
+.fa-angle-right:before {
+ content: "\f105"; }
+
+.fa-angle-up:before {
+ content: "\f106"; }
+
+.fa-angry:before {
+ content: "\f556"; }
+
+.fa-angrycreative:before {
+ content: "\f36e"; }
+
+.fa-angular:before {
+ content: "\f420"; }
+
+.fa-ankh:before {
+ content: "\f644"; }
+
+.fa-app-store:before {
+ content: "\f36f"; }
+
+.fa-app-store-ios:before {
+ content: "\f370"; }
+
+.fa-apper:before {
+ content: "\f371"; }
+
+.fa-apple:before {
+ content: "\f179"; }
+
+.fa-apple-alt:before {
+ content: "\f5d1"; }
+
+.fa-apple-pay:before {
+ content: "\f415"; }
+
+.fa-archive:before {
+ content: "\f187"; }
+
+.fa-archway:before {
+ content: "\f557"; }
+
+.fa-arrow-alt-circle-down:before {
+ content: "\f358"; }
+
+.fa-arrow-alt-circle-left:before {
+ content: "\f359"; }
+
+.fa-arrow-alt-circle-right:before {
+ content: "\f35a"; }
+
+.fa-arrow-alt-circle-up:before {
+ content: "\f35b"; }
+
+.fa-arrow-circle-down:before {
+ content: "\f0ab"; }
+
+.fa-arrow-circle-left:before {
+ content: "\f0a8"; }
+
+.fa-arrow-circle-right:before {
+ content: "\f0a9"; }
+
+.fa-arrow-circle-up:before {
+ content: "\f0aa"; }
+
+.fa-arrow-down:before {
+ content: "\f063"; }
+
+.fa-arrow-left:before {
+ content: "\f060"; }
+
+.fa-arrow-right:before {
+ content: "\f061"; }
+
+.fa-arrow-up:before {
+ content: "\f062"; }
+
+.fa-arrows-alt:before {
+ content: "\f0b2"; }
+
+.fa-arrows-alt-h:before {
+ content: "\f337"; }
+
+.fa-arrows-alt-v:before {
+ content: "\f338"; }
+
+.fa-artstation:before {
+ content: "\f77a"; }
+
+.fa-assistive-listening-systems:before {
+ content: "\f2a2"; }
+
+.fa-asterisk:before {
+ content: "\f069"; }
+
+.fa-asymmetrik:before {
+ content: "\f372"; }
+
+.fa-at:before {
+ content: "\f1fa"; }
+
+.fa-atlas:before {
+ content: "\f558"; }
+
+.fa-atlassian:before {
+ content: "\f77b"; }
+
+.fa-atom:before {
+ content: "\f5d2"; }
+
+.fa-audible:before {
+ content: "\f373"; }
+
+.fa-audio-description:before {
+ content: "\f29e"; }
+
+.fa-autoprefixer:before {
+ content: "\f41c"; }
+
+.fa-avianex:before {
+ content: "\f374"; }
+
+.fa-aviato:before {
+ content: "\f421"; }
+
+.fa-award:before {
+ content: "\f559"; }
+
+.fa-aws:before {
+ content: "\f375"; }
+
+.fa-baby:before {
+ content: "\f77c"; }
+
+.fa-baby-carriage:before {
+ content: "\f77d"; }
+
+.fa-backspace:before {
+ content: "\f55a"; }
+
+.fa-backward:before {
+ content: "\f04a"; }
+
+.fa-bacon:before {
+ content: "\f7e5"; }
+
+.fa-bacteria:before {
+ content: "\e059"; }
+
+.fa-bacterium:before {
+ content: "\e05a"; }
+
+.fa-bahai:before {
+ content: "\f666"; }
+
+.fa-balance-scale:before {
+ content: "\f24e"; }
+
+.fa-balance-scale-left:before {
+ content: "\f515"; }
+
+.fa-balance-scale-right:before {
+ content: "\f516"; }
+
+.fa-ban:before {
+ content: "\f05e"; }
+
+.fa-band-aid:before {
+ content: "\f462"; }
+
+.fa-bandcamp:before {
+ content: "\f2d5"; }
+
+.fa-barcode:before {
+ content: "\f02a"; }
+
+.fa-bars:before {
+ content: "\f0c9"; }
+
+.fa-baseball-ball:before {
+ content: "\f433"; }
+
+.fa-basketball-ball:before {
+ content: "\f434"; }
+
+.fa-bath:before {
+ content: "\f2cd"; }
+
+.fa-battery-empty:before {
+ content: "\f244"; }
+
+.fa-battery-full:before {
+ content: "\f240"; }
+
+.fa-battery-half:before {
+ content: "\f242"; }
+
+.fa-battery-quarter:before {
+ content: "\f243"; }
+
+.fa-battery-three-quarters:before {
+ content: "\f241"; }
+
+.fa-battle-net:before {
+ content: "\f835"; }
+
+.fa-bed:before {
+ content: "\f236"; }
+
+.fa-beer:before {
+ content: "\f0fc"; }
+
+.fa-behance:before {
+ content: "\f1b4"; }
+
+.fa-behance-square:before {
+ content: "\f1b5"; }
+
+.fa-bell:before {
+ content: "\f0f3"; }
+
+.fa-bell-slash:before {
+ content: "\f1f6"; }
+
+.fa-bezier-curve:before {
+ content: "\f55b"; }
+
+.fa-bible:before {
+ content: "\f647"; }
+
+.fa-bicycle:before {
+ content: "\f206"; }
+
+.fa-biking:before {
+ content: "\f84a"; }
+
+.fa-bimobject:before {
+ content: "\f378"; }
+
+.fa-binoculars:before {
+ content: "\f1e5"; }
+
+.fa-biohazard:before {
+ content: "\f780"; }
+
+.fa-birthday-cake:before {
+ content: "\f1fd"; }
+
+.fa-bitbucket:before {
+ content: "\f171"; }
+
+.fa-bitcoin:before {
+ content: "\f379"; }
+
+.fa-bity:before {
+ content: "\f37a"; }
+
+.fa-black-tie:before {
+ content: "\f27e"; }
+
+.fa-blackberry:before {
+ content: "\f37b"; }
+
+.fa-blender:before {
+ content: "\f517"; }
+
+.fa-blender-phone:before {
+ content: "\f6b6"; }
+
+.fa-blind:before {
+ content: "\f29d"; }
+
+.fa-blog:before {
+ content: "\f781"; }
+
+.fa-blogger:before {
+ content: "\f37c"; }
+
+.fa-blogger-b:before {
+ content: "\f37d"; }
+
+.fa-bluetooth:before {
+ content: "\f293"; }
+
+.fa-bluetooth-b:before {
+ content: "\f294"; }
+
+.fa-bold:before {
+ content: "\f032"; }
+
+.fa-bolt:before {
+ content: "\f0e7"; }
+
+.fa-bomb:before {
+ content: "\f1e2"; }
+
+.fa-bone:before {
+ content: "\f5d7"; }
+
+.fa-bong:before {
+ content: "\f55c"; }
+
+.fa-book:before {
+ content: "\f02d"; }
+
+.fa-book-dead:before {
+ content: "\f6b7"; }
+
+.fa-book-medical:before {
+ content: "\f7e6"; }
+
+.fa-book-open:before {
+ content: "\f518"; }
+
+.fa-book-reader:before {
+ content: "\f5da"; }
+
+.fa-bookmark:before {
+ content: "\f02e"; }
+
+.fa-bootstrap:before {
+ content: "\f836"; }
+
+.fa-border-all:before {
+ content: "\f84c"; }
+
+.fa-border-none:before {
+ content: "\f850"; }
+
+.fa-border-style:before {
+ content: "\f853"; }
+
+.fa-bowling-ball:before {
+ content: "\f436"; }
+
+.fa-box:before {
+ content: "\f466"; }
+
+.fa-box-open:before {
+ content: "\f49e"; }
+
+.fa-box-tissue:before {
+ content: "\e05b"; }
+
+.fa-boxes:before {
+ content: "\f468"; }
+
+.fa-braille:before {
+ content: "\f2a1"; }
+
+.fa-brain:before {
+ content: "\f5dc"; }
+
+.fa-bread-slice:before {
+ content: "\f7ec"; }
+
+.fa-briefcase:before {
+ content: "\f0b1"; }
+
+.fa-briefcase-medical:before {
+ content: "\f469"; }
+
+.fa-broadcast-tower:before {
+ content: "\f519"; }
+
+.fa-broom:before {
+ content: "\f51a"; }
+
+.fa-brush:before {
+ content: "\f55d"; }
+
+.fa-btc:before {
+ content: "\f15a"; }
+
+.fa-buffer:before {
+ content: "\f837"; }
+
+.fa-bug:before {
+ content: "\f188"; }
+
+.fa-building:before {
+ content: "\f1ad"; }
+
+.fa-bullhorn:before {
+ content: "\f0a1"; }
+
+.fa-bullseye:before {
+ content: "\f140"; }
+
+.fa-burn:before {
+ content: "\f46a"; }
+
+.fa-buromobelexperte:before {
+ content: "\f37f"; }
+
+.fa-bus:before {
+ content: "\f207"; }
+
+.fa-bus-alt:before {
+ content: "\f55e"; }
+
+.fa-business-time:before {
+ content: "\f64a"; }
+
+.fa-buy-n-large:before {
+ content: "\f8a6"; }
+
+.fa-buysellads:before {
+ content: "\f20d"; }
+
+.fa-calculator:before {
+ content: "\f1ec"; }
+
+.fa-calendar:before {
+ content: "\f133"; }
+
+.fa-calendar-alt:before {
+ content: "\f073"; }
+
+.fa-calendar-check:before {
+ content: "\f274"; }
+
+.fa-calendar-day:before {
+ content: "\f783"; }
+
+.fa-calendar-minus:before {
+ content: "\f272"; }
+
+.fa-calendar-plus:before {
+ content: "\f271"; }
+
+.fa-calendar-times:before {
+ content: "\f273"; }
+
+.fa-calendar-week:before {
+ content: "\f784"; }
+
+.fa-camera:before {
+ content: "\f030"; }
+
+.fa-camera-retro:before {
+ content: "\f083"; }
+
+.fa-campground:before {
+ content: "\f6bb"; }
+
+.fa-canadian-maple-leaf:before {
+ content: "\f785"; }
+
+.fa-candy-cane:before {
+ content: "\f786"; }
+
+.fa-cannabis:before {
+ content: "\f55f"; }
+
+.fa-capsules:before {
+ content: "\f46b"; }
+
+.fa-car:before {
+ content: "\f1b9"; }
+
+.fa-car-alt:before {
+ content: "\f5de"; }
+
+.fa-car-battery:before {
+ content: "\f5df"; }
+
+.fa-car-crash:before {
+ content: "\f5e1"; }
+
+.fa-car-side:before {
+ content: "\f5e4"; }
+
+.fa-caravan:before {
+ content: "\f8ff"; }
+
+.fa-caret-down:before {
+ content: "\f0d7"; }
+
+.fa-caret-left:before {
+ content: "\f0d9"; }
+
+.fa-caret-right:before {
+ content: "\f0da"; }
+
+.fa-caret-square-down:before {
+ content: "\f150"; }
+
+.fa-caret-square-left:before {
+ content: "\f191"; }
+
+.fa-caret-square-right:before {
+ content: "\f152"; }
+
+.fa-caret-square-up:before {
+ content: "\f151"; }
+
+.fa-caret-up:before {
+ content: "\f0d8"; }
+
+.fa-carrot:before {
+ content: "\f787"; }
+
+.fa-cart-arrow-down:before {
+ content: "\f218"; }
+
+.fa-cart-plus:before {
+ content: "\f217"; }
+
+.fa-cash-register:before {
+ content: "\f788"; }
+
+.fa-cat:before {
+ content: "\f6be"; }
+
+.fa-cc-amazon-pay:before {
+ content: "\f42d"; }
+
+.fa-cc-amex:before {
+ content: "\f1f3"; }
+
+.fa-cc-apple-pay:before {
+ content: "\f416"; }
+
+.fa-cc-diners-club:before {
+ content: "\f24c"; }
+
+.fa-cc-discover:before {
+ content: "\f1f2"; }
+
+.fa-cc-jcb:before {
+ content: "\f24b"; }
+
+.fa-cc-mastercard:before {
+ content: "\f1f1"; }
+
+.fa-cc-paypal:before {
+ content: "\f1f4"; }
+
+.fa-cc-stripe:before {
+ content: "\f1f5"; }
+
+.fa-cc-visa:before {
+ content: "\f1f0"; }
+
+.fa-centercode:before {
+ content: "\f380"; }
+
+.fa-centos:before {
+ content: "\f789"; }
+
+.fa-certificate:before {
+ content: "\f0a3"; }
+
+.fa-chair:before {
+ content: "\f6c0"; }
+
+.fa-chalkboard:before {
+ content: "\f51b"; }
+
+.fa-chalkboard-teacher:before {
+ content: "\f51c"; }
+
+.fa-charging-station:before {
+ content: "\f5e7"; }
+
+.fa-chart-area:before {
+ content: "\f1fe"; }
+
+.fa-chart-bar:before {
+ content: "\f080"; }
+
+.fa-chart-line:before {
+ content: "\f201"; }
+
+.fa-chart-pie:before {
+ content: "\f200"; }
+
+.fa-check:before {
+ content: "\f00c"; }
+
+.fa-check-circle:before {
+ content: "\f058"; }
+
+.fa-check-double:before {
+ content: "\f560"; }
+
+.fa-check-square:before {
+ content: "\f14a"; }
+
+.fa-cheese:before {
+ content: "\f7ef"; }
+
+.fa-chess:before {
+ content: "\f439"; }
+
+.fa-chess-bishop:before {
+ content: "\f43a"; }
+
+.fa-chess-board:before {
+ content: "\f43c"; }
+
+.fa-chess-king:before {
+ content: "\f43f"; }
+
+.fa-chess-knight:before {
+ content: "\f441"; }
+
+.fa-chess-pawn:before {
+ content: "\f443"; }
+
+.fa-chess-queen:before {
+ content: "\f445"; }
+
+.fa-chess-rook:before {
+ content: "\f447"; }
+
+.fa-chevron-circle-down:before {
+ content: "\f13a"; }
+
+.fa-chevron-circle-left:before {
+ content: "\f137"; }
+
+.fa-chevron-circle-right:before {
+ content: "\f138"; }
+
+.fa-chevron-circle-up:before {
+ content: "\f139"; }
+
+.fa-chevron-down:before {
+ content: "\f078"; }
+
+.fa-chevron-left:before {
+ content: "\f053"; }
+
+.fa-chevron-right:before {
+ content: "\f054"; }
+
+.fa-chevron-up:before {
+ content: "\f077"; }
+
+.fa-child:before {
+ content: "\f1ae"; }
+
+.fa-chrome:before {
+ content: "\f268"; }
+
+.fa-chromecast:before {
+ content: "\f838"; }
+
+.fa-church:before {
+ content: "\f51d"; }
+
+.fa-circle:before {
+ content: "\f111"; }
+
+.fa-circle-notch:before {
+ content: "\f1ce"; }
+
+.fa-city:before {
+ content: "\f64f"; }
+
+.fa-clinic-medical:before {
+ content: "\f7f2"; }
+
+.fa-clipboard:before {
+ content: "\f328"; }
+
+.fa-clipboard-check:before {
+ content: "\f46c"; }
+
+.fa-clipboard-list:before {
+ content: "\f46d"; }
+
+.fa-clock:before {
+ content: "\f017"; }
+
+.fa-clone:before {
+ content: "\f24d"; }
+
+.fa-closed-captioning:before {
+ content: "\f20a"; }
+
+.fa-cloud:before {
+ content: "\f0c2"; }
+
+.fa-cloud-download-alt:before {
+ content: "\f381"; }
+
+.fa-cloud-meatball:before {
+ content: "\f73b"; }
+
+.fa-cloud-moon:before {
+ content: "\f6c3"; }
+
+.fa-cloud-moon-rain:before {
+ content: "\f73c"; }
+
+.fa-cloud-rain:before {
+ content: "\f73d"; }
+
+.fa-cloud-showers-heavy:before {
+ content: "\f740"; }
+
+.fa-cloud-sun:before {
+ content: "\f6c4"; }
+
+.fa-cloud-sun-rain:before {
+ content: "\f743"; }
+
+.fa-cloud-upload-alt:before {
+ content: "\f382"; }
+
+.fa-cloudflare:before {
+ content: "\e07d"; }
+
+.fa-cloudscale:before {
+ content: "\f383"; }
+
+.fa-cloudsmith:before {
+ content: "\f384"; }
+
+.fa-cloudversify:before {
+ content: "\f385"; }
+
+.fa-cocktail:before {
+ content: "\f561"; }
+
+.fa-code:before {
+ content: "\f121"; }
+
+.fa-code-branch:before {
+ content: "\f126"; }
+
+.fa-codepen:before {
+ content: "\f1cb"; }
+
+.fa-codiepie:before {
+ content: "\f284"; }
+
+.fa-coffee:before {
+ content: "\f0f4"; }
+
+.fa-cog:before {
+ content: "\f013"; }
+
+.fa-cogs:before {
+ content: "\f085"; }
+
+.fa-coins:before {
+ content: "\f51e"; }
+
+.fa-columns:before {
+ content: "\f0db"; }
+
+.fa-comment:before {
+ content: "\f075"; }
+
+.fa-comment-alt:before {
+ content: "\f27a"; }
+
+.fa-comment-dollar:before {
+ content: "\f651"; }
+
+.fa-comment-dots:before {
+ content: "\f4ad"; }
+
+.fa-comment-medical:before {
+ content: "\f7f5"; }
+
+.fa-comment-slash:before {
+ content: "\f4b3"; }
+
+.fa-comments:before {
+ content: "\f086"; }
+
+.fa-comments-dollar:before {
+ content: "\f653"; }
+
+.fa-compact-disc:before {
+ content: "\f51f"; }
+
+.fa-compass:before {
+ content: "\f14e"; }
+
+.fa-compress:before {
+ content: "\f066"; }
+
+.fa-compress-alt:before {
+ content: "\f422"; }
+
+.fa-compress-arrows-alt:before {
+ content: "\f78c"; }
+
+.fa-concierge-bell:before {
+ content: "\f562"; }
+
+.fa-confluence:before {
+ content: "\f78d"; }
+
+.fa-connectdevelop:before {
+ content: "\f20e"; }
+
+.fa-contao:before {
+ content: "\f26d"; }
+
+.fa-cookie:before {
+ content: "\f563"; }
+
+.fa-cookie-bite:before {
+ content: "\f564"; }
+
+.fa-copy:before {
+ content: "\f0c5"; }
+
+.fa-copyright:before {
+ content: "\f1f9"; }
+
+.fa-cotton-bureau:before {
+ content: "\f89e"; }
+
+.fa-couch:before {
+ content: "\f4b8"; }
+
+.fa-cpanel:before {
+ content: "\f388"; }
+
+.fa-creative-commons:before {
+ content: "\f25e"; }
+
+.fa-creative-commons-by:before {
+ content: "\f4e7"; }
+
+.fa-creative-commons-nc:before {
+ content: "\f4e8"; }
+
+.fa-creative-commons-nc-eu:before {
+ content: "\f4e9"; }
+
+.fa-creative-commons-nc-jp:before {
+ content: "\f4ea"; }
+
+.fa-creative-commons-nd:before {
+ content: "\f4eb"; }
+
+.fa-creative-commons-pd:before {
+ content: "\f4ec"; }
+
+.fa-creative-commons-pd-alt:before {
+ content: "\f4ed"; }
+
+.fa-creative-commons-remix:before {
+ content: "\f4ee"; }
+
+.fa-creative-commons-sa:before {
+ content: "\f4ef"; }
+
+.fa-creative-commons-sampling:before {
+ content: "\f4f0"; }
+
+.fa-creative-commons-sampling-plus:before {
+ content: "\f4f1"; }
+
+.fa-creative-commons-share:before {
+ content: "\f4f2"; }
+
+.fa-creative-commons-zero:before {
+ content: "\f4f3"; }
+
+.fa-credit-card:before {
+ content: "\f09d"; }
+
+.fa-critical-role:before {
+ content: "\f6c9"; }
+
+.fa-crop:before {
+ content: "\f125"; }
+
+.fa-crop-alt:before {
+ content: "\f565"; }
+
+.fa-cross:before {
+ content: "\f654"; }
+
+.fa-crosshairs:before {
+ content: "\f05b"; }
+
+.fa-crow:before {
+ content: "\f520"; }
+
+.fa-crown:before {
+ content: "\f521"; }
+
+.fa-crutch:before {
+ content: "\f7f7"; }
+
+.fa-css3:before {
+ content: "\f13c"; }
+
+.fa-css3-alt:before {
+ content: "\f38b"; }
+
+.fa-cube:before {
+ content: "\f1b2"; }
+
+.fa-cubes:before {
+ content: "\f1b3"; }
+
+.fa-cut:before {
+ content: "\f0c4"; }
+
+.fa-cuttlefish:before {
+ content: "\f38c"; }
+
+.fa-d-and-d:before {
+ content: "\f38d"; }
+
+.fa-d-and-d-beyond:before {
+ content: "\f6ca"; }
+
+.fa-dailymotion:before {
+ content: "\e052"; }
+
+.fa-dashcube:before {
+ content: "\f210"; }
+
+.fa-database:before {
+ content: "\f1c0"; }
+
+.fa-deaf:before {
+ content: "\f2a4"; }
+
+.fa-deezer:before {
+ content: "\e077"; }
+
+.fa-delicious:before {
+ content: "\f1a5"; }
+
+.fa-democrat:before {
+ content: "\f747"; }
+
+.fa-deploydog:before {
+ content: "\f38e"; }
+
+.fa-deskpro:before {
+ content: "\f38f"; }
+
+.fa-desktop:before {
+ content: "\f108"; }
+
+.fa-dev:before {
+ content: "\f6cc"; }
+
+.fa-deviantart:before {
+ content: "\f1bd"; }
+
+.fa-dharmachakra:before {
+ content: "\f655"; }
+
+.fa-dhl:before {
+ content: "\f790"; }
+
+.fa-diagnoses:before {
+ content: "\f470"; }
+
+.fa-diaspora:before {
+ content: "\f791"; }
+
+.fa-dice:before {
+ content: "\f522"; }
+
+.fa-dice-d20:before {
+ content: "\f6cf"; }
+
+.fa-dice-d6:before {
+ content: "\f6d1"; }
+
+.fa-dice-five:before {
+ content: "\f523"; }
+
+.fa-dice-four:before {
+ content: "\f524"; }
+
+.fa-dice-one:before {
+ content: "\f525"; }
+
+.fa-dice-six:before {
+ content: "\f526"; }
+
+.fa-dice-three:before {
+ content: "\f527"; }
+
+.fa-dice-two:before {
+ content: "\f528"; }
+
+.fa-digg:before {
+ content: "\f1a6"; }
+
+.fa-digital-ocean:before {
+ content: "\f391"; }
+
+.fa-digital-tachograph:before {
+ content: "\f566"; }
+
+.fa-directions:before {
+ content: "\f5eb"; }
+
+.fa-discord:before {
+ content: "\f392"; }
+
+.fa-discourse:before {
+ content: "\f393"; }
+
+.fa-disease:before {
+ content: "\f7fa"; }
+
+.fa-divide:before {
+ content: "\f529"; }
+
+.fa-dizzy:before {
+ content: "\f567"; }
+
+.fa-dna:before {
+ content: "\f471"; }
+
+.fa-dochub:before {
+ content: "\f394"; }
+
+.fa-docker:before {
+ content: "\f395"; }
+
+.fa-dog:before {
+ content: "\f6d3"; }
+
+.fa-dollar-sign:before {
+ content: "\f155"; }
+
+.fa-dolly:before {
+ content: "\f472"; }
+
+.fa-dolly-flatbed:before {
+ content: "\f474"; }
+
+.fa-donate:before {
+ content: "\f4b9"; }
+
+.fa-door-closed:before {
+ content: "\f52a"; }
+
+.fa-door-open:before {
+ content: "\f52b"; }
+
+.fa-dot-circle:before {
+ content: "\f192"; }
+
+.fa-dove:before {
+ content: "\f4ba"; }
+
+.fa-download:before {
+ content: "\f019"; }
+
+.fa-draft2digital:before {
+ content: "\f396"; }
+
+.fa-drafting-compass:before {
+ content: "\f568"; }
+
+.fa-dragon:before {
+ content: "\f6d5"; }
+
+.fa-draw-polygon:before {
+ content: "\f5ee"; }
+
+.fa-dribbble:before {
+ content: "\f17d"; }
+
+.fa-dribbble-square:before {
+ content: "\f397"; }
+
+.fa-dropbox:before {
+ content: "\f16b"; }
+
+.fa-drum:before {
+ content: "\f569"; }
+
+.fa-drum-steelpan:before {
+ content: "\f56a"; }
+
+.fa-drumstick-bite:before {
+ content: "\f6d7"; }
+
+.fa-drupal:before {
+ content: "\f1a9"; }
+
+.fa-dumbbell:before {
+ content: "\f44b"; }
+
+.fa-dumpster:before {
+ content: "\f793"; }
+
+.fa-dumpster-fire:before {
+ content: "\f794"; }
+
+.fa-dungeon:before {
+ content: "\f6d9"; }
+
+.fa-dyalog:before {
+ content: "\f399"; }
+
+.fa-earlybirds:before {
+ content: "\f39a"; }
+
+.fa-ebay:before {
+ content: "\f4f4"; }
+
+.fa-edge:before {
+ content: "\f282"; }
+
+.fa-edge-legacy:before {
+ content: "\e078"; }
+
+.fa-edit:before {
+ content: "\f044"; }
+
+.fa-egg:before {
+ content: "\f7fb"; }
+
+.fa-eject:before {
+ content: "\f052"; }
+
+.fa-elementor:before {
+ content: "\f430"; }
+
+.fa-ellipsis-h:before {
+ content: "\f141"; }
+
+.fa-ellipsis-v:before {
+ content: "\f142"; }
+
+.fa-ello:before {
+ content: "\f5f1"; }
+
+.fa-ember:before {
+ content: "\f423"; }
+
+.fa-empire:before {
+ content: "\f1d1"; }
+
+.fa-envelope:before {
+ content: "\f0e0"; }
+
+.fa-envelope-open:before {
+ content: "\f2b6"; }
+
+.fa-envelope-open-text:before {
+ content: "\f658"; }
+
+.fa-envelope-square:before {
+ content: "\f199"; }
+
+.fa-envira:before {
+ content: "\f299"; }
+
+.fa-equals:before {
+ content: "\f52c"; }
+
+.fa-eraser:before {
+ content: "\f12d"; }
+
+.fa-erlang:before {
+ content: "\f39d"; }
+
+.fa-ethereum:before {
+ content: "\f42e"; }
+
+.fa-ethernet:before {
+ content: "\f796"; }
+
+.fa-etsy:before {
+ content: "\f2d7"; }
+
+.fa-euro-sign:before {
+ content: "\f153"; }
+
+.fa-evernote:before {
+ content: "\f839"; }
+
+.fa-exchange-alt:before {
+ content: "\f362"; }
+
+.fa-exclamation:before {
+ content: "\f12a"; }
+
+.fa-exclamation-circle:before {
+ content: "\f06a"; }
+
+.fa-exclamation-triangle:before {
+ content: "\f071"; }
+
+.fa-expand:before {
+ content: "\f065"; }
+
+.fa-expand-alt:before {
+ content: "\f424"; }
+
+.fa-expand-arrows-alt:before {
+ content: "\f31e"; }
+
+.fa-expeditedssl:before {
+ content: "\f23e"; }
+
+.fa-external-link-alt:before {
+ content: "\f35d"; }
+
+.fa-external-link-square-alt:before {
+ content: "\f360"; }
+
+.fa-eye:before {
+ content: "\f06e"; }
+
+.fa-eye-dropper:before {
+ content: "\f1fb"; }
+
+.fa-eye-slash:before {
+ content: "\f070"; }
+
+.fa-facebook:before {
+ content: "\f09a"; }
+
+.fa-facebook-f:before {
+ content: "\f39e"; }
+
+.fa-facebook-messenger:before {
+ content: "\f39f"; }
+
+.fa-facebook-square:before {
+ content: "\f082"; }
+
+.fa-fan:before {
+ content: "\f863"; }
+
+.fa-fantasy-flight-games:before {
+ content: "\f6dc"; }
+
+.fa-fast-backward:before {
+ content: "\f049"; }
+
+.fa-fast-forward:before {
+ content: "\f050"; }
+
+.fa-faucet:before {
+ content: "\e005"; }
+
+.fa-fax:before {
+ content: "\f1ac"; }
+
+.fa-feather:before {
+ content: "\f52d"; }
+
+.fa-feather-alt:before {
+ content: "\f56b"; }
+
+.fa-fedex:before {
+ content: "\f797"; }
+
+.fa-fedora:before {
+ content: "\f798"; }
+
+.fa-female:before {
+ content: "\f182"; }
+
+.fa-fighter-jet:before {
+ content: "\f0fb"; }
+
+.fa-figma:before {
+ content: "\f799"; }
+
+.fa-file:before {
+ content: "\f15b"; }
+
+.fa-file-alt:before {
+ content: "\f15c"; }
+
+.fa-file-archive:before {
+ content: "\f1c6"; }
+
+.fa-file-audio:before {
+ content: "\f1c7"; }
+
+.fa-file-code:before {
+ content: "\f1c9"; }
+
+.fa-file-contract:before {
+ content: "\f56c"; }
+
+.fa-file-csv:before {
+ content: "\f6dd"; }
+
+.fa-file-download:before {
+ content: "\f56d"; }
+
+.fa-file-excel:before {
+ content: "\f1c3"; }
+
+.fa-file-export:before {
+ content: "\f56e"; }
+
+.fa-file-image:before {
+ content: "\f1c5"; }
+
+.fa-file-import:before {
+ content: "\f56f"; }
+
+.fa-file-invoice:before {
+ content: "\f570"; }
+
+.fa-file-invoice-dollar:before {
+ content: "\f571"; }
+
+.fa-file-medical:before {
+ content: "\f477"; }
+
+.fa-file-medical-alt:before {
+ content: "\f478"; }
+
+.fa-file-pdf:before {
+ content: "\f1c1"; }
+
+.fa-file-powerpoint:before {
+ content: "\f1c4"; }
+
+.fa-file-prescription:before {
+ content: "\f572"; }
+
+.fa-file-signature:before {
+ content: "\f573"; }
+
+.fa-file-upload:before {
+ content: "\f574"; }
+
+.fa-file-video:before {
+ content: "\f1c8"; }
+
+.fa-file-word:before {
+ content: "\f1c2"; }
+
+.fa-fill:before {
+ content: "\f575"; }
+
+.fa-fill-drip:before {
+ content: "\f576"; }
+
+.fa-film:before {
+ content: "\f008"; }
+
+.fa-filter:before {
+ content: "\f0b0"; }
+
+.fa-fingerprint:before {
+ content: "\f577"; }
+
+.fa-fire:before {
+ content: "\f06d"; }
+
+.fa-fire-alt:before {
+ content: "\f7e4"; }
+
+.fa-fire-extinguisher:before {
+ content: "\f134"; }
+
+.fa-firefox:before {
+ content: "\f269"; }
+
+.fa-firefox-browser:before {
+ content: "\e007"; }
+
+.fa-first-aid:before {
+ content: "\f479"; }
+
+.fa-first-order:before {
+ content: "\f2b0"; }
+
+.fa-first-order-alt:before {
+ content: "\f50a"; }
+
+.fa-firstdraft:before {
+ content: "\f3a1"; }
+
+.fa-fish:before {
+ content: "\f578"; }
+
+.fa-fist-raised:before {
+ content: "\f6de"; }
+
+.fa-flag:before {
+ content: "\f024"; }
+
+.fa-flag-checkered:before {
+ content: "\f11e"; }
+
+.fa-flag-usa:before {
+ content: "\f74d"; }
+
+.fa-flask:before {
+ content: "\f0c3"; }
+
+.fa-flickr:before {
+ content: "\f16e"; }
+
+.fa-flipboard:before {
+ content: "\f44d"; }
+
+.fa-flushed:before {
+ content: "\f579"; }
+
+.fa-fly:before {
+ content: "\f417"; }
+
+.fa-folder:before {
+ content: "\f07b"; }
+
+.fa-folder-minus:before {
+ content: "\f65d"; }
+
+.fa-folder-open:before {
+ content: "\f07c"; }
+
+.fa-folder-plus:before {
+ content: "\f65e"; }
+
+.fa-font:before {
+ content: "\f031"; }
+
+.fa-font-awesome:before {
+ content: "\f2b4"; }
+
+.fa-font-awesome-alt:before {
+ content: "\f35c"; }
+
+.fa-font-awesome-flag:before {
+ content: "\f425"; }
+
+.fa-font-awesome-logo-full:before {
+ content: "\f4e6"; }
+
+.fa-fonticons:before {
+ content: "\f280"; }
+
+.fa-fonticons-fi:before {
+ content: "\f3a2"; }
+
+.fa-football-ball:before {
+ content: "\f44e"; }
+
+.fa-fort-awesome:before {
+ content: "\f286"; }
+
+.fa-fort-awesome-alt:before {
+ content: "\f3a3"; }
+
+.fa-forumbee:before {
+ content: "\f211"; }
+
+.fa-forward:before {
+ content: "\f04e"; }
+
+.fa-foursquare:before {
+ content: "\f180"; }
+
+.fa-free-code-camp:before {
+ content: "\f2c5"; }
+
+.fa-freebsd:before {
+ content: "\f3a4"; }
+
+.fa-frog:before {
+ content: "\f52e"; }
+
+.fa-frown:before {
+ content: "\f119"; }
+
+.fa-frown-open:before {
+ content: "\f57a"; }
+
+.fa-fulcrum:before {
+ content: "\f50b"; }
+
+.fa-funnel-dollar:before {
+ content: "\f662"; }
+
+.fa-futbol:before {
+ content: "\f1e3"; }
+
+.fa-galactic-republic:before {
+ content: "\f50c"; }
+
+.fa-galactic-senate:before {
+ content: "\f50d"; }
+
+.fa-gamepad:before {
+ content: "\f11b"; }
+
+.fa-gas-pump:before {
+ content: "\f52f"; }
+
+.fa-gavel:before {
+ content: "\f0e3"; }
+
+.fa-gem:before {
+ content: "\f3a5"; }
+
+.fa-genderless:before {
+ content: "\f22d"; }
+
+.fa-get-pocket:before {
+ content: "\f265"; }
+
+.fa-gg:before {
+ content: "\f260"; }
+
+.fa-gg-circle:before {
+ content: "\f261"; }
+
+.fa-ghost:before {
+ content: "\f6e2"; }
+
+.fa-gift:before {
+ content: "\f06b"; }
+
+.fa-gifts:before {
+ content: "\f79c"; }
+
+.fa-git:before {
+ content: "\f1d3"; }
+
+.fa-git-alt:before {
+ content: "\f841"; }
+
+.fa-git-square:before {
+ content: "\f1d2"; }
+
+.fa-github:before {
+ content: "\f09b"; }
+
+.fa-github-alt:before {
+ content: "\f113"; }
+
+.fa-github-square:before {
+ content: "\f092"; }
+
+.fa-gitkraken:before {
+ content: "\f3a6"; }
+
+.fa-gitlab:before {
+ content: "\f296"; }
+
+.fa-gitter:before {
+ content: "\f426"; }
+
+.fa-glass-cheers:before {
+ content: "\f79f"; }
+
+.fa-glass-martini:before {
+ content: "\f000"; }
+
+.fa-glass-martini-alt:before {
+ content: "\f57b"; }
+
+.fa-glass-whiskey:before {
+ content: "\f7a0"; }
+
+.fa-glasses:before {
+ content: "\f530"; }
+
+.fa-glide:before {
+ content: "\f2a5"; }
+
+.fa-glide-g:before {
+ content: "\f2a6"; }
+
+.fa-globe:before {
+ content: "\f0ac"; }
+
+.fa-globe-africa:before {
+ content: "\f57c"; }
+
+.fa-globe-americas:before {
+ content: "\f57d"; }
+
+.fa-globe-asia:before {
+ content: "\f57e"; }
+
+.fa-globe-europe:before {
+ content: "\f7a2"; }
+
+.fa-gofore:before {
+ content: "\f3a7"; }
+
+.fa-golf-ball:before {
+ content: "\f450"; }
+
+.fa-goodreads:before {
+ content: "\f3a8"; }
+
+.fa-goodreads-g:before {
+ content: "\f3a9"; }
+
+.fa-google:before {
+ content: "\f1a0"; }
+
+.fa-google-drive:before {
+ content: "\f3aa"; }
+
+.fa-google-pay:before {
+ content: "\e079"; }
+
+.fa-google-play:before {
+ content: "\f3ab"; }
+
+.fa-google-plus:before {
+ content: "\f2b3"; }
+
+.fa-google-plus-g:before {
+ content: "\f0d5"; }
+
+.fa-google-plus-square:before {
+ content: "\f0d4"; }
+
+.fa-google-wallet:before {
+ content: "\f1ee"; }
+
+.fa-gopuram:before {
+ content: "\f664"; }
+
+.fa-graduation-cap:before {
+ content: "\f19d"; }
+
+.fa-gratipay:before {
+ content: "\f184"; }
+
+.fa-grav:before {
+ content: "\f2d6"; }
+
+.fa-greater-than:before {
+ content: "\f531"; }
+
+.fa-greater-than-equal:before {
+ content: "\f532"; }
+
+.fa-grimace:before {
+ content: "\f57f"; }
+
+.fa-grin:before {
+ content: "\f580"; }
+
+.fa-grin-alt:before {
+ content: "\f581"; }
+
+.fa-grin-beam:before {
+ content: "\f582"; }
+
+.fa-grin-beam-sweat:before {
+ content: "\f583"; }
+
+.fa-grin-hearts:before {
+ content: "\f584"; }
+
+.fa-grin-squint:before {
+ content: "\f585"; }
+
+.fa-grin-squint-tears:before {
+ content: "\f586"; }
+
+.fa-grin-stars:before {
+ content: "\f587"; }
+
+.fa-grin-tears:before {
+ content: "\f588"; }
+
+.fa-grin-tongue:before {
+ content: "\f589"; }
+
+.fa-grin-tongue-squint:before {
+ content: "\f58a"; }
+
+.fa-grin-tongue-wink:before {
+ content: "\f58b"; }
+
+.fa-grin-wink:before {
+ content: "\f58c"; }
+
+.fa-grip-horizontal:before {
+ content: "\f58d"; }
+
+.fa-grip-lines:before {
+ content: "\f7a4"; }
+
+.fa-grip-lines-vertical:before {
+ content: "\f7a5"; }
+
+.fa-grip-vertical:before {
+ content: "\f58e"; }
+
+.fa-gripfire:before {
+ content: "\f3ac"; }
+
+.fa-grunt:before {
+ content: "\f3ad"; }
+
+.fa-guilded:before {
+ content: "\e07e"; }
+
+.fa-guitar:before {
+ content: "\f7a6"; }
+
+.fa-gulp:before {
+ content: "\f3ae"; }
+
+.fa-h-square:before {
+ content: "\f0fd"; }
+
+.fa-hacker-news:before {
+ content: "\f1d4"; }
+
+.fa-hacker-news-square:before {
+ content: "\f3af"; }
+
+.fa-hackerrank:before {
+ content: "\f5f7"; }
+
+.fa-hamburger:before {
+ content: "\f805"; }
+
+.fa-hammer:before {
+ content: "\f6e3"; }
+
+.fa-hamsa:before {
+ content: "\f665"; }
+
+.fa-hand-holding:before {
+ content: "\f4bd"; }
+
+.fa-hand-holding-heart:before {
+ content: "\f4be"; }
+
+.fa-hand-holding-medical:before {
+ content: "\e05c"; }
+
+.fa-hand-holding-usd:before {
+ content: "\f4c0"; }
+
+.fa-hand-holding-water:before {
+ content: "\f4c1"; }
+
+.fa-hand-lizard:before {
+ content: "\f258"; }
+
+.fa-hand-middle-finger:before {
+ content: "\f806"; }
+
+.fa-hand-paper:before {
+ content: "\f256"; }
+
+.fa-hand-peace:before {
+ content: "\f25b"; }
+
+.fa-hand-point-down:before {
+ content: "\f0a7"; }
+
+.fa-hand-point-left:before {
+ content: "\f0a5"; }
+
+.fa-hand-point-right:before {
+ content: "\f0a4"; }
+
+.fa-hand-point-up:before {
+ content: "\f0a6"; }
+
+.fa-hand-pointer:before {
+ content: "\f25a"; }
+
+.fa-hand-rock:before {
+ content: "\f255"; }
+
+.fa-hand-scissors:before {
+ content: "\f257"; }
+
+.fa-hand-sparkles:before {
+ content: "\e05d"; }
+
+.fa-hand-spock:before {
+ content: "\f259"; }
+
+.fa-hands:before {
+ content: "\f4c2"; }
+
+.fa-hands-helping:before {
+ content: "\f4c4"; }
+
+.fa-hands-wash:before {
+ content: "\e05e"; }
+
+.fa-handshake:before {
+ content: "\f2b5"; }
+
+.fa-handshake-alt-slash:before {
+ content: "\e05f"; }
+
+.fa-handshake-slash:before {
+ content: "\e060"; }
+
+.fa-hanukiah:before {
+ content: "\f6e6"; }
+
+.fa-hard-hat:before {
+ content: "\f807"; }
+
+.fa-hashtag:before {
+ content: "\f292"; }
+
+.fa-hat-cowboy:before {
+ content: "\f8c0"; }
+
+.fa-hat-cowboy-side:before {
+ content: "\f8c1"; }
+
+.fa-hat-wizard:before {
+ content: "\f6e8"; }
+
+.fa-hdd:before {
+ content: "\f0a0"; }
+
+.fa-head-side-cough:before {
+ content: "\e061"; }
+
+.fa-head-side-cough-slash:before {
+ content: "\e062"; }
+
+.fa-head-side-mask:before {
+ content: "\e063"; }
+
+.fa-head-side-virus:before {
+ content: "\e064"; }
+
+.fa-heading:before {
+ content: "\f1dc"; }
+
+.fa-headphones:before {
+ content: "\f025"; }
+
+.fa-headphones-alt:before {
+ content: "\f58f"; }
+
+.fa-headset:before {
+ content: "\f590"; }
+
+.fa-heart:before {
+ content: "\f004"; }
+
+.fa-heart-broken:before {
+ content: "\f7a9"; }
+
+.fa-heartbeat:before {
+ content: "\f21e"; }
+
+.fa-helicopter:before {
+ content: "\f533"; }
+
+.fa-highlighter:before {
+ content: "\f591"; }
+
+.fa-hiking:before {
+ content: "\f6ec"; }
+
+.fa-hippo:before {
+ content: "\f6ed"; }
+
+.fa-hips:before {
+ content: "\f452"; }
+
+.fa-hire-a-helper:before {
+ content: "\f3b0"; }
+
+.fa-history:before {
+ content: "\f1da"; }
+
+.fa-hive:before {
+ content: "\e07f"; }
+
+.fa-hockey-puck:before {
+ content: "\f453"; }
+
+.fa-holly-berry:before {
+ content: "\f7aa"; }
+
+.fa-home:before {
+ content: "\f015"; }
+
+.fa-hooli:before {
+ content: "\f427"; }
+
+.fa-hornbill:before {
+ content: "\f592"; }
+
+.fa-horse:before {
+ content: "\f6f0"; }
+
+.fa-horse-head:before {
+ content: "\f7ab"; }
+
+.fa-hospital:before {
+ content: "\f0f8"; }
+
+.fa-hospital-alt:before {
+ content: "\f47d"; }
+
+.fa-hospital-symbol:before {
+ content: "\f47e"; }
+
+.fa-hospital-user:before {
+ content: "\f80d"; }
+
+.fa-hot-tub:before {
+ content: "\f593"; }
+
+.fa-hotdog:before {
+ content: "\f80f"; }
+
+.fa-hotel:before {
+ content: "\f594"; }
+
+.fa-hotjar:before {
+ content: "\f3b1"; }
+
+.fa-hourglass:before {
+ content: "\f254"; }
+
+.fa-hourglass-end:before {
+ content: "\f253"; }
+
+.fa-hourglass-half:before {
+ content: "\f252"; }
+
+.fa-hourglass-start:before {
+ content: "\f251"; }
+
+.fa-house-damage:before {
+ content: "\f6f1"; }
+
+.fa-house-user:before {
+ content: "\e065"; }
+
+.fa-houzz:before {
+ content: "\f27c"; }
+
+.fa-hryvnia:before {
+ content: "\f6f2"; }
+
+.fa-html5:before {
+ content: "\f13b"; }
+
+.fa-hubspot:before {
+ content: "\f3b2"; }
+
+.fa-i-cursor:before {
+ content: "\f246"; }
+
+.fa-ice-cream:before {
+ content: "\f810"; }
+
+.fa-icicles:before {
+ content: "\f7ad"; }
+
+.fa-icons:before {
+ content: "\f86d"; }
+
+.fa-id-badge:before {
+ content: "\f2c1"; }
+
+.fa-id-card:before {
+ content: "\f2c2"; }
+
+.fa-id-card-alt:before {
+ content: "\f47f"; }
+
+.fa-ideal:before {
+ content: "\e013"; }
+
+.fa-igloo:before {
+ content: "\f7ae"; }
+
+.fa-image:before {
+ content: "\f03e"; }
+
+.fa-images:before {
+ content: "\f302"; }
+
+.fa-imdb:before {
+ content: "\f2d8"; }
+
+.fa-inbox:before {
+ content: "\f01c"; }
+
+.fa-indent:before {
+ content: "\f03c"; }
+
+.fa-industry:before {
+ content: "\f275"; }
+
+.fa-infinity:before {
+ content: "\f534"; }
+
+.fa-info:before {
+ content: "\f129"; }
+
+.fa-info-circle:before {
+ content: "\f05a"; }
+
+.fa-innosoft:before {
+ content: "\e080"; }
+
+.fa-instagram:before {
+ content: "\f16d"; }
+
+.fa-instagram-square:before {
+ content: "\e055"; }
+
+.fa-instalod:before {
+ content: "\e081"; }
+
+.fa-intercom:before {
+ content: "\f7af"; }
+
+.fa-internet-explorer:before {
+ content: "\f26b"; }
+
+.fa-invision:before {
+ content: "\f7b0"; }
+
+.fa-ioxhost:before {
+ content: "\f208"; }
+
+.fa-italic:before {
+ content: "\f033"; }
+
+.fa-itch-io:before {
+ content: "\f83a"; }
+
+.fa-itunes:before {
+ content: "\f3b4"; }
+
+.fa-itunes-note:before {
+ content: "\f3b5"; }
+
+.fa-java:before {
+ content: "\f4e4"; }
+
+.fa-jedi:before {
+ content: "\f669"; }
+
+.fa-jedi-order:before {
+ content: "\f50e"; }
+
+.fa-jenkins:before {
+ content: "\f3b6"; }
+
+.fa-jira:before {
+ content: "\f7b1"; }
+
+.fa-joget:before {
+ content: "\f3b7"; }
+
+.fa-joint:before {
+ content: "\f595"; }
+
+.fa-joomla:before {
+ content: "\f1aa"; }
+
+.fa-journal-whills:before {
+ content: "\f66a"; }
+
+.fa-js:before {
+ content: "\f3b8"; }
+
+.fa-js-square:before {
+ content: "\f3b9"; }
+
+.fa-jsfiddle:before {
+ content: "\f1cc"; }
+
+.fa-kaaba:before {
+ content: "\f66b"; }
+
+.fa-kaggle:before {
+ content: "\f5fa"; }
+
+.fa-key:before {
+ content: "\f084"; }
+
+.fa-keybase:before {
+ content: "\f4f5"; }
+
+.fa-keyboard:before {
+ content: "\f11c"; }
+
+.fa-keycdn:before {
+ content: "\f3ba"; }
+
+.fa-khanda:before {
+ content: "\f66d"; }
+
+.fa-kickstarter:before {
+ content: "\f3bb"; }
+
+.fa-kickstarter-k:before {
+ content: "\f3bc"; }
+
+.fa-kiss:before {
+ content: "\f596"; }
+
+.fa-kiss-beam:before {
+ content: "\f597"; }
+
+.fa-kiss-wink-heart:before {
+ content: "\f598"; }
+
+.fa-kiwi-bird:before {
+ content: "\f535"; }
+
+.fa-korvue:before {
+ content: "\f42f"; }
+
+.fa-landmark:before {
+ content: "\f66f"; }
+
+.fa-language:before {
+ content: "\f1ab"; }
+
+.fa-laptop:before {
+ content: "\f109"; }
+
+.fa-laptop-code:before {
+ content: "\f5fc"; }
+
+.fa-laptop-house:before {
+ content: "\e066"; }
+
+.fa-laptop-medical:before {
+ content: "\f812"; }
+
+.fa-laravel:before {
+ content: "\f3bd"; }
+
+.fa-lastfm:before {
+ content: "\f202"; }
+
+.fa-lastfm-square:before {
+ content: "\f203"; }
+
+.fa-laugh:before {
+ content: "\f599"; }
+
+.fa-laugh-beam:before {
+ content: "\f59a"; }
+
+.fa-laugh-squint:before {
+ content: "\f59b"; }
+
+.fa-laugh-wink:before {
+ content: "\f59c"; }
+
+.fa-layer-group:before {
+ content: "\f5fd"; }
+
+.fa-leaf:before {
+ content: "\f06c"; }
+
+.fa-leanpub:before {
+ content: "\f212"; }
+
+.fa-lemon:before {
+ content: "\f094"; }
+
+.fa-less:before {
+ content: "\f41d"; }
+
+.fa-less-than:before {
+ content: "\f536"; }
+
+.fa-less-than-equal:before {
+ content: "\f537"; }
+
+.fa-level-down-alt:before {
+ content: "\f3be"; }
+
+.fa-level-up-alt:before {
+ content: "\f3bf"; }
+
+.fa-life-ring:before {
+ content: "\f1cd"; }
+
+.fa-lightbulb:before {
+ content: "\f0eb"; }
+
+.fa-line:before {
+ content: "\f3c0"; }
+
+.fa-link:before {
+ content: "\f0c1"; }
+
+.fa-linkedin:before {
+ content: "\f08c"; }
+
+.fa-linkedin-in:before {
+ content: "\f0e1"; }
+
+.fa-linode:before {
+ content: "\f2b8"; }
+
+.fa-linux:before {
+ content: "\f17c"; }
+
+.fa-lira-sign:before {
+ content: "\f195"; }
+
+.fa-list:before {
+ content: "\f03a"; }
+
+.fa-list-alt:before {
+ content: "\f022"; }
+
+.fa-list-ol:before {
+ content: "\f0cb"; }
+
+.fa-list-ul:before {
+ content: "\f0ca"; }
+
+.fa-location-arrow:before {
+ content: "\f124"; }
+
+.fa-lock:before {
+ content: "\f023"; }
+
+.fa-lock-open:before {
+ content: "\f3c1"; }
+
+.fa-long-arrow-alt-down:before {
+ content: "\f309"; }
+
+.fa-long-arrow-alt-left:before {
+ content: "\f30a"; }
+
+.fa-long-arrow-alt-right:before {
+ content: "\f30b"; }
+
+.fa-long-arrow-alt-up:before {
+ content: "\f30c"; }
+
+.fa-low-vision:before {
+ content: "\f2a8"; }
+
+.fa-luggage-cart:before {
+ content: "\f59d"; }
+
+.fa-lungs:before {
+ content: "\f604"; }
+
+.fa-lungs-virus:before {
+ content: "\e067"; }
+
+.fa-lyft:before {
+ content: "\f3c3"; }
+
+.fa-magento:before {
+ content: "\f3c4"; }
+
+.fa-magic:before {
+ content: "\f0d0"; }
+
+.fa-magnet:before {
+ content: "\f076"; }
+
+.fa-mail-bulk:before {
+ content: "\f674"; }
+
+.fa-mailchimp:before {
+ content: "\f59e"; }
+
+.fa-male:before {
+ content: "\f183"; }
+
+.fa-mandalorian:before {
+ content: "\f50f"; }
+
+.fa-map:before {
+ content: "\f279"; }
+
+.fa-map-marked:before {
+ content: "\f59f"; }
+
+.fa-map-marked-alt:before {
+ content: "\f5a0"; }
+
+.fa-map-marker:before {
+ content: "\f041"; }
+
+.fa-map-marker-alt:before {
+ content: "\f3c5"; }
+
+.fa-map-pin:before {
+ content: "\f276"; }
+
+.fa-map-signs:before {
+ content: "\f277"; }
+
+.fa-markdown:before {
+ content: "\f60f"; }
+
+.fa-marker:before {
+ content: "\f5a1"; }
+
+.fa-mars:before {
+ content: "\f222"; }
+
+.fa-mars-double:before {
+ content: "\f227"; }
+
+.fa-mars-stroke:before {
+ content: "\f229"; }
+
+.fa-mars-stroke-h:before {
+ content: "\f22b"; }
+
+.fa-mars-stroke-v:before {
+ content: "\f22a"; }
+
+.fa-mask:before {
+ content: "\f6fa"; }
+
+.fa-mastodon:before {
+ content: "\f4f6"; }
+
+.fa-maxcdn:before {
+ content: "\f136"; }
+
+.fa-mdb:before {
+ content: "\f8ca"; }
+
+.fa-medal:before {
+ content: "\f5a2"; }
+
+.fa-medapps:before {
+ content: "\f3c6"; }
+
+.fa-medium:before {
+ content: "\f23a"; }
+
+.fa-medium-m:before {
+ content: "\f3c7"; }
+
+.fa-medkit:before {
+ content: "\f0fa"; }
+
+.fa-medrt:before {
+ content: "\f3c8"; }
+
+.fa-meetup:before {
+ content: "\f2e0"; }
+
+.fa-megaport:before {
+ content: "\f5a3"; }
+
+.fa-meh:before {
+ content: "\f11a"; }
+
+.fa-meh-blank:before {
+ content: "\f5a4"; }
+
+.fa-meh-rolling-eyes:before {
+ content: "\f5a5"; }
+
+.fa-memory:before {
+ content: "\f538"; }
+
+.fa-mendeley:before {
+ content: "\f7b3"; }
+
+.fa-menorah:before {
+ content: "\f676"; }
+
+.fa-mercury:before {
+ content: "\f223"; }
+
+.fa-meteor:before {
+ content: "\f753"; }
+
+.fa-microblog:before {
+ content: "\e01a"; }
+
+.fa-microchip:before {
+ content: "\f2db"; }
+
+.fa-microphone:before {
+ content: "\f130"; }
+
+.fa-microphone-alt:before {
+ content: "\f3c9"; }
+
+.fa-microphone-alt-slash:before {
+ content: "\f539"; }
+
+.fa-microphone-slash:before {
+ content: "\f131"; }
+
+.fa-microscope:before {
+ content: "\f610"; }
+
+.fa-microsoft:before {
+ content: "\f3ca"; }
+
+.fa-minus:before {
+ content: "\f068"; }
+
+.fa-minus-circle:before {
+ content: "\f056"; }
+
+.fa-minus-square:before {
+ content: "\f146"; }
+
+.fa-mitten:before {
+ content: "\f7b5"; }
+
+.fa-mix:before {
+ content: "\f3cb"; }
+
+.fa-mixcloud:before {
+ content: "\f289"; }
+
+.fa-mixer:before {
+ content: "\e056"; }
+
+.fa-mizuni:before {
+ content: "\f3cc"; }
+
+.fa-mobile:before {
+ content: "\f10b"; }
+
+.fa-mobile-alt:before {
+ content: "\f3cd"; }
+
+.fa-modx:before {
+ content: "\f285"; }
+
+.fa-monero:before {
+ content: "\f3d0"; }
+
+.fa-money-bill:before {
+ content: "\f0d6"; }
+
+.fa-money-bill-alt:before {
+ content: "\f3d1"; }
+
+.fa-money-bill-wave:before {
+ content: "\f53a"; }
+
+.fa-money-bill-wave-alt:before {
+ content: "\f53b"; }
+
+.fa-money-check:before {
+ content: "\f53c"; }
+
+.fa-money-check-alt:before {
+ content: "\f53d"; }
+
+.fa-monument:before {
+ content: "\f5a6"; }
+
+.fa-moon:before {
+ content: "\f186"; }
+
+.fa-mortar-pestle:before {
+ content: "\f5a7"; }
+
+.fa-mosque:before {
+ content: "\f678"; }
+
+.fa-motorcycle:before {
+ content: "\f21c"; }
+
+.fa-mountain:before {
+ content: "\f6fc"; }
+
+.fa-mouse:before {
+ content: "\f8cc"; }
+
+.fa-mouse-pointer:before {
+ content: "\f245"; }
+
+.fa-mug-hot:before {
+ content: "\f7b6"; }
+
+.fa-music:before {
+ content: "\f001"; }
+
+.fa-napster:before {
+ content: "\f3d2"; }
+
+.fa-neos:before {
+ content: "\f612"; }
+
+.fa-network-wired:before {
+ content: "\f6ff"; }
+
+.fa-neuter:before {
+ content: "\f22c"; }
+
+.fa-newspaper:before {
+ content: "\f1ea"; }
+
+.fa-nimblr:before {
+ content: "\f5a8"; }
+
+.fa-node:before {
+ content: "\f419"; }
+
+.fa-node-js:before {
+ content: "\f3d3"; }
+
+.fa-not-equal:before {
+ content: "\f53e"; }
+
+.fa-notes-medical:before {
+ content: "\f481"; }
+
+.fa-npm:before {
+ content: "\f3d4"; }
+
+.fa-ns8:before {
+ content: "\f3d5"; }
+
+.fa-nutritionix:before {
+ content: "\f3d6"; }
+
+.fa-object-group:before {
+ content: "\f247"; }
+
+.fa-object-ungroup:before {
+ content: "\f248"; }
+
+.fa-octopus-deploy:before {
+ content: "\e082"; }
+
+.fa-odnoklassniki:before {
+ content: "\f263"; }
+
+.fa-odnoklassniki-square:before {
+ content: "\f264"; }
+
+.fa-oil-can:before {
+ content: "\f613"; }
+
+.fa-old-republic:before {
+ content: "\f510"; }
+
+.fa-om:before {
+ content: "\f679"; }
+
+.fa-opencart:before {
+ content: "\f23d"; }
+
+.fa-openid:before {
+ content: "\f19b"; }
+
+.fa-opera:before {
+ content: "\f26a"; }
+
+.fa-optin-monster:before {
+ content: "\f23c"; }
+
+.fa-orcid:before {
+ content: "\f8d2"; }
+
+.fa-osi:before {
+ content: "\f41a"; }
+
+.fa-otter:before {
+ content: "\f700"; }
+
+.fa-outdent:before {
+ content: "\f03b"; }
+
+.fa-page4:before {
+ content: "\f3d7"; }
+
+.fa-pagelines:before {
+ content: "\f18c"; }
+
+.fa-pager:before {
+ content: "\f815"; }
+
+.fa-paint-brush:before {
+ content: "\f1fc"; }
+
+.fa-paint-roller:before {
+ content: "\f5aa"; }
+
+.fa-palette:before {
+ content: "\f53f"; }
+
+.fa-palfed:before {
+ content: "\f3d8"; }
+
+.fa-pallet:before {
+ content: "\f482"; }
+
+.fa-paper-plane:before {
+ content: "\f1d8"; }
+
+.fa-paperclip:before {
+ content: "\f0c6"; }
+
+.fa-parachute-box:before {
+ content: "\f4cd"; }
+
+.fa-paragraph:before {
+ content: "\f1dd"; }
+
+.fa-parking:before {
+ content: "\f540"; }
+
+.fa-passport:before {
+ content: "\f5ab"; }
+
+.fa-pastafarianism:before {
+ content: "\f67b"; }
+
+.fa-paste:before {
+ content: "\f0ea"; }
+
+.fa-patreon:before {
+ content: "\f3d9"; }
+
+.fa-pause:before {
+ content: "\f04c"; }
+
+.fa-pause-circle:before {
+ content: "\f28b"; }
+
+.fa-paw:before {
+ content: "\f1b0"; }
+
+.fa-paypal:before {
+ content: "\f1ed"; }
+
+.fa-peace:before {
+ content: "\f67c"; }
+
+.fa-pen:before {
+ content: "\f304"; }
+
+.fa-pen-alt:before {
+ content: "\f305"; }
+
+.fa-pen-fancy:before {
+ content: "\f5ac"; }
+
+.fa-pen-nib:before {
+ content: "\f5ad"; }
+
+.fa-pen-square:before {
+ content: "\f14b"; }
+
+.fa-pencil-alt:before {
+ content: "\f303"; }
+
+.fa-pencil-ruler:before {
+ content: "\f5ae"; }
+
+.fa-penny-arcade:before {
+ content: "\f704"; }
+
+.fa-people-arrows:before {
+ content: "\e068"; }
+
+.fa-people-carry:before {
+ content: "\f4ce"; }
+
+.fa-pepper-hot:before {
+ content: "\f816"; }
+
+.fa-perbyte:before {
+ content: "\e083"; }
+
+.fa-percent:before {
+ content: "\f295"; }
+
+.fa-percentage:before {
+ content: "\f541"; }
+
+.fa-periscope:before {
+ content: "\f3da"; }
+
+.fa-person-booth:before {
+ content: "\f756"; }
+
+.fa-phabricator:before {
+ content: "\f3db"; }
+
+.fa-phoenix-framework:before {
+ content: "\f3dc"; }
+
+.fa-phoenix-squadron:before {
+ content: "\f511"; }
+
+.fa-phone:before {
+ content: "\f095"; }
+
+.fa-phone-alt:before {
+ content: "\f879"; }
+
+.fa-phone-slash:before {
+ content: "\f3dd"; }
+
+.fa-phone-square:before {
+ content: "\f098"; }
+
+.fa-phone-square-alt:before {
+ content: "\f87b"; }
+
+.fa-phone-volume:before {
+ content: "\f2a0"; }
+
+.fa-photo-video:before {
+ content: "\f87c"; }
+
+.fa-php:before {
+ content: "\f457"; }
+
+.fa-pied-piper:before {
+ content: "\f2ae"; }
+
+.fa-pied-piper-alt:before {
+ content: "\f1a8"; }
+
+.fa-pied-piper-hat:before {
+ content: "\f4e5"; }
+
+.fa-pied-piper-pp:before {
+ content: "\f1a7"; }
+
+.fa-pied-piper-square:before {
+ content: "\e01e"; }
+
+.fa-piggy-bank:before {
+ content: "\f4d3"; }
+
+.fa-pills:before {
+ content: "\f484"; }
+
+.fa-pinterest:before {
+ content: "\f0d2"; }
+
+.fa-pinterest-p:before {
+ content: "\f231"; }
+
+.fa-pinterest-square:before {
+ content: "\f0d3"; }
+
+.fa-pizza-slice:before {
+ content: "\f818"; }
+
+.fa-place-of-worship:before {
+ content: "\f67f"; }
+
+.fa-plane:before {
+ content: "\f072"; }
+
+.fa-plane-arrival:before {
+ content: "\f5af"; }
+
+.fa-plane-departure:before {
+ content: "\f5b0"; }
+
+.fa-plane-slash:before {
+ content: "\e069"; }
+
+.fa-play:before {
+ content: "\f04b"; }
+
+.fa-play-circle:before {
+ content: "\f144"; }
+
+.fa-playstation:before {
+ content: "\f3df"; }
+
+.fa-plug:before {
+ content: "\f1e6"; }
+
+.fa-plus:before {
+ content: "\f067"; }
+
+.fa-plus-circle:before {
+ content: "\f055"; }
+
+.fa-plus-square:before {
+ content: "\f0fe"; }
+
+.fa-podcast:before {
+ content: "\f2ce"; }
+
+.fa-poll:before {
+ content: "\f681"; }
+
+.fa-poll-h:before {
+ content: "\f682"; }
+
+.fa-poo:before {
+ content: "\f2fe"; }
+
+.fa-poo-storm:before {
+ content: "\f75a"; }
+
+.fa-poop:before {
+ content: "\f619"; }
+
+.fa-portrait:before {
+ content: "\f3e0"; }
+
+.fa-pound-sign:before {
+ content: "\f154"; }
+
+.fa-power-off:before {
+ content: "\f011"; }
+
+.fa-pray:before {
+ content: "\f683"; }
+
+.fa-praying-hands:before {
+ content: "\f684"; }
+
+.fa-prescription:before {
+ content: "\f5b1"; }
+
+.fa-prescription-bottle:before {
+ content: "\f485"; }
+
+.fa-prescription-bottle-alt:before {
+ content: "\f486"; }
+
+.fa-print:before {
+ content: "\f02f"; }
+
+.fa-procedures:before {
+ content: "\f487"; }
+
+.fa-product-hunt:before {
+ content: "\f288"; }
+
+.fa-project-diagram:before {
+ content: "\f542"; }
+
+.fa-pump-medical:before {
+ content: "\e06a"; }
+
+.fa-pump-soap:before {
+ content: "\e06b"; }
+
+.fa-pushed:before {
+ content: "\f3e1"; }
+
+.fa-puzzle-piece:before {
+ content: "\f12e"; }
+
+.fa-python:before {
+ content: "\f3e2"; }
+
+.fa-qq:before {
+ content: "\f1d6"; }
+
+.fa-qrcode:before {
+ content: "\f029"; }
+
+.fa-question:before {
+ content: "\f128"; }
+
+.fa-question-circle:before {
+ content: "\f059"; }
+
+.fa-quidditch:before {
+ content: "\f458"; }
+
+.fa-quinscape:before {
+ content: "\f459"; }
+
+.fa-quora:before {
+ content: "\f2c4"; }
+
+.fa-quote-left:before {
+ content: "\f10d"; }
+
+.fa-quote-right:before {
+ content: "\f10e"; }
+
+.fa-quran:before {
+ content: "\f687"; }
+
+.fa-r-project:before {
+ content: "\f4f7"; }
+
+.fa-radiation:before {
+ content: "\f7b9"; }
+
+.fa-radiation-alt:before {
+ content: "\f7ba"; }
+
+.fa-rainbow:before {
+ content: "\f75b"; }
+
+.fa-random:before {
+ content: "\f074"; }
+
+.fa-raspberry-pi:before {
+ content: "\f7bb"; }
+
+.fa-ravelry:before {
+ content: "\f2d9"; }
+
+.fa-react:before {
+ content: "\f41b"; }
+
+.fa-reacteurope:before {
+ content: "\f75d"; }
+
+.fa-readme:before {
+ content: "\f4d5"; }
+
+.fa-rebel:before {
+ content: "\f1d0"; }
+
+.fa-receipt:before {
+ content: "\f543"; }
+
+.fa-record-vinyl:before {
+ content: "\f8d9"; }
+
+.fa-recycle:before {
+ content: "\f1b8"; }
+
+.fa-red-river:before {
+ content: "\f3e3"; }
+
+.fa-reddit:before {
+ content: "\f1a1"; }
+
+.fa-reddit-alien:before {
+ content: "\f281"; }
+
+.fa-reddit-square:before {
+ content: "\f1a2"; }
+
+.fa-redhat:before {
+ content: "\f7bc"; }
+
+.fa-redo:before {
+ content: "\f01e"; }
+
+.fa-redo-alt:before {
+ content: "\f2f9"; }
+
+.fa-registered:before {
+ content: "\f25d"; }
+
+.fa-remove-format:before {
+ content: "\f87d"; }
+
+.fa-renren:before {
+ content: "\f18b"; }
+
+.fa-reply:before {
+ content: "\f3e5"; }
+
+.fa-reply-all:before {
+ content: "\f122"; }
+
+.fa-replyd:before {
+ content: "\f3e6"; }
+
+.fa-republican:before {
+ content: "\f75e"; }
+
+.fa-researchgate:before {
+ content: "\f4f8"; }
+
+.fa-resolving:before {
+ content: "\f3e7"; }
+
+.fa-restroom:before {
+ content: "\f7bd"; }
+
+.fa-retweet:before {
+ content: "\f079"; }
+
+.fa-rev:before {
+ content: "\f5b2"; }
+
+.fa-ribbon:before {
+ content: "\f4d6"; }
+
+.fa-ring:before {
+ content: "\f70b"; }
+
+.fa-road:before {
+ content: "\f018"; }
+
+.fa-robot:before {
+ content: "\f544"; }
+
+.fa-rocket:before {
+ content: "\f135"; }
+
+.fa-rocketchat:before {
+ content: "\f3e8"; }
+
+.fa-rockrms:before {
+ content: "\f3e9"; }
+
+.fa-route:before {
+ content: "\f4d7"; }
+
+.fa-rss:before {
+ content: "\f09e"; }
+
+.fa-rss-square:before {
+ content: "\f143"; }
+
+.fa-ruble-sign:before {
+ content: "\f158"; }
+
+.fa-ruler:before {
+ content: "\f545"; }
+
+.fa-ruler-combined:before {
+ content: "\f546"; }
+
+.fa-ruler-horizontal:before {
+ content: "\f547"; }
+
+.fa-ruler-vertical:before {
+ content: "\f548"; }
+
+.fa-running:before {
+ content: "\f70c"; }
+
+.fa-rupee-sign:before {
+ content: "\f156"; }
+
+.fa-rust:before {
+ content: "\e07a"; }
+
+.fa-sad-cry:before {
+ content: "\f5b3"; }
+
+.fa-sad-tear:before {
+ content: "\f5b4"; }
+
+.fa-safari:before {
+ content: "\f267"; }
+
+.fa-salesforce:before {
+ content: "\f83b"; }
+
+.fa-sass:before {
+ content: "\f41e"; }
+
+.fa-satellite:before {
+ content: "\f7bf"; }
+
+.fa-satellite-dish:before {
+ content: "\f7c0"; }
+
+.fa-save:before {
+ content: "\f0c7"; }
+
+.fa-schlix:before {
+ content: "\f3ea"; }
+
+.fa-school:before {
+ content: "\f549"; }
+
+.fa-screwdriver:before {
+ content: "\f54a"; }
+
+.fa-scribd:before {
+ content: "\f28a"; }
+
+.fa-scroll:before {
+ content: "\f70e"; }
+
+.fa-sd-card:before {
+ content: "\f7c2"; }
+
+.fa-search:before {
+ content: "\f002"; }
+
+.fa-search-dollar:before {
+ content: "\f688"; }
+
+.fa-search-location:before {
+ content: "\f689"; }
+
+.fa-search-minus:before {
+ content: "\f010"; }
+
+.fa-search-plus:before {
+ content: "\f00e"; }
+
+.fa-searchengin:before {
+ content: "\f3eb"; }
+
+.fa-seedling:before {
+ content: "\f4d8"; }
+
+.fa-sellcast:before {
+ content: "\f2da"; }
+
+.fa-sellsy:before {
+ content: "\f213"; }
+
+.fa-server:before {
+ content: "\f233"; }
+
+.fa-servicestack:before {
+ content: "\f3ec"; }
+
+.fa-shapes:before {
+ content: "\f61f"; }
+
+.fa-share:before {
+ content: "\f064"; }
+
+.fa-share-alt:before {
+ content: "\f1e0"; }
+
+.fa-share-alt-square:before {
+ content: "\f1e1"; }
+
+.fa-share-square:before {
+ content: "\f14d"; }
+
+.fa-shekel-sign:before {
+ content: "\f20b"; }
+
+.fa-shield-alt:before {
+ content: "\f3ed"; }
+
+.fa-shield-virus:before {
+ content: "\e06c"; }
+
+.fa-ship:before {
+ content: "\f21a"; }
+
+.fa-shipping-fast:before {
+ content: "\f48b"; }
+
+.fa-shirtsinbulk:before {
+ content: "\f214"; }
+
+.fa-shoe-prints:before {
+ content: "\f54b"; }
+
+.fa-shopify:before {
+ content: "\e057"; }
+
+.fa-shopping-bag:before {
+ content: "\f290"; }
+
+.fa-shopping-basket:before {
+ content: "\f291"; }
+
+.fa-shopping-cart:before {
+ content: "\f07a"; }
+
+.fa-shopware:before {
+ content: "\f5b5"; }
+
+.fa-shower:before {
+ content: "\f2cc"; }
+
+.fa-shuttle-van:before {
+ content: "\f5b6"; }
+
+.fa-sign:before {
+ content: "\f4d9"; }
+
+.fa-sign-in-alt:before {
+ content: "\f2f6"; }
+
+.fa-sign-language:before {
+ content: "\f2a7"; }
+
+.fa-sign-out-alt:before {
+ content: "\f2f5"; }
+
+.fa-signal:before {
+ content: "\f012"; }
+
+.fa-signature:before {
+ content: "\f5b7"; }
+
+.fa-sim-card:before {
+ content: "\f7c4"; }
+
+.fa-simplybuilt:before {
+ content: "\f215"; }
+
+.fa-sink:before {
+ content: "\e06d"; }
+
+.fa-sistrix:before {
+ content: "\f3ee"; }
+
+.fa-sitemap:before {
+ content: "\f0e8"; }
+
+.fa-sith:before {
+ content: "\f512"; }
+
+.fa-skating:before {
+ content: "\f7c5"; }
+
+.fa-sketch:before {
+ content: "\f7c6"; }
+
+.fa-skiing:before {
+ content: "\f7c9"; }
+
+.fa-skiing-nordic:before {
+ content: "\f7ca"; }
+
+.fa-skull:before {
+ content: "\f54c"; }
+
+.fa-skull-crossbones:before {
+ content: "\f714"; }
+
+.fa-skyatlas:before {
+ content: "\f216"; }
+
+.fa-skype:before {
+ content: "\f17e"; }
+
+.fa-slack:before {
+ content: "\f198"; }
+
+.fa-slack-hash:before {
+ content: "\f3ef"; }
+
+.fa-slash:before {
+ content: "\f715"; }
+
+.fa-sleigh:before {
+ content: "\f7cc"; }
+
+.fa-sliders-h:before {
+ content: "\f1de"; }
+
+.fa-slideshare:before {
+ content: "\f1e7"; }
+
+.fa-smile:before {
+ content: "\f118"; }
+
+.fa-smile-beam:before {
+ content: "\f5b8"; }
+
+.fa-smile-wink:before {
+ content: "\f4da"; }
+
+.fa-smog:before {
+ content: "\f75f"; }
+
+.fa-smoking:before {
+ content: "\f48d"; }
+
+.fa-smoking-ban:before {
+ content: "\f54d"; }
+
+.fa-sms:before {
+ content: "\f7cd"; }
+
+.fa-snapchat:before {
+ content: "\f2ab"; }
+
+.fa-snapchat-ghost:before {
+ content: "\f2ac"; }
+
+.fa-snapchat-square:before {
+ content: "\f2ad"; }
+
+.fa-snowboarding:before {
+ content: "\f7ce"; }
+
+.fa-snowflake:before {
+ content: "\f2dc"; }
+
+.fa-snowman:before {
+ content: "\f7d0"; }
+
+.fa-snowplow:before {
+ content: "\f7d2"; }
+
+.fa-soap:before {
+ content: "\e06e"; }
+
+.fa-socks:before {
+ content: "\f696"; }
+
+.fa-solar-panel:before {
+ content: "\f5ba"; }
+
+.fa-sort:before {
+ content: "\f0dc"; }
+
+.fa-sort-alpha-down:before {
+ content: "\f15d"; }
+
+.fa-sort-alpha-down-alt:before {
+ content: "\f881"; }
+
+.fa-sort-alpha-up:before {
+ content: "\f15e"; }
+
+.fa-sort-alpha-up-alt:before {
+ content: "\f882"; }
+
+.fa-sort-amount-down:before {
+ content: "\f160"; }
+
+.fa-sort-amount-down-alt:before {
+ content: "\f884"; }
+
+.fa-sort-amount-up:before {
+ content: "\f161"; }
+
+.fa-sort-amount-up-alt:before {
+ content: "\f885"; }
+
+.fa-sort-down:before {
+ content: "\f0dd"; }
+
+.fa-sort-numeric-down:before {
+ content: "\f162"; }
+
+.fa-sort-numeric-down-alt:before {
+ content: "\f886"; }
+
+.fa-sort-numeric-up:before {
+ content: "\f163"; }
+
+.fa-sort-numeric-up-alt:before {
+ content: "\f887"; }
+
+.fa-sort-up:before {
+ content: "\f0de"; }
+
+.fa-soundcloud:before {
+ content: "\f1be"; }
+
+.fa-sourcetree:before {
+ content: "\f7d3"; }
+
+.fa-spa:before {
+ content: "\f5bb"; }
+
+.fa-space-shuttle:before {
+ content: "\f197"; }
+
+.fa-speakap:before {
+ content: "\f3f3"; }
+
+.fa-speaker-deck:before {
+ content: "\f83c"; }
+
+.fa-spell-check:before {
+ content: "\f891"; }
+
+.fa-spider:before {
+ content: "\f717"; }
+
+.fa-spinner:before {
+ content: "\f110"; }
+
+.fa-splotch:before {
+ content: "\f5bc"; }
+
+.fa-spotify:before {
+ content: "\f1bc"; }
+
+.fa-spray-can:before {
+ content: "\f5bd"; }
+
+.fa-square:before {
+ content: "\f0c8"; }
+
+.fa-square-full:before {
+ content: "\f45c"; }
+
+.fa-square-root-alt:before {
+ content: "\f698"; }
+
+.fa-squarespace:before {
+ content: "\f5be"; }
+
+.fa-stack-exchange:before {
+ content: "\f18d"; }
+
+.fa-stack-overflow:before {
+ content: "\f16c"; }
+
+.fa-stackpath:before {
+ content: "\f842"; }
+
+.fa-stamp:before {
+ content: "\f5bf"; }
+
+.fa-star:before {
+ content: "\f005"; }
+
+.fa-star-and-crescent:before {
+ content: "\f699"; }
+
+.fa-star-half:before {
+ content: "\f089"; }
+
+.fa-star-half-alt:before {
+ content: "\f5c0"; }
+
+.fa-star-of-david:before {
+ content: "\f69a"; }
+
+.fa-star-of-life:before {
+ content: "\f621"; }
+
+.fa-staylinked:before {
+ content: "\f3f5"; }
+
+.fa-steam:before {
+ content: "\f1b6"; }
+
+.fa-steam-square:before {
+ content: "\f1b7"; }
+
+.fa-steam-symbol:before {
+ content: "\f3f6"; }
+
+.fa-step-backward:before {
+ content: "\f048"; }
+
+.fa-step-forward:before {
+ content: "\f051"; }
+
+.fa-stethoscope:before {
+ content: "\f0f1"; }
+
+.fa-sticker-mule:before {
+ content: "\f3f7"; }
+
+.fa-sticky-note:before {
+ content: "\f249"; }
+
+.fa-stop:before {
+ content: "\f04d"; }
+
+.fa-stop-circle:before {
+ content: "\f28d"; }
+
+.fa-stopwatch:before {
+ content: "\f2f2"; }
+
+.fa-stopwatch-20:before {
+ content: "\e06f"; }
+
+.fa-store:before {
+ content: "\f54e"; }
+
+.fa-store-alt:before {
+ content: "\f54f"; }
+
+.fa-store-alt-slash:before {
+ content: "\e070"; }
+
+.fa-store-slash:before {
+ content: "\e071"; }
+
+.fa-strava:before {
+ content: "\f428"; }
+
+.fa-stream:before {
+ content: "\f550"; }
+
+.fa-street-view:before {
+ content: "\f21d"; }
+
+.fa-strikethrough:before {
+ content: "\f0cc"; }
+
+.fa-stripe:before {
+ content: "\f429"; }
+
+.fa-stripe-s:before {
+ content: "\f42a"; }
+
+.fa-stroopwafel:before {
+ content: "\f551"; }
+
+.fa-studiovinari:before {
+ content: "\f3f8"; }
+
+.fa-stumbleupon:before {
+ content: "\f1a4"; }
+
+.fa-stumbleupon-circle:before {
+ content: "\f1a3"; }
+
+.fa-subscript:before {
+ content: "\f12c"; }
+
+.fa-subway:before {
+ content: "\f239"; }
+
+.fa-suitcase:before {
+ content: "\f0f2"; }
+
+.fa-suitcase-rolling:before {
+ content: "\f5c1"; }
+
+.fa-sun:before {
+ content: "\f185"; }
+
+.fa-superpowers:before {
+ content: "\f2dd"; }
+
+.fa-superscript:before {
+ content: "\f12b"; }
+
+.fa-supple:before {
+ content: "\f3f9"; }
+
+.fa-surprise:before {
+ content: "\f5c2"; }
+
+.fa-suse:before {
+ content: "\f7d6"; }
+
+.fa-swatchbook:before {
+ content: "\f5c3"; }
+
+.fa-swift:before {
+ content: "\f8e1"; }
+
+.fa-swimmer:before {
+ content: "\f5c4"; }
+
+.fa-swimming-pool:before {
+ content: "\f5c5"; }
+
+.fa-symfony:before {
+ content: "\f83d"; }
+
+.fa-synagogue:before {
+ content: "\f69b"; }
+
+.fa-sync:before {
+ content: "\f021"; }
+
+.fa-sync-alt:before {
+ content: "\f2f1"; }
+
+.fa-syringe:before {
+ content: "\f48e"; }
+
+.fa-table:before {
+ content: "\f0ce"; }
+
+.fa-table-tennis:before {
+ content: "\f45d"; }
+
+.fa-tablet:before {
+ content: "\f10a"; }
+
+.fa-tablet-alt:before {
+ content: "\f3fa"; }
+
+.fa-tablets:before {
+ content: "\f490"; }
+
+.fa-tachometer-alt:before {
+ content: "\f3fd"; }
+
+.fa-tag:before {
+ content: "\f02b"; }
+
+.fa-tags:before {
+ content: "\f02c"; }
+
+.fa-tape:before {
+ content: "\f4db"; }
+
+.fa-tasks:before {
+ content: "\f0ae"; }
+
+.fa-taxi:before {
+ content: "\f1ba"; }
+
+.fa-teamspeak:before {
+ content: "\f4f9"; }
+
+.fa-teeth:before {
+ content: "\f62e"; }
+
+.fa-teeth-open:before {
+ content: "\f62f"; }
+
+.fa-telegram:before {
+ content: "\f2c6"; }
+
+.fa-telegram-plane:before {
+ content: "\f3fe"; }
+
+.fa-temperature-high:before {
+ content: "\f769"; }
+
+.fa-temperature-low:before {
+ content: "\f76b"; }
+
+.fa-tencent-weibo:before {
+ content: "\f1d5"; }
+
+.fa-tenge:before {
+ content: "\f7d7"; }
+
+.fa-terminal:before {
+ content: "\f120"; }
+
+.fa-text-height:before {
+ content: "\f034"; }
+
+.fa-text-width:before {
+ content: "\f035"; }
+
+.fa-th:before {
+ content: "\f00a"; }
+
+.fa-th-large:before {
+ content: "\f009"; }
+
+.fa-th-list:before {
+ content: "\f00b"; }
+
+.fa-the-red-yeti:before {
+ content: "\f69d"; }
+
+.fa-theater-masks:before {
+ content: "\f630"; }
+
+.fa-themeco:before {
+ content: "\f5c6"; }
+
+.fa-themeisle:before {
+ content: "\f2b2"; }
+
+.fa-thermometer:before {
+ content: "\f491"; }
+
+.fa-thermometer-empty:before {
+ content: "\f2cb"; }
+
+.fa-thermometer-full:before {
+ content: "\f2c7"; }
+
+.fa-thermometer-half:before {
+ content: "\f2c9"; }
+
+.fa-thermometer-quarter:before {
+ content: "\f2ca"; }
+
+.fa-thermometer-three-quarters:before {
+ content: "\f2c8"; }
+
+.fa-think-peaks:before {
+ content: "\f731"; }
+
+.fa-thumbs-down:before {
+ content: "\f165"; }
+
+.fa-thumbs-up:before {
+ content: "\f164"; }
+
+.fa-thumbtack:before {
+ content: "\f08d"; }
+
+.fa-ticket-alt:before {
+ content: "\f3ff"; }
+
+.fa-tiktok:before {
+ content: "\e07b"; }
+
+.fa-times:before {
+ content: "\f00d"; }
+
+.fa-times-circle:before {
+ content: "\f057"; }
+
+.fa-tint:before {
+ content: "\f043"; }
+
+.fa-tint-slash:before {
+ content: "\f5c7"; }
+
+.fa-tired:before {
+ content: "\f5c8"; }
+
+.fa-toggle-off:before {
+ content: "\f204"; }
+
+.fa-toggle-on:before {
+ content: "\f205"; }
+
+.fa-toilet:before {
+ content: "\f7d8"; }
+
+.fa-toilet-paper:before {
+ content: "\f71e"; }
+
+.fa-toilet-paper-slash:before {
+ content: "\e072"; }
+
+.fa-toolbox:before {
+ content: "\f552"; }
+
+.fa-tools:before {
+ content: "\f7d9"; }
+
+.fa-tooth:before {
+ content: "\f5c9"; }
+
+.fa-torah:before {
+ content: "\f6a0"; }
+
+.fa-torii-gate:before {
+ content: "\f6a1"; }
+
+.fa-tractor:before {
+ content: "\f722"; }
+
+.fa-trade-federation:before {
+ content: "\f513"; }
+
+.fa-trademark:before {
+ content: "\f25c"; }
+
+.fa-traffic-light:before {
+ content: "\f637"; }
+
+.fa-trailer:before {
+ content: "\e041"; }
+
+.fa-train:before {
+ content: "\f238"; }
+
+.fa-tram:before {
+ content: "\f7da"; }
+
+.fa-transgender:before {
+ content: "\f224"; }
+
+.fa-transgender-alt:before {
+ content: "\f225"; }
+
+.fa-trash:before {
+ content: "\f1f8"; }
+
+.fa-trash-alt:before {
+ content: "\f2ed"; }
+
+.fa-trash-restore:before {
+ content: "\f829"; }
+
+.fa-trash-restore-alt:before {
+ content: "\f82a"; }
+
+.fa-tree:before {
+ content: "\f1bb"; }
+
+.fa-trello:before {
+ content: "\f181"; }
+
+.fa-trophy:before {
+ content: "\f091"; }
+
+.fa-truck:before {
+ content: "\f0d1"; }
+
+.fa-truck-loading:before {
+ content: "\f4de"; }
+
+.fa-truck-monster:before {
+ content: "\f63b"; }
+
+.fa-truck-moving:before {
+ content: "\f4df"; }
+
+.fa-truck-pickup:before {
+ content: "\f63c"; }
+
+.fa-tshirt:before {
+ content: "\f553"; }
+
+.fa-tty:before {
+ content: "\f1e4"; }
+
+.fa-tumblr:before {
+ content: "\f173"; }
+
+.fa-tumblr-square:before {
+ content: "\f174"; }
+
+.fa-tv:before {
+ content: "\f26c"; }
+
+.fa-twitch:before {
+ content: "\f1e8"; }
+
+.fa-twitter:before {
+ content: "\f099"; }
+
+.fa-twitter-square:before {
+ content: "\f081"; }
+
+.fa-typo3:before {
+ content: "\f42b"; }
+
+.fa-uber:before {
+ content: "\f402"; }
+
+.fa-ubuntu:before {
+ content: "\f7df"; }
+
+.fa-uikit:before {
+ content: "\f403"; }
+
+.fa-umbraco:before {
+ content: "\f8e8"; }
+
+.fa-umbrella:before {
+ content: "\f0e9"; }
+
+.fa-umbrella-beach:before {
+ content: "\f5ca"; }
+
+.fa-uncharted:before {
+ content: "\e084"; }
+
+.fa-underline:before {
+ content: "\f0cd"; }
+
+.fa-undo:before {
+ content: "\f0e2"; }
+
+.fa-undo-alt:before {
+ content: "\f2ea"; }
+
+.fa-uniregistry:before {
+ content: "\f404"; }
+
+.fa-unity:before {
+ content: "\e049"; }
+
+.fa-universal-access:before {
+ content: "\f29a"; }
+
+.fa-university:before {
+ content: "\f19c"; }
+
+.fa-unlink:before {
+ content: "\f127"; }
+
+.fa-unlock:before {
+ content: "\f09c"; }
+
+.fa-unlock-alt:before {
+ content: "\f13e"; }
+
+.fa-unsplash:before {
+ content: "\e07c"; }
+
+.fa-untappd:before {
+ content: "\f405"; }
+
+.fa-upload:before {
+ content: "\f093"; }
+
+.fa-ups:before {
+ content: "\f7e0"; }
+
+.fa-usb:before {
+ content: "\f287"; }
+
+.fa-user:before {
+ content: "\f007"; }
+
+.fa-user-alt:before {
+ content: "\f406"; }
+
+.fa-user-alt-slash:before {
+ content: "\f4fa"; }
+
+.fa-user-astronaut:before {
+ content: "\f4fb"; }
+
+.fa-user-check:before {
+ content: "\f4fc"; }
+
+.fa-user-circle:before {
+ content: "\f2bd"; }
+
+.fa-user-clock:before {
+ content: "\f4fd"; }
+
+.fa-user-cog:before {
+ content: "\f4fe"; }
+
+.fa-user-edit:before {
+ content: "\f4ff"; }
+
+.fa-user-friends:before {
+ content: "\f500"; }
+
+.fa-user-graduate:before {
+ content: "\f501"; }
+
+.fa-user-injured:before {
+ content: "\f728"; }
+
+.fa-user-lock:before {
+ content: "\f502"; }
+
+.fa-user-md:before {
+ content: "\f0f0"; }
+
+.fa-user-minus:before {
+ content: "\f503"; }
+
+.fa-user-ninja:before {
+ content: "\f504"; }
+
+.fa-user-nurse:before {
+ content: "\f82f"; }
+
+.fa-user-plus:before {
+ content: "\f234"; }
+
+.fa-user-secret:before {
+ content: "\f21b"; }
+
+.fa-user-shield:before {
+ content: "\f505"; }
+
+.fa-user-slash:before {
+ content: "\f506"; }
+
+.fa-user-tag:before {
+ content: "\f507"; }
+
+.fa-user-tie:before {
+ content: "\f508"; }
+
+.fa-user-times:before {
+ content: "\f235"; }
+
+.fa-users:before {
+ content: "\f0c0"; }
+
+.fa-users-cog:before {
+ content: "\f509"; }
+
+.fa-users-slash:before {
+ content: "\e073"; }
+
+.fa-usps:before {
+ content: "\f7e1"; }
+
+.fa-ussunnah:before {
+ content: "\f407"; }
+
+.fa-utensil-spoon:before {
+ content: "\f2e5"; }
+
+.fa-utensils:before {
+ content: "\f2e7"; }
+
+.fa-vaadin:before {
+ content: "\f408"; }
+
+.fa-vector-square:before {
+ content: "\f5cb"; }
+
+.fa-venus:before {
+ content: "\f221"; }
+
+.fa-venus-double:before {
+ content: "\f226"; }
+
+.fa-venus-mars:before {
+ content: "\f228"; }
+
+.fa-vest:before {
+ content: "\e085"; }
+
+.fa-vest-patches:before {
+ content: "\e086"; }
+
+.fa-viacoin:before {
+ content: "\f237"; }
+
+.fa-viadeo:before {
+ content: "\f2a9"; }
+
+.fa-viadeo-square:before {
+ content: "\f2aa"; }
+
+.fa-vial:before {
+ content: "\f492"; }
+
+.fa-vials:before {
+ content: "\f493"; }
+
+.fa-viber:before {
+ content: "\f409"; }
+
+.fa-video:before {
+ content: "\f03d"; }
+
+.fa-video-slash:before {
+ content: "\f4e2"; }
+
+.fa-vihara:before {
+ content: "\f6a7"; }
+
+.fa-vimeo:before {
+ content: "\f40a"; }
+
+.fa-vimeo-square:before {
+ content: "\f194"; }
+
+.fa-vimeo-v:before {
+ content: "\f27d"; }
+
+.fa-vine:before {
+ content: "\f1ca"; }
+
+.fa-virus:before {
+ content: "\e074"; }
+
+.fa-virus-slash:before {
+ content: "\e075"; }
+
+.fa-viruses:before {
+ content: "\e076"; }
+
+.fa-vk:before {
+ content: "\f189"; }
+
+.fa-vnv:before {
+ content: "\f40b"; }
+
+.fa-voicemail:before {
+ content: "\f897"; }
+
+.fa-volleyball-ball:before {
+ content: "\f45f"; }
+
+.fa-volume-down:before {
+ content: "\f027"; }
+
+.fa-volume-mute:before {
+ content: "\f6a9"; }
+
+.fa-volume-off:before {
+ content: "\f026"; }
+
+.fa-volume-up:before {
+ content: "\f028"; }
+
+.fa-vote-yea:before {
+ content: "\f772"; }
+
+.fa-vr-cardboard:before {
+ content: "\f729"; }
+
+.fa-vuejs:before {
+ content: "\f41f"; }
+
+.fa-walking:before {
+ content: "\f554"; }
+
+.fa-wallet:before {
+ content: "\f555"; }
+
+.fa-warehouse:before {
+ content: "\f494"; }
+
+.fa-watchman-monitoring:before {
+ content: "\e087"; }
+
+.fa-water:before {
+ content: "\f773"; }
+
+.fa-wave-square:before {
+ content: "\f83e"; }
+
+.fa-waze:before {
+ content: "\f83f"; }
+
+.fa-weebly:before {
+ content: "\f5cc"; }
+
+.fa-weibo:before {
+ content: "\f18a"; }
+
+.fa-weight:before {
+ content: "\f496"; }
+
+.fa-weight-hanging:before {
+ content: "\f5cd"; }
+
+.fa-weixin:before {
+ content: "\f1d7"; }
+
+.fa-whatsapp:before {
+ content: "\f232"; }
+
+.fa-whatsapp-square:before {
+ content: "\f40c"; }
+
+.fa-wheelchair:before {
+ content: "\f193"; }
+
+.fa-whmcs:before {
+ content: "\f40d"; }
+
+.fa-wifi:before {
+ content: "\f1eb"; }
+
+.fa-wikipedia-w:before {
+ content: "\f266"; }
+
+.fa-wind:before {
+ content: "\f72e"; }
+
+.fa-window-close:before {
+ content: "\f410"; }
+
+.fa-window-maximize:before {
+ content: "\f2d0"; }
+
+.fa-window-minimize:before {
+ content: "\f2d1"; }
+
+.fa-window-restore:before {
+ content: "\f2d2"; }
+
+.fa-windows:before {
+ content: "\f17a"; }
+
+.fa-wine-bottle:before {
+ content: "\f72f"; }
+
+.fa-wine-glass:before {
+ content: "\f4e3"; }
+
+.fa-wine-glass-alt:before {
+ content: "\f5ce"; }
+
+.fa-wix:before {
+ content: "\f5cf"; }
+
+.fa-wizards-of-the-coast:before {
+ content: "\f730"; }
+
+.fa-wodu:before {
+ content: "\e088"; }
+
+.fa-wolf-pack-battalion:before {
+ content: "\f514"; }
+
+.fa-won-sign:before {
+ content: "\f159"; }
+
+.fa-wordpress:before {
+ content: "\f19a"; }
+
+.fa-wordpress-simple:before {
+ content: "\f411"; }
+
+.fa-wpbeginner:before {
+ content: "\f297"; }
+
+.fa-wpexplorer:before {
+ content: "\f2de"; }
+
+.fa-wpforms:before {
+ content: "\f298"; }
+
+.fa-wpressr:before {
+ content: "\f3e4"; }
+
+.fa-wrench:before {
+ content: "\f0ad"; }
+
+.fa-x-ray:before {
+ content: "\f497"; }
+
+.fa-xbox:before {
+ content: "\f412"; }
+
+.fa-xing:before {
+ content: "\f168"; }
+
+.fa-xing-square:before {
+ content: "\f169"; }
+
+.fa-y-combinator:before {
+ content: "\f23b"; }
+
+.fa-yahoo:before {
+ content: "\f19e"; }
+
+.fa-yammer:before {
+ content: "\f840"; }
+
+.fa-yandex:before {
+ content: "\f413"; }
+
+.fa-yandex-international:before {
+ content: "\f414"; }
+
+.fa-yarn:before {
+ content: "\f7e3"; }
+
+.fa-yelp:before {
+ content: "\f1e9"; }
+
+.fa-yen-sign:before {
+ content: "\f157"; }
+
+.fa-yin-yang:before {
+ content: "\f6ad"; }
+
+.fa-yoast:before {
+ content: "\f2b1"; }
+
+.fa-youtube:before {
+ content: "\f167"; }
+
+.fa-youtube-square:before {
+ content: "\f431"; }
+
+.fa-zhihu:before {
+ content: "\f63f"; }
+
+.sr-only {
+ border: 0;
+ clip: rect(0, 0, 0, 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px; }
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+ clip: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ position: static;
+ width: auto; }
+@font-face {
+ font-family: 'Font Awesome 5 Brands';
+ font-style: normal;
+ font-weight: 400;
+ font-display: block;
+ src: url("../webfonts/fa-brands-400.eot");
+ src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); }
+
+.fab {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+@font-face {
+ font-family: 'Font Awesome 5 Free';
+ font-style: normal;
+ font-weight: 400;
+ font-display: block;
+ src: url("../webfonts/fa-regular-400.eot");
+ src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); }
+
+.far {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+@font-face {
+ font-family: 'Font Awesome 5 Free';
+ font-style: normal;
+ font-weight: 900;
+ font-display: block;
+ src: url("../webfonts/fa-solid-900.eot");
+ src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); }
+
+.fa,
+.fas {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 900; }
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css
new file mode 100644
index 0000000000..1ef4893b4a
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css
@@ -0,0 +1,2172 @@
+/*!
+ * Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
+ * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
+ */
+.fa.fa-glass:before {
+ content: "\f000"; }
+
+.fa.fa-meetup {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-star-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-star-o:before {
+ content: "\f005"; }
+
+.fa.fa-remove:before {
+ content: "\f00d"; }
+
+.fa.fa-close:before {
+ content: "\f00d"; }
+
+.fa.fa-gear:before {
+ content: "\f013"; }
+
+.fa.fa-trash-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-trash-o:before {
+ content: "\f2ed"; }
+
+.fa.fa-file-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-o:before {
+ content: "\f15b"; }
+
+.fa.fa-clock-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-clock-o:before {
+ content: "\f017"; }
+
+.fa.fa-arrow-circle-o-down {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-arrow-circle-o-down:before {
+ content: "\f358"; }
+
+.fa.fa-arrow-circle-o-up {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-arrow-circle-o-up:before {
+ content: "\f35b"; }
+
+.fa.fa-play-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-play-circle-o:before {
+ content: "\f144"; }
+
+.fa.fa-repeat:before {
+ content: "\f01e"; }
+
+.fa.fa-rotate-right:before {
+ content: "\f01e"; }
+
+.fa.fa-refresh:before {
+ content: "\f021"; }
+
+.fa.fa-list-alt {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-dedent:before {
+ content: "\f03b"; }
+
+.fa.fa-video-camera:before {
+ content: "\f03d"; }
+
+.fa.fa-picture-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-picture-o:before {
+ content: "\f03e"; }
+
+.fa.fa-photo {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-photo:before {
+ content: "\f03e"; }
+
+.fa.fa-image {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-image:before {
+ content: "\f03e"; }
+
+.fa.fa-pencil:before {
+ content: "\f303"; }
+
+.fa.fa-map-marker:before {
+ content: "\f3c5"; }
+
+.fa.fa-pencil-square-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-pencil-square-o:before {
+ content: "\f044"; }
+
+.fa.fa-share-square-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-share-square-o:before {
+ content: "\f14d"; }
+
+.fa.fa-check-square-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-check-square-o:before {
+ content: "\f14a"; }
+
+.fa.fa-arrows:before {
+ content: "\f0b2"; }
+
+.fa.fa-times-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-times-circle-o:before {
+ content: "\f057"; }
+
+.fa.fa-check-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-check-circle-o:before {
+ content: "\f058"; }
+
+.fa.fa-mail-forward:before {
+ content: "\f064"; }
+
+.fa.fa-expand:before {
+ content: "\f424"; }
+
+.fa.fa-compress:before {
+ content: "\f422"; }
+
+.fa.fa-eye {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-eye-slash {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-warning:before {
+ content: "\f071"; }
+
+.fa.fa-calendar:before {
+ content: "\f073"; }
+
+.fa.fa-arrows-v:before {
+ content: "\f338"; }
+
+.fa.fa-arrows-h:before {
+ content: "\f337"; }
+
+.fa.fa-bar-chart {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-bar-chart:before {
+ content: "\f080"; }
+
+.fa.fa-bar-chart-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-bar-chart-o:before {
+ content: "\f080"; }
+
+.fa.fa-twitter-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-facebook-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-gears:before {
+ content: "\f085"; }
+
+.fa.fa-thumbs-o-up {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-thumbs-o-up:before {
+ content: "\f164"; }
+
+.fa.fa-thumbs-o-down {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-thumbs-o-down:before {
+ content: "\f165"; }
+
+.fa.fa-heart-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-heart-o:before {
+ content: "\f004"; }
+
+.fa.fa-sign-out:before {
+ content: "\f2f5"; }
+
+.fa.fa-linkedin-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-linkedin-square:before {
+ content: "\f08c"; }
+
+.fa.fa-thumb-tack:before {
+ content: "\f08d"; }
+
+.fa.fa-external-link:before {
+ content: "\f35d"; }
+
+.fa.fa-sign-in:before {
+ content: "\f2f6"; }
+
+.fa.fa-github-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-lemon-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-lemon-o:before {
+ content: "\f094"; }
+
+.fa.fa-square-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-square-o:before {
+ content: "\f0c8"; }
+
+.fa.fa-bookmark-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-bookmark-o:before {
+ content: "\f02e"; }
+
+.fa.fa-twitter {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-facebook {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-facebook:before {
+ content: "\f39e"; }
+
+.fa.fa-facebook-f {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-facebook-f:before {
+ content: "\f39e"; }
+
+.fa.fa-github {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-credit-card {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-feed:before {
+ content: "\f09e"; }
+
+.fa.fa-hdd-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hdd-o:before {
+ content: "\f0a0"; }
+
+.fa.fa-hand-o-right {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-o-right:before {
+ content: "\f0a4"; }
+
+.fa.fa-hand-o-left {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-o-left:before {
+ content: "\f0a5"; }
+
+.fa.fa-hand-o-up {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-o-up:before {
+ content: "\f0a6"; }
+
+.fa.fa-hand-o-down {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-o-down:before {
+ content: "\f0a7"; }
+
+.fa.fa-arrows-alt:before {
+ content: "\f31e"; }
+
+.fa.fa-group:before {
+ content: "\f0c0"; }
+
+.fa.fa-chain:before {
+ content: "\f0c1"; }
+
+.fa.fa-scissors:before {
+ content: "\f0c4"; }
+
+.fa.fa-files-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-files-o:before {
+ content: "\f0c5"; }
+
+.fa.fa-floppy-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-floppy-o:before {
+ content: "\f0c7"; }
+
+.fa.fa-navicon:before {
+ content: "\f0c9"; }
+
+.fa.fa-reorder:before {
+ content: "\f0c9"; }
+
+.fa.fa-pinterest {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-pinterest-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google-plus-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google-plus {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google-plus:before {
+ content: "\f0d5"; }
+
+.fa.fa-money {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-money:before {
+ content: "\f3d1"; }
+
+.fa.fa-unsorted:before {
+ content: "\f0dc"; }
+
+.fa.fa-sort-desc:before {
+ content: "\f0dd"; }
+
+.fa.fa-sort-asc:before {
+ content: "\f0de"; }
+
+.fa.fa-linkedin {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-linkedin:before {
+ content: "\f0e1"; }
+
+.fa.fa-rotate-left:before {
+ content: "\f0e2"; }
+
+.fa.fa-legal:before {
+ content: "\f0e3"; }
+
+.fa.fa-tachometer:before {
+ content: "\f3fd"; }
+
+.fa.fa-dashboard:before {
+ content: "\f3fd"; }
+
+.fa.fa-comment-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-comment-o:before {
+ content: "\f075"; }
+
+.fa.fa-comments-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-comments-o:before {
+ content: "\f086"; }
+
+.fa.fa-flash:before {
+ content: "\f0e7"; }
+
+.fa.fa-clipboard {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-paste {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-paste:before {
+ content: "\f328"; }
+
+.fa.fa-lightbulb-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-lightbulb-o:before {
+ content: "\f0eb"; }
+
+.fa.fa-exchange:before {
+ content: "\f362"; }
+
+.fa.fa-cloud-download:before {
+ content: "\f381"; }
+
+.fa.fa-cloud-upload:before {
+ content: "\f382"; }
+
+.fa.fa-bell-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-bell-o:before {
+ content: "\f0f3"; }
+
+.fa.fa-cutlery:before {
+ content: "\f2e7"; }
+
+.fa.fa-file-text-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-text-o:before {
+ content: "\f15c"; }
+
+.fa.fa-building-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-building-o:before {
+ content: "\f1ad"; }
+
+.fa.fa-hospital-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hospital-o:before {
+ content: "\f0f8"; }
+
+.fa.fa-tablet:before {
+ content: "\f3fa"; }
+
+.fa.fa-mobile:before {
+ content: "\f3cd"; }
+
+.fa.fa-mobile-phone:before {
+ content: "\f3cd"; }
+
+.fa.fa-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-circle-o:before {
+ content: "\f111"; }
+
+.fa.fa-mail-reply:before {
+ content: "\f3e5"; }
+
+.fa.fa-github-alt {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-folder-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-folder-o:before {
+ content: "\f07b"; }
+
+.fa.fa-folder-open-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-folder-open-o:before {
+ content: "\f07c"; }
+
+.fa.fa-smile-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-smile-o:before {
+ content: "\f118"; }
+
+.fa.fa-frown-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-frown-o:before {
+ content: "\f119"; }
+
+.fa.fa-meh-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-meh-o:before {
+ content: "\f11a"; }
+
+.fa.fa-keyboard-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-keyboard-o:before {
+ content: "\f11c"; }
+
+.fa.fa-flag-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-flag-o:before {
+ content: "\f024"; }
+
+.fa.fa-mail-reply-all:before {
+ content: "\f122"; }
+
+.fa.fa-star-half-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-star-half-o:before {
+ content: "\f089"; }
+
+.fa.fa-star-half-empty {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-star-half-empty:before {
+ content: "\f089"; }
+
+.fa.fa-star-half-full {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-star-half-full:before {
+ content: "\f089"; }
+
+.fa.fa-code-fork:before {
+ content: "\f126"; }
+
+.fa.fa-chain-broken:before {
+ content: "\f127"; }
+
+.fa.fa-shield:before {
+ content: "\f3ed"; }
+
+.fa.fa-calendar-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-calendar-o:before {
+ content: "\f133"; }
+
+.fa.fa-maxcdn {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-html5 {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-css3 {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-ticket:before {
+ content: "\f3ff"; }
+
+.fa.fa-minus-square-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-minus-square-o:before {
+ content: "\f146"; }
+
+.fa.fa-level-up:before {
+ content: "\f3bf"; }
+
+.fa.fa-level-down:before {
+ content: "\f3be"; }
+
+.fa.fa-pencil-square:before {
+ content: "\f14b"; }
+
+.fa.fa-external-link-square:before {
+ content: "\f360"; }
+
+.fa.fa-compass {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-caret-square-o-down {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-caret-square-o-down:before {
+ content: "\f150"; }
+
+.fa.fa-toggle-down {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-toggle-down:before {
+ content: "\f150"; }
+
+.fa.fa-caret-square-o-up {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-caret-square-o-up:before {
+ content: "\f151"; }
+
+.fa.fa-toggle-up {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-toggle-up:before {
+ content: "\f151"; }
+
+.fa.fa-caret-square-o-right {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-caret-square-o-right:before {
+ content: "\f152"; }
+
+.fa.fa-toggle-right {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-toggle-right:before {
+ content: "\f152"; }
+
+.fa.fa-eur:before {
+ content: "\f153"; }
+
+.fa.fa-euro:before {
+ content: "\f153"; }
+
+.fa.fa-gbp:before {
+ content: "\f154"; }
+
+.fa.fa-usd:before {
+ content: "\f155"; }
+
+.fa.fa-dollar:before {
+ content: "\f155"; }
+
+.fa.fa-inr:before {
+ content: "\f156"; }
+
+.fa.fa-rupee:before {
+ content: "\f156"; }
+
+.fa.fa-jpy:before {
+ content: "\f157"; }
+
+.fa.fa-cny:before {
+ content: "\f157"; }
+
+.fa.fa-rmb:before {
+ content: "\f157"; }
+
+.fa.fa-yen:before {
+ content: "\f157"; }
+
+.fa.fa-rub:before {
+ content: "\f158"; }
+
+.fa.fa-ruble:before {
+ content: "\f158"; }
+
+.fa.fa-rouble:before {
+ content: "\f158"; }
+
+.fa.fa-krw:before {
+ content: "\f159"; }
+
+.fa.fa-won:before {
+ content: "\f159"; }
+
+.fa.fa-btc {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-bitcoin {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-bitcoin:before {
+ content: "\f15a"; }
+
+.fa.fa-file-text:before {
+ content: "\f15c"; }
+
+.fa.fa-sort-alpha-asc:before {
+ content: "\f15d"; }
+
+.fa.fa-sort-alpha-desc:before {
+ content: "\f881"; }
+
+.fa.fa-sort-amount-asc:before {
+ content: "\f160"; }
+
+.fa.fa-sort-amount-desc:before {
+ content: "\f884"; }
+
+.fa.fa-sort-numeric-asc:before {
+ content: "\f162"; }
+
+.fa.fa-sort-numeric-desc:before {
+ content: "\f886"; }
+
+.fa.fa-youtube-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-youtube {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-xing {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-xing-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-youtube-play {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-youtube-play:before {
+ content: "\f167"; }
+
+.fa.fa-dropbox {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-stack-overflow {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-instagram {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-flickr {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-adn {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-bitbucket {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-bitbucket-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-bitbucket-square:before {
+ content: "\f171"; }
+
+.fa.fa-tumblr {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-tumblr-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-long-arrow-down:before {
+ content: "\f309"; }
+
+.fa.fa-long-arrow-up:before {
+ content: "\f30c"; }
+
+.fa.fa-long-arrow-left:before {
+ content: "\f30a"; }
+
+.fa.fa-long-arrow-right:before {
+ content: "\f30b"; }
+
+.fa.fa-apple {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-windows {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-android {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-linux {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-dribbble {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-skype {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-foursquare {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-trello {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-gratipay {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-gittip {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-gittip:before {
+ content: "\f184"; }
+
+.fa.fa-sun-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-sun-o:before {
+ content: "\f185"; }
+
+.fa.fa-moon-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-moon-o:before {
+ content: "\f186"; }
+
+.fa.fa-vk {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-weibo {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-renren {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-pagelines {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-stack-exchange {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-arrow-circle-o-right {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-arrow-circle-o-right:before {
+ content: "\f35a"; }
+
+.fa.fa-arrow-circle-o-left {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-arrow-circle-o-left:before {
+ content: "\f359"; }
+
+.fa.fa-caret-square-o-left {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-caret-square-o-left:before {
+ content: "\f191"; }
+
+.fa.fa-toggle-left {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-toggle-left:before {
+ content: "\f191"; }
+
+.fa.fa-dot-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-dot-circle-o:before {
+ content: "\f192"; }
+
+.fa.fa-vimeo-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-try:before {
+ content: "\f195"; }
+
+.fa.fa-turkish-lira:before {
+ content: "\f195"; }
+
+.fa.fa-plus-square-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-plus-square-o:before {
+ content: "\f0fe"; }
+
+.fa.fa-slack {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wordpress {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-openid {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-institution:before {
+ content: "\f19c"; }
+
+.fa.fa-bank:before {
+ content: "\f19c"; }
+
+.fa.fa-mortar-board:before {
+ content: "\f19d"; }
+
+.fa.fa-yahoo {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-reddit {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-reddit-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-stumbleupon-circle {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-stumbleupon {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-delicious {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-digg {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-pied-piper-pp {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-pied-piper-alt {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-drupal {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-joomla {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-spoon:before {
+ content: "\f2e5"; }
+
+.fa.fa-behance {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-behance-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-steam {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-steam-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-automobile:before {
+ content: "\f1b9"; }
+
+.fa.fa-envelope-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-envelope-o:before {
+ content: "\f0e0"; }
+
+.fa.fa-spotify {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-deviantart {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-soundcloud {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-file-pdf-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-pdf-o:before {
+ content: "\f1c1"; }
+
+.fa.fa-file-word-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-word-o:before {
+ content: "\f1c2"; }
+
+.fa.fa-file-excel-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-excel-o:before {
+ content: "\f1c3"; }
+
+.fa.fa-file-powerpoint-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-powerpoint-o:before {
+ content: "\f1c4"; }
+
+.fa.fa-file-image-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-image-o:before {
+ content: "\f1c5"; }
+
+.fa.fa-file-photo-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-photo-o:before {
+ content: "\f1c5"; }
+
+.fa.fa-file-picture-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-picture-o:before {
+ content: "\f1c5"; }
+
+.fa.fa-file-archive-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-archive-o:before {
+ content: "\f1c6"; }
+
+.fa.fa-file-zip-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-zip-o:before {
+ content: "\f1c6"; }
+
+.fa.fa-file-audio-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-audio-o:before {
+ content: "\f1c7"; }
+
+.fa.fa-file-sound-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-sound-o:before {
+ content: "\f1c7"; }
+
+.fa.fa-file-video-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-video-o:before {
+ content: "\f1c8"; }
+
+.fa.fa-file-movie-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-movie-o:before {
+ content: "\f1c8"; }
+
+.fa.fa-file-code-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-file-code-o:before {
+ content: "\f1c9"; }
+
+.fa.fa-vine {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-codepen {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-jsfiddle {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-life-ring {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-life-bouy {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-life-bouy:before {
+ content: "\f1cd"; }
+
+.fa.fa-life-buoy {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-life-buoy:before {
+ content: "\f1cd"; }
+
+.fa.fa-life-saver {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-life-saver:before {
+ content: "\f1cd"; }
+
+.fa.fa-support {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-support:before {
+ content: "\f1cd"; }
+
+.fa.fa-circle-o-notch:before {
+ content: "\f1ce"; }
+
+.fa.fa-rebel {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-ra {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-ra:before {
+ content: "\f1d0"; }
+
+.fa.fa-resistance {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-resistance:before {
+ content: "\f1d0"; }
+
+.fa.fa-empire {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-ge {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-ge:before {
+ content: "\f1d1"; }
+
+.fa.fa-git-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-git {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-hacker-news {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-y-combinator-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-y-combinator-square:before {
+ content: "\f1d4"; }
+
+.fa.fa-yc-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-yc-square:before {
+ content: "\f1d4"; }
+
+.fa.fa-tencent-weibo {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-qq {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-weixin {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wechat {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wechat:before {
+ content: "\f1d7"; }
+
+.fa.fa-send:before {
+ content: "\f1d8"; }
+
+.fa.fa-paper-plane-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-paper-plane-o:before {
+ content: "\f1d8"; }
+
+.fa.fa-send-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-send-o:before {
+ content: "\f1d8"; }
+
+.fa.fa-circle-thin {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-circle-thin:before {
+ content: "\f111"; }
+
+.fa.fa-header:before {
+ content: "\f1dc"; }
+
+.fa.fa-sliders:before {
+ content: "\f1de"; }
+
+.fa.fa-futbol-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-futbol-o:before {
+ content: "\f1e3"; }
+
+.fa.fa-soccer-ball-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-soccer-ball-o:before {
+ content: "\f1e3"; }
+
+.fa.fa-slideshare {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-twitch {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-yelp {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-newspaper-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-newspaper-o:before {
+ content: "\f1ea"; }
+
+.fa.fa-paypal {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google-wallet {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc-visa {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc-mastercard {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc-discover {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc-amex {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc-paypal {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc-stripe {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-bell-slash-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-bell-slash-o:before {
+ content: "\f1f6"; }
+
+.fa.fa-trash:before {
+ content: "\f2ed"; }
+
+.fa.fa-copyright {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-eyedropper:before {
+ content: "\f1fb"; }
+
+.fa.fa-area-chart:before {
+ content: "\f1fe"; }
+
+.fa.fa-pie-chart:before {
+ content: "\f200"; }
+
+.fa.fa-line-chart:before {
+ content: "\f201"; }
+
+.fa.fa-lastfm {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-lastfm-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-ioxhost {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-angellist {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-cc:before {
+ content: "\f20a"; }
+
+.fa.fa-ils:before {
+ content: "\f20b"; }
+
+.fa.fa-shekel:before {
+ content: "\f20b"; }
+
+.fa.fa-sheqel:before {
+ content: "\f20b"; }
+
+.fa.fa-meanpath {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-meanpath:before {
+ content: "\f2b4"; }
+
+.fa.fa-buysellads {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-connectdevelop {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-dashcube {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-forumbee {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-leanpub {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-sellsy {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-shirtsinbulk {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-simplybuilt {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-skyatlas {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-diamond {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-diamond:before {
+ content: "\f3a5"; }
+
+.fa.fa-intersex:before {
+ content: "\f224"; }
+
+.fa.fa-facebook-official {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-facebook-official:before {
+ content: "\f09a"; }
+
+.fa.fa-pinterest-p {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-whatsapp {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-hotel:before {
+ content: "\f236"; }
+
+.fa.fa-viacoin {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-medium {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-y-combinator {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-yc {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-yc:before {
+ content: "\f23b"; }
+
+.fa.fa-optin-monster {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-opencart {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-expeditedssl {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-battery-4:before {
+ content: "\f240"; }
+
+.fa.fa-battery:before {
+ content: "\f240"; }
+
+.fa.fa-battery-3:before {
+ content: "\f241"; }
+
+.fa.fa-battery-2:before {
+ content: "\f242"; }
+
+.fa.fa-battery-1:before {
+ content: "\f243"; }
+
+.fa.fa-battery-0:before {
+ content: "\f244"; }
+
+.fa.fa-object-group {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-object-ungroup {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-sticky-note-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-sticky-note-o:before {
+ content: "\f249"; }
+
+.fa.fa-cc-jcb {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cc-diners-club {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-clone {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hourglass-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hourglass-o:before {
+ content: "\f254"; }
+
+.fa.fa-hourglass-1:before {
+ content: "\f251"; }
+
+.fa.fa-hourglass-2:before {
+ content: "\f252"; }
+
+.fa.fa-hourglass-3:before {
+ content: "\f253"; }
+
+.fa.fa-hand-rock-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-rock-o:before {
+ content: "\f255"; }
+
+.fa.fa-hand-grab-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-grab-o:before {
+ content: "\f255"; }
+
+.fa.fa-hand-paper-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-paper-o:before {
+ content: "\f256"; }
+
+.fa.fa-hand-stop-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-stop-o:before {
+ content: "\f256"; }
+
+.fa.fa-hand-scissors-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-scissors-o:before {
+ content: "\f257"; }
+
+.fa.fa-hand-lizard-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-lizard-o:before {
+ content: "\f258"; }
+
+.fa.fa-hand-spock-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-spock-o:before {
+ content: "\f259"; }
+
+.fa.fa-hand-pointer-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-pointer-o:before {
+ content: "\f25a"; }
+
+.fa.fa-hand-peace-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-hand-peace-o:before {
+ content: "\f25b"; }
+
+.fa.fa-registered {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-creative-commons {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-gg {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-gg-circle {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-tripadvisor {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-odnoklassniki {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-odnoklassniki-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-get-pocket {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wikipedia-w {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-safari {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-chrome {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-firefox {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-opera {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-internet-explorer {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-television:before {
+ content: "\f26c"; }
+
+.fa.fa-contao {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-500px {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-amazon {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-calendar-plus-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-calendar-plus-o:before {
+ content: "\f271"; }
+
+.fa.fa-calendar-minus-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-calendar-minus-o:before {
+ content: "\f272"; }
+
+.fa.fa-calendar-times-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-calendar-times-o:before {
+ content: "\f273"; }
+
+.fa.fa-calendar-check-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-calendar-check-o:before {
+ content: "\f274"; }
+
+.fa.fa-map-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-map-o:before {
+ content: "\f279"; }
+
+.fa.fa-commenting:before {
+ content: "\f4ad"; }
+
+.fa.fa-commenting-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-commenting-o:before {
+ content: "\f4ad"; }
+
+.fa.fa-houzz {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-vimeo {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-vimeo:before {
+ content: "\f27d"; }
+
+.fa.fa-black-tie {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-fonticons {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-reddit-alien {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-edge {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-credit-card-alt:before {
+ content: "\f09d"; }
+
+.fa.fa-codiepie {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-modx {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-fort-awesome {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-usb {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-product-hunt {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-mixcloud {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-scribd {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-pause-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-pause-circle-o:before {
+ content: "\f28b"; }
+
+.fa.fa-stop-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-stop-circle-o:before {
+ content: "\f28d"; }
+
+.fa.fa-bluetooth {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-bluetooth-b {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-gitlab {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wpbeginner {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wpforms {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-envira {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wheelchair-alt {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wheelchair-alt:before {
+ content: "\f368"; }
+
+.fa.fa-question-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-question-circle-o:before {
+ content: "\f059"; }
+
+.fa.fa-volume-control-phone:before {
+ content: "\f2a0"; }
+
+.fa.fa-asl-interpreting:before {
+ content: "\f2a3"; }
+
+.fa.fa-deafness:before {
+ content: "\f2a4"; }
+
+.fa.fa-hard-of-hearing:before {
+ content: "\f2a4"; }
+
+.fa.fa-glide {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-glide-g {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-signing:before {
+ content: "\f2a7"; }
+
+.fa.fa-viadeo {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-viadeo-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-snapchat {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-snapchat-ghost {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-snapchat-square {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-pied-piper {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-first-order {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-yoast {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-themeisle {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google-plus-official {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google-plus-official:before {
+ content: "\f2b3"; }
+
+.fa.fa-google-plus-circle {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-google-plus-circle:before {
+ content: "\f2b3"; }
+
+.fa.fa-font-awesome {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-fa {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-fa:before {
+ content: "\f2b4"; }
+
+.fa.fa-handshake-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-handshake-o:before {
+ content: "\f2b5"; }
+
+.fa.fa-envelope-open-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-envelope-open-o:before {
+ content: "\f2b6"; }
+
+.fa.fa-linode {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-address-book-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-address-book-o:before {
+ content: "\f2b9"; }
+
+.fa.fa-vcard:before {
+ content: "\f2bb"; }
+
+.fa.fa-address-card-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-address-card-o:before {
+ content: "\f2bb"; }
+
+.fa.fa-vcard-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-vcard-o:before {
+ content: "\f2bb"; }
+
+.fa.fa-user-circle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-user-circle-o:before {
+ content: "\f2bd"; }
+
+.fa.fa-user-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-user-o:before {
+ content: "\f007"; }
+
+.fa.fa-id-badge {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-drivers-license:before {
+ content: "\f2c2"; }
+
+.fa.fa-id-card-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-id-card-o:before {
+ content: "\f2c2"; }
+
+.fa.fa-drivers-license-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-drivers-license-o:before {
+ content: "\f2c2"; }
+
+.fa.fa-quora {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-free-code-camp {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-telegram {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-thermometer-4:before {
+ content: "\f2c7"; }
+
+.fa.fa-thermometer:before {
+ content: "\f2c7"; }
+
+.fa.fa-thermometer-3:before {
+ content: "\f2c8"; }
+
+.fa.fa-thermometer-2:before {
+ content: "\f2c9"; }
+
+.fa.fa-thermometer-1:before {
+ content: "\f2ca"; }
+
+.fa.fa-thermometer-0:before {
+ content: "\f2cb"; }
+
+.fa.fa-bathtub:before {
+ content: "\f2cd"; }
+
+.fa.fa-s15:before {
+ content: "\f2cd"; }
+
+.fa.fa-window-maximize {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-window-restore {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-times-rectangle:before {
+ content: "\f410"; }
+
+.fa.fa-window-close-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-window-close-o:before {
+ content: "\f410"; }
+
+.fa.fa-times-rectangle-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-times-rectangle-o:before {
+ content: "\f410"; }
+
+.fa.fa-bandcamp {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-grav {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-etsy {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-imdb {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-ravelry {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-eercast {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-eercast:before {
+ content: "\f2da"; }
+
+.fa.fa-snowflake-o {
+ font-family: 'Font Awesome 5 Free';
+ font-weight: 400; }
+
+.fa.fa-snowflake-o:before {
+ content: "\f2dc"; }
+
+.fa.fa-superpowers {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-wpexplorer {
+ font-family: 'Font Awesome 5 Brands';
+ font-weight: 400; }
+
+.fa.fa-cab:before {
+ content: "\f1ba"; }
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.svg
diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf
similarity index 99%
rename from modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf
index cba6c6cce8..8d75deddae 100644
Binary files a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.eot and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf differ
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2 b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2
new file mode 100644
index 0000000000..402f81c0bc
Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2 differ
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg
diff --git a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf
similarity index 95%
rename from modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf
index a4e598936b..7157aafbac 100644
Binary files a/modules/blogging/app/Volo.BloggingTestApp/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf differ
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2 b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2
new file mode 100644
index 0000000000..56328948b3
Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2 differ
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg
diff --git a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf
similarity index 97%
rename from modules/client-simulation/demo/Volo.ClientSimulation.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf
index e99417197e..25abf389e2 100644
Binary files a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf differ
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff
similarity index 100%
rename from modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff
rename to modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2 b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2
new file mode 100644
index 0000000000..2217164f0c
Binary files /dev/null and b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2 differ
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css
new file mode 100644
index 0000000000..ddf9cae5b2
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css
@@ -0,0 +1,56 @@
+@keyframes spin {
+ 0% {
+ transform: translateZ(0) rotate(0deg);
+ }
+
+ 100% {
+ transform: translateZ(0) rotate(360deg);
+ }
+}
+
+.abp-block-area {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 102;
+ background-color: #fff;
+ opacity: .8;
+ transition: opacity .25s;
+}
+
+ .abp-block-area.abp-block-area-disappearing {
+ opacity: 0;
+ }
+
+ .abp-block-area.abp-block-area-busy:after {
+ content: attr(data-text);
+ display: block;
+ max-width: 125px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ font-size: 20px;
+ font-family: sans-serif;
+ color: #343a40;
+ text-align: center;
+ text-transform: uppercase;
+ }
+
+ .abp-block-area.abp-block-area-busy:before {
+ content: "";
+ display: block;
+ width: 150px;
+ height: 150px;
+ border-radius: 50%;
+ border-width: 2px;
+ border-style: solid;
+ border-color: transparent #228ae6 #228ae6 #228ae6;
+ position: absolute;
+ top: calc(50% - 75px);
+ left: calc(50% - 75px);
+ will-change: transform;
+ animation: spin .75s infinite ease-in-out;
+ }
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js
new file mode 100644
index 0000000000..7a82f58e98
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js
@@ -0,0 +1,823 @@
+var abp = abp || {};
+(function () {
+
+ /* Application paths *****************************************/
+
+ //Current application root path (including virtual directory if exists).
+ abp.appPath = abp.appPath || '/';
+
+ abp.pageLoadTime = new Date();
+
+ //Converts given path to absolute path using abp.appPath variable.
+ abp.toAbsAppPath = function (path) {
+ if (path.indexOf('/') == 0) {
+ path = path.substring(1);
+ }
+
+ return abp.appPath + path;
+ };
+
+ /* LOGGING ***************************************************/
+ //Implements Logging API that provides secure & controlled usage of console.log
+
+ abp.log = abp.log || {};
+
+ abp.log.levels = {
+ DEBUG: 1,
+ INFO: 2,
+ WARN: 3,
+ ERROR: 4,
+ FATAL: 5
+ };
+
+ abp.log.level = abp.log.levels.DEBUG;
+
+ abp.log.log = function (logObject, logLevel) {
+ if (!window.console || !window.console.log) {
+ return;
+ }
+
+ if (logLevel != undefined && logLevel < abp.log.level) {
+ return;
+ }
+
+ console.log(logObject);
+ };
+
+ abp.log.debug = function (logObject) {
+ abp.log.log("DEBUG: ", abp.log.levels.DEBUG);
+ abp.log.log(logObject, abp.log.levels.DEBUG);
+ };
+
+ abp.log.info = function (logObject) {
+ abp.log.log("INFO: ", abp.log.levels.INFO);
+ abp.log.log(logObject, abp.log.levels.INFO);
+ };
+
+ abp.log.warn = function (logObject) {
+ abp.log.log("WARN: ", abp.log.levels.WARN);
+ abp.log.log(logObject, abp.log.levels.WARN);
+ };
+
+ abp.log.error = function (logObject) {
+ abp.log.log("ERROR: ", abp.log.levels.ERROR);
+ abp.log.log(logObject, abp.log.levels.ERROR);
+ };
+
+ abp.log.fatal = function (logObject) {
+ abp.log.log("FATAL: ", abp.log.levels.FATAL);
+ abp.log.log(logObject, abp.log.levels.FATAL);
+ };
+
+ /* LOCALIZATION ***********************************************/
+
+ abp.localization = abp.localization || {};
+ abp.localization.internal = abp.localization.internal || {};
+ abp.localization.values = abp.localization.values || {};
+ abp.localization.resources = abp.localization.resources || {};
+
+ abp.localization.internal.getResource = function (resourceName) {
+ var resource = abp.localization.resources[resourceName];
+ if (resource) {
+ return resource;
+ }
+
+ var legacySource = abp.localization.values[resourceName];
+ if (legacySource) {
+ return {
+ texts: abp.localization.values[resourceName],
+ baseResources: []
+ };
+ }
+
+ abp.log.warn('Could not find localization source: ' + resourceName);
+ return null;
+ };
+
+ abp.localization.internal.localize = function (key, sourceName) {
+ var resource = abp.localization.internal.getResource(sourceName);
+ if (!resource){
+ return {
+ value: key,
+ found: false
+ };
+ }
+
+ var value = resource.texts[key];
+ if (value === undefined) {
+ for (var i = 0; i < resource.baseResources.length; i++){
+ var basedArguments = Array.prototype.slice.call(arguments, 0);
+ basedArguments[1] = resource.baseResources[i];
+
+ var result = abp.localization.internal.localize.apply(this, basedArguments);
+ if (result.found){
+ return result;
+ }
+ }
+
+ return {
+ value: key,
+ found: false
+ };
+ }
+
+ var copiedArguments = Array.prototype.slice.call(arguments, 0);
+ copiedArguments.splice(1, 1);
+ copiedArguments[0] = value;
+
+ return {
+ value: abp.utils.formatString.apply(this, copiedArguments),
+ found: true
+ };
+ };
+
+ abp.localization.localize = function (key, sourceName) {
+ if (sourceName === '_') { //A convention to suppress the localization
+ return key;
+ }
+
+ if (sourceName) {
+ return abp.localization.internal.localize.apply(this, arguments).value;
+ }
+
+ if (!abp.localization.defaultResourceName) {
+ abp.log.warn('Localization source name is not specified and the defaultResourceName was not defined!');
+ return key;
+ }
+
+ var copiedArguments = Array.prototype.slice.call(arguments, 0);
+ copiedArguments.splice(1, 1, abp.localization.defaultResourceName);
+
+ return abp.localization.internal.localize.apply(this, copiedArguments).value;
+ };
+
+ abp.localization.isLocalized = function (key, sourceName) {
+ if (sourceName === '_') { //A convention to suppress the localization
+ return true;
+ }
+
+ sourceName = sourceName || abp.localization.defaultResourceName;
+ if (!sourceName) {
+ return false;
+ }
+
+ return abp.localization.internal.localize(key, sourceName).found;
+ };
+
+ abp.localization.getResource = function (name) {
+ return function () {
+ var copiedArguments = Array.prototype.slice.call(arguments, 0);
+ copiedArguments.splice(1, 0, name);
+ return abp.localization.localize.apply(this, copiedArguments);
+ };
+ };
+
+ abp.localization.defaultResourceName = undefined;
+ abp.localization.currentCulture = {
+ cultureName: undefined
+ };
+
+ var getMapValue = function (packageMaps, packageName, language) {
+ language = language || abp.localization.currentCulture.name;
+ if (!packageMaps || !packageName || !language) {
+ return language;
+ }
+
+ var packageMap = packageMaps[packageName];
+ if (!packageMap) {
+ return language;
+ }
+
+ for (var i = 0; i < packageMap.length; i++) {
+ var map = packageMap[i];
+ if (map.name === language){
+ return map.value;
+ }
+ }
+
+ return language;
+ };
+
+ abp.localization.getLanguagesMap = function (packageName, language) {
+ return getMapValue(abp.localization.languagesMap, packageName, language);
+ };
+
+ abp.localization.getLanguageFilesMap = function (packageName, language) {
+ return getMapValue(abp.localization.languageFilesMap, packageName, language);
+ };
+
+ /* AUTHORIZATION **********************************************/
+
+ abp.auth = abp.auth || {};
+
+ abp.auth.grantedPolicies = abp.auth.grantedPolicies || {};
+
+ abp.auth.isGranted = function (policyName) {
+ return abp.auth.grantedPolicies[policyName] != undefined;
+ };
+
+ abp.auth.isAnyGranted = function () {
+ if (!arguments || arguments.length <= 0) {
+ return true;
+ }
+
+ for (var i = 0; i < arguments.length; i++) {
+ if (abp.auth.isGranted(arguments[i])) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ abp.auth.areAllGranted = function () {
+ if (!arguments || arguments.length <= 0) {
+ return true;
+ }
+
+ for (var i = 0; i < arguments.length; i++) {
+ if (!abp.auth.isGranted(arguments[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ abp.auth.tokenCookieName = 'Abp.AuthToken';
+
+ abp.auth.setToken = function (authToken, expireDate) {
+ abp.utils.setCookieValue(abp.auth.tokenCookieName, authToken, expireDate, abp.appPath, abp.domain);
+ };
+
+ abp.auth.getToken = function () {
+ return abp.utils.getCookieValue(abp.auth.tokenCookieName);
+ }
+
+ abp.auth.clearToken = function () {
+ abp.auth.setToken();
+ }
+
+ /* SETTINGS *************************************************/
+
+ abp.setting = abp.setting || {};
+
+ abp.setting.values = abp.setting.values || {};
+
+ abp.setting.get = function (name) {
+ return abp.setting.values[name];
+ };
+
+ abp.setting.getBoolean = function (name) {
+ var value = abp.setting.get(name);
+ return value == 'true' || value == 'True';
+ };
+
+ abp.setting.getInt = function (name) {
+ return parseInt(abp.setting.values[name]);
+ };
+
+ /* NOTIFICATION *********************************************/
+ //Defines Notification API, not implements it
+
+ abp.notify = abp.notify || {};
+
+ abp.notify.success = function (message, title, options) {
+ abp.log.warn('abp.notify.success is not implemented!');
+ };
+
+ abp.notify.info = function (message, title, options) {
+ abp.log.warn('abp.notify.info is not implemented!');
+ };
+
+ abp.notify.warn = function (message, title, options) {
+ abp.log.warn('abp.notify.warn is not implemented!');
+ };
+
+ abp.notify.error = function (message, title, options) {
+ abp.log.warn('abp.notify.error is not implemented!');
+ };
+
+ /* MESSAGE **************************************************/
+ //Defines Message API, not implements it
+
+ abp.message = abp.message || {};
+
+ abp.message._showMessage = function (message, title) {
+ alert((title || '') + ' ' + message);
+ };
+
+ abp.message.info = function (message, title) {
+ abp.log.warn('abp.message.info is not implemented!');
+ return abp.message._showMessage(message, title);
+ };
+
+ abp.message.success = function (message, title) {
+ abp.log.warn('abp.message.success is not implemented!');
+ return abp.message._showMessage(message, title);
+ };
+
+ abp.message.warn = function (message, title) {
+ abp.log.warn('abp.message.warn is not implemented!');
+ return abp.message._showMessage(message, title);
+ };
+
+ abp.message.error = function (message, title) {
+ abp.log.warn('abp.message.error is not implemented!');
+ return abp.message._showMessage(message, title);
+ };
+
+ abp.message.confirm = function (message, titleOrCallback, callback) {
+ abp.log.warn('abp.message.confirm is not properly implemented!');
+
+ if (titleOrCallback && !(typeof titleOrCallback == 'string')) {
+ callback = titleOrCallback;
+ }
+
+ var result = confirm(message);
+ callback && callback(result);
+ };
+
+ /* UI *******************************************************/
+
+ abp.ui = abp.ui || {};
+
+ /* UI BLOCK */
+ //Defines UI Block API and implements basically
+
+ var $abpBlockArea = document.createElement('div');
+ $abpBlockArea.classList.add('abp-block-area');
+
+ /* opts: { //Can be an object with options or a string for query a selector
+ * elm: a query selector (optional - default: document.body)
+ * busy: boolean (optional - default: false)
+ * promise: A promise with always or finally handler (optional - auto unblocks the ui if provided)
+ * }
+ */
+ abp.ui.block = function (opts) {
+ if (!opts) {
+ opts = {};
+ } else if (typeof opts == 'string') {
+ opts = {
+ elm: opts
+ };
+ }
+
+ var $elm = document.querySelector(opts.elm) || document.body;
+
+ if (opts.busy) {
+ $abpBlockArea.classList.add('abp-block-area-busy');
+ } else {
+ $abpBlockArea.classList.remove('abp-block-area-busy');
+ }
+
+ if (document.querySelector(opts.elm)) {
+ $abpBlockArea.style.position = 'absolute';
+ } else {
+ $abpBlockArea.style.position = 'fixed';
+ }
+
+ $elm.appendChild($abpBlockArea);
+
+ if (opts.promise) {
+ if (opts.promise.always) { //jQuery.Deferred style
+ opts.promise.always(function () {
+ abp.ui.unblock({
+ $elm: opts.elm
+ });
+ });
+ } else if (opts.promise['finally']) { //Q style
+ opts.promise['finally'](function () {
+ abp.ui.unblock({
+ $elm: opts.elm
+ });
+ });
+ }
+ }
+ };
+
+ /* opts: {
+ *
+ * }
+ */
+ abp.ui.unblock = function (opts) {
+ var element = document.querySelector('.abp-block-area');
+ if (element) {
+ element.classList.add('abp-block-area-disappearing');
+ setTimeout(function () {
+ if (element) {
+ element.classList.remove('abp-block-area-disappearing');
+ if (element.parentElement) {
+ element.parentElement.removeChild(element);
+ }
+ }
+ }, 250);
+ }
+ };
+
+ /* UI BUSY */
+ //Defines UI Busy API, not implements it
+
+ abp.ui.setBusy = function (opts) {
+ if (!opts) {
+ opts = {
+ busy: true
+ };
+ } else if (typeof opts == 'string') {
+ opts = {
+ elm: opts,
+ busy: true
+ };
+ }
+
+ abp.ui.block(opts);
+ };
+
+ abp.ui.clearBusy = function (opts) {
+ abp.ui.unblock(opts);
+ };
+
+ /* SIMPLE EVENT BUS *****************************************/
+
+ abp.event = (function () {
+
+ var _callbacks = {};
+
+ var on = function (eventName, callback) {
+ if (!_callbacks[eventName]) {
+ _callbacks[eventName] = [];
+ }
+
+ _callbacks[eventName].push(callback);
+ };
+
+ var off = function (eventName, callback) {
+ var callbacks = _callbacks[eventName];
+ if (!callbacks) {
+ return;
+ }
+
+ var index = -1;
+ for (var i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] === callback) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0) {
+ return;
+ }
+
+ _callbacks[eventName].splice(index, 1);
+ };
+
+ var trigger = function (eventName) {
+ var callbacks = _callbacks[eventName];
+ if (!callbacks || !callbacks.length) {
+ return;
+ }
+
+ var args = Array.prototype.slice.call(arguments, 1);
+ for (var i = 0; i < callbacks.length; i++) {
+ callbacks[i].apply(this, args);
+ }
+ };
+
+ // Public interface ///////////////////////////////////////////////////
+
+ return {
+ on: on,
+ off: off,
+ trigger: trigger
+ };
+ })();
+
+
+ /* UTILS ***************************************************/
+
+ abp.utils = abp.utils || {};
+
+ /* Creates a name namespace.
+ * Example:
+ * var taskService = abp.utils.createNamespace(abp, 'services.task');
+ * taskService will be equal to abp.services.task
+ * first argument (root) must be defined first
+ ************************************************************/
+ abp.utils.createNamespace = function (root, ns) {
+ var parts = ns.split('.');
+ for (var i = 0; i < parts.length; i++) {
+ if (typeof root[parts[i]] == 'undefined') {
+ root[parts[i]] = {};
+ }
+
+ root = root[parts[i]];
+ }
+
+ return root;
+ };
+
+ /* Find and replaces a string (search) to another string (replacement) in
+ * given string (str).
+ * Example:
+ * abp.utils.replaceAll('This is a test string', 'is', 'X') = 'ThX X a test string'
+ ************************************************************/
+ abp.utils.replaceAll = function (str, search, replacement) {
+ var fix = search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
+ return str.replace(new RegExp(fix, 'g'), replacement);
+ };
+
+ /* Formats a string just like string.format in C#.
+ * Example:
+ * abp.utils.formatString('Hello {0}','Tuana') = 'Hello Tuana'
+ ************************************************************/
+ abp.utils.formatString = function () {
+ if (arguments.length < 1) {
+ return null;
+ }
+
+ var str = arguments[0];
+
+ for (var i = 1; i < arguments.length; i++) {
+ var placeHolder = '{' + (i - 1) + '}';
+ str = abp.utils.replaceAll(str, placeHolder, arguments[i]);
+ }
+
+ return str;
+ };
+
+ abp.utils.toPascalCase = function (str) {
+ if (!str || !str.length) {
+ return str;
+ }
+
+ if (str.length === 1) {
+ return str.charAt(0).toUpperCase();
+ }
+
+ return str.charAt(0).toUpperCase() + str.substr(1);
+ }
+
+ abp.utils.toCamelCase = function (str) {
+ if (!str || !str.length) {
+ return str;
+ }
+
+ if (str.length === 1) {
+ return str.charAt(0).toLowerCase();
+ }
+
+ return str.charAt(0).toLowerCase() + str.substr(1);
+ }
+
+ abp.utils.truncateString = function (str, maxLength) {
+ if (!str || !str.length || str.length <= maxLength) {
+ return str;
+ }
+
+ return str.substr(0, maxLength);
+ };
+
+ abp.utils.truncateStringWithPostfix = function (str, maxLength, postfix) {
+ postfix = postfix || '...';
+
+ if (!str || !str.length || str.length <= maxLength) {
+ return str;
+ }
+
+ if (maxLength <= postfix.length) {
+ return postfix.substr(0, maxLength);
+ }
+
+ return str.substr(0, maxLength - postfix.length) + postfix;
+ };
+
+ abp.utils.isFunction = function (obj) {
+ return !!(obj && obj.constructor && obj.call && obj.apply);
+ };
+
+ /**
+ * parameterInfos should be an array of { name, value } objects
+ * where name is query string parameter name and value is it's value.
+ * includeQuestionMark is true by default.
+ */
+ abp.utils.buildQueryString = function (parameterInfos, includeQuestionMark) {
+ if (includeQuestionMark === undefined) {
+ includeQuestionMark = true;
+ }
+
+ var qs = '';
+
+ function addSeperator() {
+ if (!qs.length) {
+ if (includeQuestionMark) {
+ qs = qs + '?';
+ }
+ } else {
+ qs = qs + '&';
+ }
+ }
+
+ for (var i = 0; i < parameterInfos.length; ++i) {
+ var parameterInfo = parameterInfos[i];
+ if (parameterInfo.value === undefined) {
+ continue;
+ }
+
+ if (parameterInfo.value === null) {
+ parameterInfo.value = '';
+ }
+
+ addSeperator();
+
+ if (parameterInfo.value.toJSON && typeof parameterInfo.value.toJSON === "function") {
+ qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value.toJSON());
+ } else if (Array.isArray(parameterInfo.value) && parameterInfo.value.length) {
+ for (var j = 0; j < parameterInfo.value.length; j++) {
+ if (j > 0) {
+ addSeperator();
+ }
+
+ qs = qs + parameterInfo.name + '[' + j + ']=' + encodeURIComponent(parameterInfo.value[j]);
+ }
+ } else {
+ qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value);
+ }
+ }
+
+ return qs;
+ }
+
+ /**
+ * Sets a cookie value for given key.
+ * This is a simple implementation created to be used by ABP.
+ * Please use a complete cookie library if you need.
+ * @param {string} key
+ * @param {string} value
+ * @param {Date} expireDate (optional). If not specified the cookie will expire at the end of session.
+ * @param {string} path (optional)
+ */
+ abp.utils.setCookieValue = function (key, value, expireDate, path) {
+ var cookieValue = encodeURIComponent(key) + '=';
+
+ if (value) {
+ cookieValue = cookieValue + encodeURIComponent(value);
+ }
+
+ if (expireDate) {
+ cookieValue = cookieValue + "; expires=" + expireDate.toUTCString();
+ }
+
+ if (path) {
+ cookieValue = cookieValue + "; path=" + path;
+ }
+
+ document.cookie = cookieValue;
+ };
+
+ /**
+ * Gets a cookie with given key.
+ * This is a simple implementation created to be used by ABP.
+ * Please use a complete cookie library if you need.
+ * @param {string} key
+ * @returns {string} Cookie value or null
+ */
+ abp.utils.getCookieValue = function (key) {
+ var equalities = document.cookie.split('; ');
+ for (var i = 0; i < equalities.length; i++) {
+ if (!equalities[i]) {
+ continue;
+ }
+
+ var splitted = equalities[i].split('=');
+ if (splitted.length != 2) {
+ continue;
+ }
+
+ if (decodeURIComponent(splitted[0]) === key) {
+ return decodeURIComponent(splitted[1] || '');
+ }
+ }
+
+ return null;
+ };
+
+ /**
+ * Deletes cookie for given key.
+ * This is a simple implementation created to be used by ABP.
+ * Please use a complete cookie library if you need.
+ * @param {string} key
+ * @param {string} path (optional)
+ */
+ abp.utils.deleteCookie = function (key, path) {
+ var cookieValue = encodeURIComponent(key) + '=';
+
+ cookieValue = cookieValue + "; expires=" + (new Date(new Date().getTime() - 86400000)).toUTCString();
+
+ if (path) {
+ cookieValue = cookieValue + "; path=" + path;
+ }
+
+ document.cookie = cookieValue;
+ }
+
+ /**
+ * Escape HTML to help prevent XSS attacks.
+ */
+ abp.utils.htmlEscape = function (html) {
+ return typeof html === 'string' ? html.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"') : html;
+ }
+
+ /* SECURITY ***************************************/
+ abp.security = abp.security || {};
+ abp.security.antiForgery = abp.security.antiForgery || {};
+
+ abp.security.antiForgery.tokenCookieName = 'XSRF-TOKEN';
+ abp.security.antiForgery.tokenHeaderName = 'RequestVerificationToken';
+
+ abp.security.antiForgery.getToken = function () {
+ return abp.utils.getCookieValue(abp.security.antiForgery.tokenCookieName);
+ };
+
+ /* CLOCK *****************************************/
+ abp.clock = abp.clock || {};
+
+ abp.clock.kind = 'Unspecified';
+
+ abp.clock.supportsMultipleTimezone = function () {
+ return abp.clock.kind === 'Utc';
+ };
+
+ var toLocal = function (date) {
+ return new Date(
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ date.getHours(),
+ date.getMinutes(),
+ date.getSeconds(),
+ date.getMilliseconds()
+ );
+ };
+
+ var toUtc = function (date) {
+ return Date.UTC(
+ date.getUTCFullYear(),
+ date.getUTCMonth(),
+ date.getUTCDate(),
+ date.getUTCHours(),
+ date.getUTCMinutes(),
+ date.getUTCSeconds(),
+ date.getUTCMilliseconds()
+ );
+ };
+
+ abp.clock.now = function () {
+ if (abp.clock.kind === 'Utc') {
+ return toUtc(new Date());
+ }
+ return new Date();
+ };
+
+ abp.clock.normalize = function (date) {
+ var kind = abp.clock.kind;
+
+ if (kind === 'Unspecified') {
+ return date;
+ }
+
+ if (kind === 'Local') {
+ return toLocal(date);
+ }
+
+ if (kind === 'Utc') {
+ return toUtc(date);
+ }
+ };
+
+ /* FEATURES *************************************************/
+
+ abp.features = abp.features || {};
+
+ abp.features.values = abp.features.values || {};
+
+ abp.features.isEnabled = function(name){
+ var value = abp.features.get(name);
+ return value == 'true' || value == 'True';
+ }
+
+ abp.features.get = function (name) {
+ return abp.features.values[name];
+ };
+
+ /* GLOBAL FEATURES *************************************************/
+
+ abp.globalFeatures = abp.globalFeatures || {};
+
+ abp.globalFeatures.enabledFeatures = abp.globalFeatures.enabledFeatures || [];
+
+ abp.globalFeatures.isEnabled = function(name){
+ return abp.globalFeatures.enabledFeatures.indexOf(name) != -1;
+ }
+
+})();
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js
new file mode 100644
index 0000000000..7dc3439da2
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js
@@ -0,0 +1,411 @@
+var abp = abp || {};
+(function($) {
+
+ if (!$) {
+ throw "abp/jquery library requires the jquery library included to the page!";
+ }
+
+ // ABP CORE OVERRIDES /////////////////////////////////////////////////////
+
+ abp.message._showMessage = function (message, title) {
+ alert((title || '') + ' ' + message);
+
+ return $.Deferred(function ($dfd) {
+ $dfd.resolve();
+ });
+ };
+
+ abp.message.confirm = function (message, titleOrCallback, callback) {
+ if (titleOrCallback && !(typeof titleOrCallback == 'string')) {
+ callback = titleOrCallback;
+ }
+
+ var result = confirm(message);
+ callback && callback(result);
+
+ return $.Deferred(function ($dfd) {
+ $dfd.resolve(result);
+ });
+ };
+
+ abp.utils.isFunction = function (obj) {
+ return $.isFunction(obj);
+ };
+
+ // JQUERY EXTENSIONS //////////////////////////////////////////////////////
+
+ $.fn.findWithSelf = function (selector) {
+ return this.filter(selector).add(this.find(selector));
+ };
+
+ // DOM ////////////////////////////////////////////////////////////////////
+
+ abp.dom = abp.dom || {};
+
+ abp.dom.onNodeAdded = function (callback) {
+ abp.event.on('abp.dom.nodeAdded', callback);
+ };
+
+ abp.dom.onNodeRemoved = function (callback) {
+ abp.event.on('abp.dom.nodeRemoved', callback);
+ };
+
+ var mutationObserverCallback = function (mutationsList) {
+ for (var i = 0; i < mutationsList.length; i++) {
+ var mutation = mutationsList[i];
+ if (mutation.type === 'childList') {
+ if (mutation.addedNodes && mutation.removedNodes.length) {
+ for (var k = 0; k < mutation.removedNodes.length; k++) {
+ abp.event.trigger(
+ 'abp.dom.nodeRemoved',
+ {
+ $el: $(mutation.removedNodes[k])
+ }
+ );
+ }
+ }
+
+ if (mutation.addedNodes && mutation.addedNodes.length) {
+ for (var j = 0; j < mutation.addedNodes.length; j++) {
+ abp.event.trigger(
+ 'abp.dom.nodeAdded',
+ {
+ $el: $(mutation.addedNodes[j])
+ }
+ );
+ }
+ }
+ }
+ }
+ };
+
+ $(function(){
+ new MutationObserver(mutationObserverCallback).observe(
+ $('body')[0],
+ {
+ subtree: true,
+ childList: true
+ }
+ );
+ });
+
+ // AJAX ///////////////////////////////////////////////////////////////////
+
+ abp.ajax = function (userOptions) {
+ userOptions = userOptions || {};
+
+ var options = $.extend(true, {}, abp.ajax.defaultOpts, userOptions);
+
+ options.success = undefined;
+ options.error = undefined;
+
+ var xhr = null;
+ var promise = $.Deferred(function ($dfd) {
+ xhr = $.ajax(options)
+ .done(function (data, textStatus, jqXHR) {
+ $dfd.resolve(data);
+ userOptions.success && userOptions.success(data);
+ }).fail(function (jqXHR) {
+ if(jqXHR.statusText === 'abort') {
+ //ajax request is abort, ignore error handle.
+ return;
+ }
+ if (jqXHR.getResponseHeader('_AbpErrorFormat') === 'true') {
+ abp.ajax.handleAbpErrorResponse(jqXHR, userOptions, $dfd);
+ } else {
+ abp.ajax.handleNonAbpErrorResponse(jqXHR, userOptions, $dfd);
+ }
+ });
+ }).promise();
+
+ promise['jqXHR'] = xhr;
+
+ return promise;
+ };
+
+ $.extend(abp.ajax, {
+ defaultOpts: {
+ dataType: 'json',
+ type: 'POST',
+ contentType: 'application/json',
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest'
+ }
+ },
+
+ defaultError: {
+ message: 'An error has occurred!',
+ details: 'Error detail not sent by server.'
+ },
+
+ defaultError401: {
+ message: 'You are not authenticated!',
+ details: 'You should be authenticated (sign in) in order to perform this operation.'
+ },
+
+ defaultError403: {
+ message: 'You are not authorized!',
+ details: 'You are not allowed to perform this operation.'
+ },
+
+ defaultError404: {
+ message: 'Resource not found!',
+ details: 'The resource requested could not found on the server.'
+ },
+
+ logError: function (error) {
+ abp.log.error(error);
+ },
+
+ showError: function (error) {
+ if (error.details) {
+ return abp.message.error(error.details, error.message);
+ } else {
+ return abp.message.error(error.message || abp.ajax.defaultError.message);
+ }
+ },
+
+ handleTargetUrl: function (targetUrl) {
+ if (!targetUrl) {
+ location.href = abp.appPath;
+ } else {
+ location.href = targetUrl;
+ }
+ },
+
+ handleErrorStatusCode: function (status) {
+ switch (status) {
+ case 401:
+ abp.ajax.handleUnAuthorizedRequest(
+ abp.ajax.showError(abp.ajax.defaultError401),
+ abp.appPath
+ );
+ break;
+ case 403:
+ abp.ajax.showError(abp.ajax.defaultError403);
+ break;
+ case 404:
+ abp.ajax.showError(abp.ajax.defaultError404);
+ break;
+ default:
+ abp.ajax.showError(abp.ajax.defaultError);
+ break;
+ }
+ },
+
+ handleNonAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
+ if (userOptions.abpHandleError !== false) {
+ abp.ajax.handleErrorStatusCode(jqXHR.status);
+ }
+
+ $dfd.reject.apply(this, arguments);
+ userOptions.error && userOptions.error.apply(this, arguments);
+ },
+
+ handleAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
+ var messagePromise = null;
+
+ var responseJSON = jqXHR.responseJSON ? jqXHR.responseJSON : JSON.parse(jqXHR.responseText);
+
+ if (userOptions.abpHandleError !== false) {
+ messagePromise = abp.ajax.showError(responseJSON.error);
+ }
+
+ abp.ajax.logError(responseJSON.error);
+
+ $dfd && $dfd.reject(responseJSON.error, jqXHR);
+ userOptions.error && userOptions.error(responseJSON.error, jqXHR);
+
+ if (jqXHR.status === 401 && userOptions.abpHandleError !== false) {
+ abp.ajax.handleUnAuthorizedRequest(messagePromise);
+ }
+ },
+
+ handleUnAuthorizedRequest: function (messagePromise, targetUrl) {
+ if (messagePromise) {
+ messagePromise.done(function () {
+ abp.ajax.handleTargetUrl(targetUrl);
+ });
+ } else {
+ abp.ajax.handleTargetUrl(targetUrl);
+ }
+ },
+
+ blockUI: function (options) {
+ if (options.blockUI) {
+ if (options.blockUI === true) { //block whole page
+ abp.ui.setBusy();
+ } else { //block an element
+ abp.ui.setBusy(options.blockUI);
+ }
+ }
+ },
+
+ unblockUI: function (options) {
+ if (options.blockUI) {
+ if (options.blockUI === true) { //unblock whole page
+ abp.ui.clearBusy();
+ } else { //unblock an element
+ abp.ui.clearBusy(options.blockUI);
+ }
+ }
+ },
+
+ ajaxSendHandler: function (event, request, settings) {
+ var token = abp.security.antiForgery.getToken();
+ if (!token) {
+ return;
+ }
+
+ if (!settings.headers || settings.headers[abp.security.antiForgery.tokenHeaderName] === undefined) {
+ request.setRequestHeader(abp.security.antiForgery.tokenHeaderName, token);
+ }
+ }
+ });
+
+ $(document).ajaxSend(function (event, request, settings) {
+ return abp.ajax.ajaxSendHandler(event, request, settings);
+ });
+
+ abp.event.on('abp.configurationInitialized', function () {
+ var l = abp.localization.getResource('AbpUi');
+
+ abp.ajax.defaultError.message = l('DefaultErrorMessage');
+ abp.ajax.defaultError.details = l('DefaultErrorMessageDetail');
+ abp.ajax.defaultError401.message = l('DefaultErrorMessage401');
+ abp.ajax.defaultError401.details = l('DefaultErrorMessage401Detail');
+ abp.ajax.defaultError403.message = l('DefaultErrorMessage403');
+ abp.ajax.defaultError403.details = l('DefaultErrorMessage403Detail');
+ abp.ajax.defaultError404.message = l('DefaultErrorMessage404');
+ abp.ajax.defaultError404.details = l('DefaultErrorMessage404Detail');
+ });
+
+ // RESOURCE LOADER ////////////////////////////////////////////////////////
+
+ /* UrlStates enum */
+ var UrlStates = {
+ LOADING: 'LOADING',
+ LOADED: 'LOADED',
+ FAILED: 'FAILED'
+ };
+
+ /* UrlInfo class */
+ function UrlInfo(url) {
+ this.url = url;
+ this.state = UrlStates.LOADING;
+ this.loadCallbacks = [];
+ this.failCallbacks = [];
+ }
+
+ UrlInfo.prototype.succeed = function () {
+ this.state = UrlStates.LOADED;
+ for (var i = 0; i < this.loadCallbacks.length; i++) {
+ this.loadCallbacks[i]();
+ }
+ };
+
+ UrlInfo.prototype.failed = function () {
+ this.state = UrlStates.FAILED;
+ for (var i = 0; i < this.failCallbacks.length; i++) {
+ this.failCallbacks[i]();
+ }
+ };
+
+ UrlInfo.prototype.handleCallbacks = function (loadCallback, failCallback) {
+ switch (this.state) {
+ case UrlStates.LOADED:
+ loadCallback && loadCallback();
+ break;
+ case UrlStates.FAILED:
+ failCallback && failCallback();
+ break;
+ case UrlStates.LOADING:
+ this.addCallbacks(loadCallback, failCallback);
+ break;
+ }
+ };
+
+ UrlInfo.prototype.addCallbacks = function (loadCallback, failCallback) {
+ loadCallback && this.loadCallbacks.push(loadCallback);
+ failCallback && this.failCallbacks.push(failCallback);
+ };
+
+ /* ResourceLoader API */
+
+ abp.ResourceLoader = (function () {
+
+ var _urlInfos = {};
+
+ function getCacheKey(url) {
+ return url;
+ }
+
+ function appendTimeToUrl(url) {
+
+ if (url.indexOf('?') < 0) {
+ url += '?';
+ } else {
+ url += '&';
+ }
+
+ url += '_=' + new Date().getTime();
+
+ return url;
+ }
+
+ var _loadFromUrl = function (url, loadCallback, failCallback, serverLoader) {
+
+ var cacheKey = getCacheKey(url);
+
+ var urlInfo = _urlInfos[cacheKey];
+
+ if (urlInfo) {
+ urlInfo.handleCallbacks(loadCallback, failCallback);
+ return;
+ }
+
+ _urlInfos[cacheKey] = urlInfo = new UrlInfo(url);
+ urlInfo.addCallbacks(loadCallback, failCallback);
+
+ serverLoader(urlInfo);
+ };
+
+ var _loadScript = function (url, loadCallback, failCallback) {
+ var nonce = document.body.nonce || document.body.getAttribute('nonce');
+ _loadFromUrl(url, loadCallback, failCallback, function (urlInfo) {
+ $.get({
+ url: url,
+ dataType: 'text'
+ })
+ .done(function (script) {
+ if(nonce){
+ $.globalEval(script, { nonce: nonce});
+ }else{
+ $.globalEval(script);
+ }
+ urlInfo.succeed();
+ })
+ .fail(function () {
+ urlInfo.failed();
+ });
+ });
+ };
+
+ var _loadStyle = function (url) {
+ _loadFromUrl(url, undefined, undefined, function (urlInfo) {
+
+ $('', {
+ rel: 'stylesheet',
+ type: 'text/css',
+ href: appendTimeToUrl(url)
+ }).appendTo('head');
+ });
+ };
+
+ return {
+ loadScript: _loadScript,
+ loadStyle: _loadStyle
+ }
+ })();
+
+})(jQuery);
\ No newline at end of file
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js
new file mode 100644
index 0000000000..b04de7cadf
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js
@@ -0,0 +1,46 @@
+var abp = abp || {};
+(function () {
+
+ if (!luxon) {
+ throw "abp/luxon library requires the luxon library included to the page!";
+ }
+
+ /* TIMING *************************************************/
+
+ abp.timing = abp.timing || {};
+
+ var setObjectValue = function (obj, property, value) {
+ if (typeof property === "string") {
+ property = property.split('.');
+ }
+
+ if (property.length > 1) {
+ var p = property.shift();
+ setObjectValue(obj[p], property, value);
+ } else {
+ obj[property[0]] = value;
+ }
+ }
+
+ var getObjectValue = function (obj, property) {
+ return property.split('.').reduce((a, v) => a[v], obj)
+ }
+
+ abp.timing.convertFieldsToIsoDate = function (form, fields) {
+ for (var field of fields) {
+ var dateTime = luxon.DateTime
+ .fromFormat(
+ getObjectValue(form, field),
+ abp.localization.currentCulture.dateTimeFormat.shortDatePattern,
+ {locale: abp.localization.currentCulture.cultureName}
+ );
+
+ if (!dateTime.invalid) {
+ setObjectValue(form, field, dateTime.toFormat("yyyy-MM-dd HH:mm:ss"))
+ }
+ }
+
+ return form;
+ }
+
+})(jQuery);
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js
new file mode 100644
index 0000000000..28ebcc3765
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js
@@ -0,0 +1,694 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('just-compare')) :
+ typeof define === 'function' && define.amd ? define('@abp/utils', ['exports', 'just-compare'], factory) :
+ (global = global || self, factory((global.abp = global.abp || {}, global.abp.utils = global.abp.utils || {}, global.abp.utils.common = {}), global.compare));
+}(this, (function (exports, compare) { 'use strict';
+
+ compare = compare && Object.prototype.hasOwnProperty.call(compare, 'default') ? compare['default'] : compare;
+
+ /*! *****************************************************************************
+ Copyright (c) Microsoft Corporation.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ PERFORMANCE OF THIS SOFTWARE.
+ ***************************************************************************** */
+ /* global Reflect, Promise */
+ var extendStatics = function (d, b) {
+ extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b)
+ if (b.hasOwnProperty(p))
+ d[p] = b[p]; };
+ return extendStatics(d, b);
+ };
+ function __extends(d, b) {
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+ }
+ var __assign = function () {
+ __assign = Object.assign || function __assign(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s)
+ if (Object.prototype.hasOwnProperty.call(s, p))
+ t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+ };
+ function __rest(s, e) {
+ var t = {};
+ for (var p in s)
+ if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
+ t[p] = s[p];
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
+ t[p[i]] = s[p[i]];
+ }
+ return t;
+ }
+ function __decorate(decorators, target, key, desc) {
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
+ r = Reflect.decorate(decorators, target, key, desc);
+ else
+ for (var i = decorators.length - 1; i >= 0; i--)
+ if (d = decorators[i])
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
+ }
+ function __param(paramIndex, decorator) {
+ return function (target, key) { decorator(target, key, paramIndex); };
+ }
+ function __metadata(metadataKey, metadataValue) {
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
+ return Reflect.metadata(metadataKey, metadataValue);
+ }
+ function __awaiter(thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try {
+ step(generator.next(value));
+ }
+ catch (e) {
+ reject(e);
+ } }
+ function rejected(value) { try {
+ step(generator["throw"](value));
+ }
+ catch (e) {
+ reject(e);
+ } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+ }
+ function __generator(thisArg, body) {
+ var _ = { label: 0, sent: function () { if (t[0] & 1)
+ throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f)
+ throw new TypeError("Generator is already executing.");
+ while (_)
+ try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
+ return t;
+ if (y = 0, t)
+ op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0:
+ case 1:
+ t = op;
+ break;
+ case 4:
+ _.label++;
+ return { value: op[1], done: false };
+ case 5:
+ _.label++;
+ y = op[1];
+ op = [0];
+ continue;
+ case 7:
+ op = _.ops.pop();
+ _.trys.pop();
+ continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
+ _ = 0;
+ continue;
+ }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
+ _.label = op[1];
+ break;
+ }
+ if (op[0] === 6 && _.label < t[1]) {
+ _.label = t[1];
+ t = op;
+ break;
+ }
+ if (t && _.label < t[2]) {
+ _.label = t[2];
+ _.ops.push(op);
+ break;
+ }
+ if (t[2])
+ _.ops.pop();
+ _.trys.pop();
+ continue;
+ }
+ op = body.call(thisArg, _);
+ }
+ catch (e) {
+ op = [6, e];
+ y = 0;
+ }
+ finally {
+ f = t = 0;
+ }
+ if (op[0] & 5)
+ throw op[1];
+ return { value: op[0] ? op[1] : void 0, done: true };
+ }
+ }
+ var __createBinding = Object.create ? (function (o, m, k, k2) {
+ if (k2 === undefined)
+ k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
+ }) : (function (o, m, k, k2) {
+ if (k2 === undefined)
+ k2 = k;
+ o[k2] = m[k];
+ });
+ function __exportStar(m, exports) {
+ for (var p in m)
+ if (p !== "default" && !exports.hasOwnProperty(p))
+ __createBinding(exports, m, p);
+ }
+ function __values(o) {
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
+ if (m)
+ return m.call(o);
+ if (o && typeof o.length === "number")
+ return {
+ next: function () {
+ if (o && i >= o.length)
+ o = void 0;
+ return { value: o && o[i++], done: !o };
+ }
+ };
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
+ }
+ function __read(o, n) {
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
+ if (!m)
+ return o;
+ var i = m.call(o), r, ar = [], e;
+ try {
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
+ ar.push(r.value);
+ }
+ catch (error) {
+ e = { error: error };
+ }
+ finally {
+ try {
+ if (r && !r.done && (m = i["return"]))
+ m.call(i);
+ }
+ finally {
+ if (e)
+ throw e.error;
+ }
+ }
+ return ar;
+ }
+ function __spread() {
+ for (var ar = [], i = 0; i < arguments.length; i++)
+ ar = ar.concat(__read(arguments[i]));
+ return ar;
+ }
+ function __spreadArrays() {
+ for (var s = 0, i = 0, il = arguments.length; i < il; i++)
+ s += arguments[i].length;
+ for (var r = Array(s), k = 0, i = 0; i < il; i++)
+ for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
+ r[k] = a[j];
+ return r;
+ }
+ ;
+ function __await(v) {
+ return this instanceof __await ? (this.v = v, this) : new __await(v);
+ }
+ function __asyncGenerator(thisArg, _arguments, generator) {
+ if (!Symbol.asyncIterator)
+ throw new TypeError("Symbol.asyncIterator is not defined.");
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
+ return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
+ function verb(n) { if (g[n])
+ i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
+ function resume(n, v) { try {
+ step(g[n](v));
+ }
+ catch (e) {
+ settle(q[0][3], e);
+ } }
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
+ function fulfill(value) { resume("next", value); }
+ function reject(value) { resume("throw", value); }
+ function settle(f, v) { if (f(v), q.shift(), q.length)
+ resume(q[0][0], q[0][1]); }
+ }
+ function __asyncDelegator(o) {
+ var i, p;
+ return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
+ function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
+ }
+ function __asyncValues(o) {
+ if (!Symbol.asyncIterator)
+ throw new TypeError("Symbol.asyncIterator is not defined.");
+ var m = o[Symbol.asyncIterator], i;
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
+ }
+ function __makeTemplateObject(cooked, raw) {
+ if (Object.defineProperty) {
+ Object.defineProperty(cooked, "raw", { value: raw });
+ }
+ else {
+ cooked.raw = raw;
+ }
+ return cooked;
+ }
+ ;
+ var __setModuleDefault = Object.create ? (function (o, v) {
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
+ }) : function (o, v) {
+ o["default"] = v;
+ };
+ function __importStar(mod) {
+ if (mod && mod.__esModule)
+ return mod;
+ var result = {};
+ if (mod != null)
+ for (var k in mod)
+ if (Object.hasOwnProperty.call(mod, k))
+ __createBinding(result, mod, k);
+ __setModuleDefault(result, mod);
+ return result;
+ }
+ function __importDefault(mod) {
+ return (mod && mod.__esModule) ? mod : { default: mod };
+ }
+ function __classPrivateFieldGet(receiver, privateMap) {
+ if (!privateMap.has(receiver)) {
+ throw new TypeError("attempted to get private field on non-instance");
+ }
+ return privateMap.get(receiver);
+ }
+ function __classPrivateFieldSet(receiver, privateMap, value) {
+ if (!privateMap.has(receiver)) {
+ throw new TypeError("attempted to set private field on non-instance");
+ }
+ privateMap.set(receiver, value);
+ return value;
+ }
+
+ var ListNode = /** @class */ (function () {
+ function ListNode(value) {
+ this.value = value;
+ }
+ return ListNode;
+ }());
+ var LinkedList = /** @class */ (function () {
+ function LinkedList() {
+ this.size = 0;
+ }
+ Object.defineProperty(LinkedList.prototype, "head", {
+ get: function () {
+ return this.first;
+ },
+ enumerable: false,
+ configurable: true
+ });
+ Object.defineProperty(LinkedList.prototype, "tail", {
+ get: function () {
+ return this.last;
+ },
+ enumerable: false,
+ configurable: true
+ });
+ Object.defineProperty(LinkedList.prototype, "length", {
+ get: function () {
+ return this.size;
+ },
+ enumerable: false,
+ configurable: true
+ });
+ LinkedList.prototype.attach = function (value, previousNode, nextNode) {
+ if (!previousNode)
+ return this.addHead(value);
+ if (!nextNode)
+ return this.addTail(value);
+ var node = new ListNode(value);
+ node.previous = previousNode;
+ previousNode.next = node;
+ node.next = nextNode;
+ nextNode.previous = node;
+ this.size++;
+ return node;
+ };
+ LinkedList.prototype.attachMany = function (values, previousNode, nextNode) {
+ if (!values.length)
+ return [];
+ if (!previousNode)
+ return this.addManyHead(values);
+ if (!nextNode)
+ return this.addManyTail(values);
+ var list = new LinkedList();
+ list.addManyTail(values);
+ list.first.previous = previousNode;
+ previousNode.next = list.first;
+ list.last.next = nextNode;
+ nextNode.previous = list.last;
+ this.size += values.length;
+ return list.toNodeArray();
+ };
+ LinkedList.prototype.detach = function (node) {
+ if (!node.previous)
+ return this.dropHead();
+ if (!node.next)
+ return this.dropTail();
+ node.previous.next = node.next;
+ node.next.previous = node.previous;
+ this.size--;
+ return node;
+ };
+ LinkedList.prototype.add = function (value) {
+ var _this = this;
+ return {
+ after: function () {
+ var _a;
+ var params = [];
+ for (var _i = 0; _i < arguments.length; _i++) {
+ params[_i] = arguments[_i];
+ }
+ return (_a = _this.addAfter).call.apply(_a, __spread([_this, value], params));
+ },
+ before: function () {
+ var _a;
+ var params = [];
+ for (var _i = 0; _i < arguments.length; _i++) {
+ params[_i] = arguments[_i];
+ }
+ return (_a = _this.addBefore).call.apply(_a, __spread([_this, value], params));
+ },
+ byIndex: function (position) { return _this.addByIndex(value, position); },
+ head: function () { return _this.addHead(value); },
+ tail: function () { return _this.addTail(value); },
+ };
+ };
+ LinkedList.prototype.addMany = function (values) {
+ var _this = this;
+ return {
+ after: function () {
+ var _a;
+ var params = [];
+ for (var _i = 0; _i < arguments.length; _i++) {
+ params[_i] = arguments[_i];
+ }
+ return (_a = _this.addManyAfter).call.apply(_a, __spread([_this, values], params));
+ },
+ before: function () {
+ var _a;
+ var params = [];
+ for (var _i = 0; _i < arguments.length; _i++) {
+ params[_i] = arguments[_i];
+ }
+ return (_a = _this.addManyBefore).call.apply(_a, __spread([_this, values], params));
+ },
+ byIndex: function (position) { return _this.addManyByIndex(values, position); },
+ head: function () { return _this.addManyHead(values); },
+ tail: function () { return _this.addManyTail(values); },
+ };
+ };
+ LinkedList.prototype.addAfter = function (value, previousValue, compareFn) {
+ if (compareFn === void 0) { compareFn = compare; }
+ var previous = this.find(function (node) { return compareFn(node.value, previousValue); });
+ return previous ? this.attach(value, previous, previous.next) : this.addTail(value);
+ };
+ LinkedList.prototype.addBefore = function (value, nextValue, compareFn) {
+ if (compareFn === void 0) { compareFn = compare; }
+ var next = this.find(function (node) { return compareFn(node.value, nextValue); });
+ return next ? this.attach(value, next.previous, next) : this.addHead(value);
+ };
+ LinkedList.prototype.addByIndex = function (value, position) {
+ if (position < 0)
+ position += this.size;
+ else if (position >= this.size)
+ return this.addTail(value);
+ if (position <= 0)
+ return this.addHead(value);
+ var next = this.get(position);
+ return this.attach(value, next.previous, next);
+ };
+ LinkedList.prototype.addHead = function (value) {
+ var node = new ListNode(value);
+ node.next = this.first;
+ if (this.first)
+ this.first.previous = node;
+ else
+ this.last = node;
+ this.first = node;
+ this.size++;
+ return node;
+ };
+ LinkedList.prototype.addTail = function (value) {
+ var node = new ListNode(value);
+ if (this.first) {
+ node.previous = this.last;
+ this.last.next = node;
+ this.last = node;
+ }
+ else {
+ this.first = node;
+ this.last = node;
+ }
+ this.size++;
+ return node;
+ };
+ LinkedList.prototype.addManyAfter = function (values, previousValue, compareFn) {
+ if (compareFn === void 0) { compareFn = compare; }
+ var previous = this.find(function (node) { return compareFn(node.value, previousValue); });
+ return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values);
+ };
+ LinkedList.prototype.addManyBefore = function (values, nextValue, compareFn) {
+ if (compareFn === void 0) { compareFn = compare; }
+ var next = this.find(function (node) { return compareFn(node.value, nextValue); });
+ return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values);
+ };
+ LinkedList.prototype.addManyByIndex = function (values, position) {
+ if (position < 0)
+ position += this.size;
+ if (position <= 0)
+ return this.addManyHead(values);
+ if (position >= this.size)
+ return this.addManyTail(values);
+ var next = this.get(position);
+ return this.attachMany(values, next.previous, next);
+ };
+ LinkedList.prototype.addManyHead = function (values) {
+ var _this = this;
+ return values.reduceRight(function (nodes, value) {
+ nodes.unshift(_this.addHead(value));
+ return nodes;
+ }, []);
+ };
+ LinkedList.prototype.addManyTail = function (values) {
+ var _this = this;
+ return values.map(function (value) { return _this.addTail(value); });
+ };
+ LinkedList.prototype.drop = function () {
+ var _this = this;
+ return {
+ byIndex: function (position) { return _this.dropByIndex(position); },
+ byValue: function () {
+ var params = [];
+ for (var _i = 0; _i < arguments.length; _i++) {
+ params[_i] = arguments[_i];
+ }
+ return _this.dropByValue.apply(_this, params);
+ },
+ byValueAll: function () {
+ var params = [];
+ for (var _i = 0; _i < arguments.length; _i++) {
+ params[_i] = arguments[_i];
+ }
+ return _this.dropByValueAll.apply(_this, params);
+ },
+ head: function () { return _this.dropHead(); },
+ tail: function () { return _this.dropTail(); },
+ };
+ };
+ LinkedList.prototype.dropMany = function (count) {
+ var _this = this;
+ return {
+ byIndex: function (position) { return _this.dropManyByIndex(count, position); },
+ head: function () { return _this.dropManyHead(count); },
+ tail: function () { return _this.dropManyTail(count); },
+ };
+ };
+ LinkedList.prototype.dropByIndex = function (position) {
+ if (position < 0)
+ position += this.size;
+ var current = this.get(position);
+ return current ? this.detach(current) : undefined;
+ };
+ LinkedList.prototype.dropByValue = function (value, compareFn) {
+ if (compareFn === void 0) { compareFn = compare; }
+ var position = this.findIndex(function (node) { return compareFn(node.value, value); });
+ return position < 0 ? undefined : this.dropByIndex(position);
+ };
+ LinkedList.prototype.dropByValueAll = function (value, compareFn) {
+ if (compareFn === void 0) { compareFn = compare; }
+ var dropped = [];
+ for (var current = this.first, position = 0; current; position++, current = current.next) {
+ if (compareFn(current.value, value)) {
+ dropped.push(this.dropByIndex(position - dropped.length));
+ }
+ }
+ return dropped;
+ };
+ LinkedList.prototype.dropHead = function () {
+ var head = this.first;
+ if (head) {
+ this.first = head.next;
+ if (this.first)
+ this.first.previous = undefined;
+ else
+ this.last = undefined;
+ this.size--;
+ return head;
+ }
+ return undefined;
+ };
+ LinkedList.prototype.dropTail = function () {
+ var tail = this.last;
+ if (tail) {
+ this.last = tail.previous;
+ if (this.last)
+ this.last.next = undefined;
+ else
+ this.first = undefined;
+ this.size--;
+ return tail;
+ }
+ return undefined;
+ };
+ LinkedList.prototype.dropManyByIndex = function (count, position) {
+ if (count <= 0)
+ return [];
+ if (position < 0)
+ position = Math.max(position + this.size, 0);
+ else if (position >= this.size)
+ return [];
+ count = Math.min(count, this.size - position);
+ var dropped = [];
+ while (count--) {
+ var current = this.get(position);
+ dropped.push(this.detach(current));
+ }
+ return dropped;
+ };
+ LinkedList.prototype.dropManyHead = function (count) {
+ if (count <= 0)
+ return [];
+ count = Math.min(count, this.size);
+ var dropped = [];
+ while (count--)
+ dropped.unshift(this.dropHead());
+ return dropped;
+ };
+ LinkedList.prototype.dropManyTail = function (count) {
+ if (count <= 0)
+ return [];
+ count = Math.min(count, this.size);
+ var dropped = [];
+ while (count--)
+ dropped.push(this.dropTail());
+ return dropped;
+ };
+ LinkedList.prototype.find = function (predicate) {
+ for (var current = this.first, position = 0; current; position++, current = current.next) {
+ if (predicate(current, position, this))
+ return current;
+ }
+ return undefined;
+ };
+ LinkedList.prototype.findIndex = function (predicate) {
+ for (var current = this.first, position = 0; current; position++, current = current.next) {
+ if (predicate(current, position, this))
+ return position;
+ }
+ return -1;
+ };
+ LinkedList.prototype.forEach = function (iteratorFn) {
+ for (var node = this.first, position = 0; node; position++, node = node.next) {
+ iteratorFn(node, position, this);
+ }
+ };
+ LinkedList.prototype.get = function (position) {
+ return this.find(function (_, index) { return position === index; });
+ };
+ LinkedList.prototype.indexOf = function (value, compareFn) {
+ if (compareFn === void 0) { compareFn = compare; }
+ return this.findIndex(function (node) { return compareFn(node.value, value); });
+ };
+ LinkedList.prototype.toArray = function () {
+ var array = new Array(this.size);
+ this.forEach(function (node, index) { return (array[index] = node.value); });
+ return array;
+ };
+ LinkedList.prototype.toNodeArray = function () {
+ var array = new Array(this.size);
+ this.forEach(function (node, index) { return (array[index] = node); });
+ return array;
+ };
+ LinkedList.prototype.toString = function (mapperFn) {
+ if (mapperFn === void 0) { mapperFn = JSON.stringify; }
+ return this.toArray()
+ .map(function (value) { return mapperFn(value); })
+ .join(' <-> ');
+ };
+ // Cannot use Generator type because of ng-packagr
+ LinkedList.prototype[Symbol.iterator] = function () {
+ var node, position;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ node = this.first, position = 0;
+ _a.label = 1;
+ case 1:
+ if (!node) return [3 /*break*/, 4];
+ return [4 /*yield*/, node.value];
+ case 2:
+ _a.sent();
+ _a.label = 3;
+ case 3:
+ position++, node = node.next;
+ return [3 /*break*/, 1];
+ case 4: return [2 /*return*/];
+ }
+ });
+ };
+ return LinkedList;
+ }());
+
+ /*
+ * Public API Surface of utils
+ */
+
+ /**
+ * Generated bundle index. Do not edit.
+ */
+
+ exports.LinkedList = LinkedList;
+ exports.ListNode = ListNode;
+
+ Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
+//# sourceMappingURL=abp-utils.umd.js.map
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map
new file mode 100644
index 0000000000..c8cf999f3b
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"abp-utils.umd.js","sources":["../../node_modules/tslib/tslib.es6.js","../../projects/utils/src/lib/linked-list.ts","../../projects/utils/src/public-api.ts","../../projects/utils/src/abp-utils.ts"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (p !== \"default\" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/* tslint:disable:no-non-null-assertion */\r\n\r\nimport compare from 'just-compare';\r\n\r\nexport class ListNode {\r\n next: ListNode | undefined;\r\n previous: ListNode | undefined;\r\n constructor(public readonly value: T) {}\r\n}\r\n\r\nexport class LinkedList {\r\n private first: ListNode | undefined;\r\n private last: ListNode | undefined;\r\n private size = 0;\r\n\r\n get head(): ListNode | undefined {\r\n return this.first;\r\n }\r\n get tail(): ListNode | undefined {\r\n return this.last;\r\n }\r\n get length(): number {\r\n return this.size;\r\n }\r\n\r\n private attach(\r\n value: T,\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode {\r\n if (!previousNode) return this.addHead(value);\r\n\r\n if (!nextNode) return this.addTail(value);\r\n\r\n const node = new ListNode(value);\r\n node.previous = previousNode;\r\n previousNode.next = node;\r\n node.next = nextNode;\r\n nextNode.previous = node;\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n private attachMany(\r\n values: T[],\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode[] {\r\n if (!values.length) return [];\r\n\r\n if (!previousNode) return this.addManyHead(values);\r\n\r\n if (!nextNode) return this.addManyTail(values);\r\n\r\n const list = new LinkedList();\r\n list.addManyTail(values);\r\n list.first!.previous = previousNode;\r\n previousNode.next = list.first;\r\n list.last!.next = nextNode;\r\n nextNode.previous = list.last;\r\n\r\n this.size += values.length;\r\n\r\n return list.toNodeArray();\r\n }\r\n\r\n private detach(node: ListNode) {\r\n if (!node.previous) return this.dropHead();\r\n\r\n if (!node.next) return this.dropTail();\r\n\r\n node.previous.next = node.next;\r\n node.next.previous = node.previous;\r\n\r\n this.size--;\r\n\r\n return node;\r\n }\r\n\r\n add(value: T) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addAfter.call(this, value, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addBefore.call(this, value, ...params),\r\n byIndex: (position: number) => this.addByIndex(value, position),\r\n head: () => this.addHead(value),\r\n tail: () => this.addTail(value),\r\n };\r\n }\r\n\r\n addMany(values: T[]) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyAfter.call(this, values, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyBefore.call(this, values, ...params),\r\n byIndex: (position: number) => this.addManyByIndex(values, position),\r\n head: () => this.addManyHead(values),\r\n tail: () => this.addManyTail(values),\r\n };\r\n }\r\n\r\n addAfter(value: T, previousValue: T): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attach(value, previous, previous.next) : this.addTail(value);\r\n }\r\n\r\n addBefore(value: T, nextValue: T): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attach(value, next.previous, next) : this.addHead(value);\r\n }\r\n\r\n addByIndex(value: T, position: number): ListNode {\r\n if (position < 0) position += this.size;\r\n else if (position >= this.size) return this.addTail(value);\r\n\r\n if (position <= 0) return this.addHead(value);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attach(value, next.previous, next);\r\n }\r\n\r\n addHead(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n node.next = this.first;\r\n\r\n if (this.first) this.first.previous = node;\r\n else this.last = node;\r\n\r\n this.first = node;\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addTail(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n if (this.first) {\r\n node.previous = this.last;\r\n this.last!.next = node;\r\n this.last = node;\r\n } else {\r\n this.first = node;\r\n this.last = node;\r\n }\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addManyAfter(values: T[], previousValue: T): ListNode[];\r\n addManyAfter(values: T[], previousValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyAfter(\r\n values: T[],\r\n previousValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values);\r\n }\r\n\r\n addManyBefore(values: T[], nextValue: T): ListNode[];\r\n addManyBefore(values: T[], nextValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyBefore(\r\n values: T[],\r\n nextValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values);\r\n }\r\n\r\n addManyByIndex(values: T[], position: number): ListNode[] {\r\n if (position < 0) position += this.size;\r\n\r\n if (position <= 0) return this.addManyHead(values);\r\n\r\n if (position >= this.size) return this.addManyTail(values);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attachMany(values, next.previous, next);\r\n }\r\n\r\n addManyHead(values: T[]): ListNode[] {\r\n return values.reduceRight[]>((nodes, value) => {\r\n nodes.unshift(this.addHead(value));\r\n return nodes;\r\n }, []);\r\n }\r\n\r\n addManyTail(values: T[]): ListNode[] {\r\n return values.map(value => this.addTail(value));\r\n }\r\n\r\n drop() {\r\n return {\r\n byIndex: (position: number) => this.dropByIndex(position),\r\n byValue: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValue.apply(this, params),\r\n byValueAll: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValueAll.apply(this, params),\r\n head: () => this.dropHead(),\r\n tail: () => this.dropTail(),\r\n };\r\n }\r\n\r\n dropMany(count: number) {\r\n return {\r\n byIndex: (position: number) => this.dropManyByIndex(count, position),\r\n head: () => this.dropManyHead(count),\r\n tail: () => this.dropManyTail(count),\r\n };\r\n }\r\n\r\n dropByIndex(position: number): ListNode | undefined {\r\n if (position < 0) position += this.size;\r\n\r\n const current = this.get(position);\r\n\r\n return current ? this.detach(current) : undefined;\r\n }\r\n\r\n dropByValue(value: T): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn = compare): ListNode | undefined {\r\n const position = this.findIndex(node => compareFn(node.value, value));\r\n\r\n return position < 0 ? undefined : this.dropByIndex(position);\r\n }\r\n\r\n dropByValueAll(value: T): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn = compare): ListNode[] {\r\n const dropped: ListNode[] = [];\r\n\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (compareFn(current.value, value)) {\r\n dropped.push(this.dropByIndex(position - dropped.length)!);\r\n }\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropHead(): ListNode | undefined {\r\n const head = this.first;\r\n\r\n if (head) {\r\n this.first = head.next;\r\n\r\n if (this.first) this.first.previous = undefined;\r\n else this.last = undefined;\r\n\r\n this.size--;\r\n\r\n return head;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropTail(): ListNode | undefined {\r\n const tail = this.last;\r\n\r\n if (tail) {\r\n this.last = tail.previous;\r\n\r\n if (this.last) this.last.next = undefined;\r\n else this.first = undefined;\r\n\r\n this.size--;\r\n\r\n return tail;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropManyByIndex(count: number, position: number): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n if (position < 0) position = Math.max(position + this.size, 0);\r\n else if (position >= this.size) return [];\r\n\r\n count = Math.min(count, this.size - position);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) {\r\n const current = this.get(position);\r\n dropped.push(this.detach(current!)!);\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyHead(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.unshift(this.dropHead()!);\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyTail(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.push(this.dropTail()!);\r\n\r\n return dropped;\r\n }\r\n\r\n find(predicate: ListIteratorFn): ListNode | undefined {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return current;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n findIndex(predicate: ListIteratorFn): number {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return position;\r\n }\r\n\r\n return -1;\r\n }\r\n\r\n forEach(iteratorFn: ListIteratorFn) {\r\n for (let node = this.first, position = 0; node; position++, node = node.next) {\r\n iteratorFn(node, position, this);\r\n }\r\n }\r\n\r\n get(position: number): ListNode | undefined {\r\n return this.find((_, index) => position === index);\r\n }\r\n\r\n indexOf(value: T): number;\r\n indexOf(value: any, compareFn: ListComparisonFn): number;\r\n indexOf(value: any, compareFn: ListComparisonFn = compare): number {\r\n return this.findIndex(node => compareFn(node.value, value));\r\n }\r\n\r\n toArray(): T[] {\r\n const array = new Array(this.size);\r\n\r\n this.forEach((node, index) => (array[index!] = node.value));\r\n\r\n return array;\r\n }\r\n\r\n toNodeArray(): ListNode[] {\r\n const array = new Array(this.size);\r\n\r\n this.forEach((node, index) => (array[index!] = node));\r\n\r\n return array;\r\n }\r\n\r\n toString(mapperFn: ListMapperFn = JSON.stringify): string {\r\n return this.toArray()\r\n .map(value => mapperFn(value))\r\n .join(' <-> ');\r\n }\r\n\r\n // Cannot use Generator type because of ng-packagr\r\n *[Symbol.iterator](): any {\r\n for (let node = this.first, position = 0; node; position++, node = node.next) {\r\n yield node.value;\r\n }\r\n }\r\n}\r\n\r\nexport type ListMapperFn = (value: T) => any;\r\n\r\nexport type ListComparisonFn = (value1: T, value2: any) => boolean;\r\n\r\nexport type ListIteratorFn = (\r\n node: ListNode,\r\n index?: number,\r\n list?: LinkedList,\r\n) => R;\r\n","/*\r\n * Public API Surface of utils\r\n */\r\n\r\nexport * from './lib/linked-list';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js
new file mode 100644
index 0000000000..57b22e5188
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js
@@ -0,0 +1,2 @@
+!function(t,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("just-compare")):"function"==typeof define&&define.amd?define("@abp/utils",["exports","just-compare"],r):r(((t=t||self).abp=t.abp||{},t.abp.utils=t.abp.utils||{},t.abp.utils.common={}),t.compare)}(this,(function(t,r){"use strict";r=r&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r;function e(t,r){var e,n,i,o,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function u(o){return function(u){return function(o){if(e)throw new TypeError("Generator is already executing.");for(;a;)try{if(e=1,n&&(i=2&o[0]?n.return:o[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,o[1])).done)return i;switch(n=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,n=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(i=a.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0)&&!(n=o.next()).done;)a.push(n.value)}catch(t){i={error:t}}finally{try{n&&!n.done&&(e=o.return)&&e.call(o)}finally{if(i)throw i.error}}return a}function i(){for(var t=[],r=0;r=this.size)return this.addTail(t);if(r<=0)return this.addHead(t);var e=this.get(r);return this.attach(t,e.previous,e)},t.prototype.addHead=function(t){var r=new o(t);return r.next=this.first,this.first?this.first.previous=r:this.last=r,this.first=r,this.size++,r},t.prototype.addTail=function(t){var r=new o(t);return this.first?(r.previous=this.last,this.last.next=r,this.last=r):(this.first=r,this.last=r),this.size++,r},t.prototype.addManyAfter=function(t,e,n){void 0===n&&(n=r);var i=this.find((function(t){return n(t.value,e)}));return i?this.attachMany(t,i,i.next):this.addManyTail(t)},t.prototype.addManyBefore=function(t,e,n){void 0===n&&(n=r);var i=this.find((function(t){return n(t.value,e)}));return i?this.attachMany(t,i.previous,i):this.addManyHead(t)},t.prototype.addManyByIndex=function(t,r){if(r<0&&(r+=this.size),r<=0)return this.addManyHead(t);if(r>=this.size)return this.addManyTail(t);var e=this.get(r);return this.attachMany(t,e.previous,e)},t.prototype.addManyHead=function(t){var r=this;return t.reduceRight((function(t,e){return t.unshift(r.addHead(e)),t}),[])},t.prototype.addManyTail=function(t){var r=this;return t.map((function(t){return r.addTail(t)}))},t.prototype.drop=function(){var t=this;return{byIndex:function(r){return t.dropByIndex(r)},byValue:function(){for(var r=[],e=0;e=this.size)return[];t=Math.min(t,this.size-r);for(var e=[];t--;){var n=this.get(r);e.push(this.detach(n))}return e},t.prototype.dropManyHead=function(t){if(t<=0)return[];t=Math.min(t,this.size);for(var r=[];t--;)r.unshift(this.dropHead());return r},t.prototype.dropManyTail=function(t){if(t<=0)return[];t=Math.min(t,this.size);for(var r=[];t--;)r.push(this.dropTail());return r},t.prototype.find=function(t){for(var r=this.first,e=0;r;e++,r=r.next)if(t(r,e,this))return r},t.prototype.findIndex=function(t){for(var r=this.first,e=0;r;e++,r=r.next)if(t(r,e,this))return e;return-1},t.prototype.forEach=function(t){for(var r=this.first,e=0;r;e++,r=r.next)t(r,e,this)},t.prototype.get=function(t){return this.find((function(r,e){return t===e}))},t.prototype.indexOf=function(t,e){return void 0===e&&(e=r),this.findIndex((function(r){return e(r.value,t)}))},t.prototype.toArray=function(){var t=new Array(this.size);return this.forEach((function(r,e){return t[e]=r.value})),t},t.prototype.toNodeArray=function(){var t=new Array(this.size);return this.forEach((function(r,e){return t[e]=r})),t},t.prototype.toString=function(t){return void 0===t&&(t=JSON.stringify),this.toArray().map((function(r){return t(r)})).join(" <-> ")},t.prototype[Symbol.iterator]=function(){var t;return e(this,(function(r){switch(r.label){case 0:t=this.first,0,r.label=1;case 1:return t?[4,t.value]:[3,4];case 2:r.sent(),r.label=3;case 3:return t=t.next,[3,1];case 4:return[2]}}))},t}();t.LinkedList=a,t.ListNode=o,Object.defineProperty(t,"__esModule",{value:!0})}));
+//# sourceMappingURL=abp-utils.umd.min.js.map
\ No newline at end of file
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map
new file mode 100644
index 0000000000..529ba4c447
--- /dev/null
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../node_modules/tslib/tslib.es6.js","../../projects/utils/src/lib/linked-list.ts"],"names":["__generator","thisArg","body","f","y","t","g","_","label","sent","trys","ops","next","verb","throw","return","Symbol","iterator","this","n","v","op","TypeError","call","done","value","pop","length","push","e","step","Object","create","__read","o","m","r","i","ar","error","__spread","arguments","concat","LinkedList","size","defineProperty","prototype","first","last","attach","previousNode","nextNode","addHead","addTail","node","ListNode","previous","attachMany","values","addManyHead","addManyTail","list","toNodeArray","detach","dropTail","dropHead","add","_this","after","params","_i","_a","addAfter","apply","before","addBefore","byIndex","position","addByIndex","head","tail","addMany","addManyAfter","addManyBefore","addManyByIndex","previousValue","compareFn","compare","find","nextValue","get","reduceRight","nodes","unshift","map","drop","dropByIndex","byValue","dropByValue","byValueAll","dropByValueAll","dropMany","count","dropManyByIndex","dropManyHead","dropManyTail","current","undefined","findIndex","dropped","Math","max","min","predicate","forEach","iteratorFn","index","indexOf","toArray","array","Array","toString","mapperFn","JSON","stringify","join"],"mappings":"wYA6EgBA,EAAYC,EAASC,GACjC,IAAsGC,EAAGC,EAAGC,EAAGC,EAA3GC,EAAI,CAAEC,MAAO,EAAGC,KAAM,WAAa,GAAW,EAAPJ,EAAE,GAAQ,MAAMA,EAAE,GAAI,OAAOA,EAAE,IAAOK,KAAM,GAAIC,IAAK,IAChG,OAAOL,EAAI,CAAEM,KAAMC,EAAK,GAAIC,MAASD,EAAK,GAAIE,OAAUF,EAAK,IAAwB,mBAAXG,SAA0BV,EAAEU,OAAOC,UAAY,WAAa,OAAOC,OAAUZ,EACvJ,SAASO,EAAKM,GAAK,OAAO,SAAUC,GAAK,OACzC,SAAcC,GACV,GAAIlB,EAAG,MAAM,IAAImB,UAAU,mCAC3B,KAAOf,GAAG,IACN,GAAIJ,EAAI,EAAGC,IAAMC,EAAY,EAARgB,EAAG,GAASjB,EAAU,OAAIiB,EAAG,GAAKjB,EAAS,SAAOC,EAAID,EAAU,SAAMC,EAAEkB,KAAKnB,GAAI,GAAKA,EAAEQ,SAAWP,EAAIA,EAAEkB,KAAKnB,EAAGiB,EAAG,KAAKG,KAAM,OAAOnB,EAE3J,OADID,EAAI,EAAGC,IAAGgB,EAAK,CAAS,EAARA,EAAG,GAAQhB,EAAEoB,QACzBJ,EAAG,IACP,KAAK,EAAG,KAAK,EAAGhB,EAAIgB,EAAI,MACxB,KAAK,EAAc,OAAXd,EAAEC,QAAgB,CAAEiB,MAAOJ,EAAG,GAAIG,MAAM,GAChD,KAAK,EAAGjB,EAAEC,QAASJ,EAAIiB,EAAG,GAAIA,EAAK,CAAC,GAAI,SACxC,KAAK,EAAGA,EAAKd,EAAEI,IAAIe,MAAOnB,EAAEG,KAAKgB,MAAO,SACxC,QACI,KAAMrB,EAAIE,EAAEG,MAAML,EAAIA,EAAEsB,OAAS,GAAKtB,EAAEA,EAAEsB,OAAS,KAAkB,IAAVN,EAAG,IAAsB,IAAVA,EAAG,IAAW,CAAEd,EAAI,EAAG,SACjG,GAAc,IAAVc,EAAG,MAAchB,GAAMgB,EAAG,GAAKhB,EAAE,IAAMgB,EAAG,GAAKhB,EAAE,IAAM,CAAEE,EAAEC,MAAQa,EAAG,GAAI,MAC9E,GAAc,IAAVA,EAAG,IAAYd,EAAEC,MAAQH,EAAE,GAAI,CAAEE,EAAEC,MAAQH,EAAE,GAAIA,EAAIgB,EAAI,MAC7D,GAAIhB,GAAKE,EAAEC,MAAQH,EAAE,GAAI,CAAEE,EAAEC,MAAQH,EAAE,GAAIE,EAAEI,IAAIiB,KAAKP,GAAK,MACvDhB,EAAE,IAAIE,EAAEI,IAAIe,MAChBnB,EAAEG,KAAKgB,MAAO,SAEtBL,EAAKnB,EAAKqB,KAAKtB,EAASM,GAC1B,MAAOsB,GAAKR,EAAK,CAAC,EAAGQ,GAAIzB,EAAI,UAAeD,EAAIE,EAAI,EACtD,GAAY,EAARgB,EAAG,GAAQ,MAAMA,EAAG,GAAI,MAAO,CAAEI,MAAOJ,EAAG,GAAKA,EAAG,QAAK,EAAQG,MAAM,GArB9BM,CAAK,CAACX,EAAGC,MAyBhCW,OAAOC,gBAwBpBC,EAAOC,EAAGf,GACtB,IAAIgB,EAAsB,mBAAXnB,QAAyBkB,EAAElB,OAAOC,UACjD,IAAKkB,EAAG,OAAOD,EACf,IAAmBE,EAAYP,EAA3BQ,EAAIF,EAAEZ,KAAKW,GAAOI,EAAK,GAC3B,IACI,WAAc,IAANnB,GAAgBA,KAAM,MAAQiB,EAAIC,EAAEzB,QAAQY,MAAMc,EAAGV,KAAKQ,EAAEX,OAExE,MAAOc,GAASV,EAAI,CAAEU,MAAOA,WAEzB,IACQH,IAAMA,EAAEZ,OAASW,EAAIE,EAAU,SAAIF,EAAEZ,KAAKc,WAExC,GAAIR,EAAG,MAAMA,EAAEU,OAE7B,OAAOD,WAGKE,IACZ,IAAK,IAAIF,EAAK,GAAID,EAAI,EAAGA,EAAII,UAAUd,OAAQU,IAC3CC,EAAKA,EAAGI,OAAOT,EAAOQ,UAAUJ,KACpC,OAAOC,EA8CcP,OAAOC,aC5L9B,SAA4BP,GAAAP,KAAAO,MAAAA,gBAG9B,SAAAkB,IAGUzB,KAAA0B,KAAO,SAEfb,OAAAc,eAAIF,EAAAG,UAAA,OAAI,KAAR,WACE,OAAO5B,KAAK6B,uCAEdhB,OAAAc,eAAIF,EAAAG,UAAA,OAAI,KAAR,WACE,OAAO5B,KAAK8B,sCAEdjB,OAAAc,eAAIF,EAAAG,UAAA,SAAM,KAAV,WACE,OAAO5B,KAAK0B,sCAGND,EAAAG,UAAAG,OAAA,SACNxB,EACAyB,EACAC,GAEA,IAAKD,EAAc,OAAOhC,KAAKkC,QAAQ3B,GAEvC,IAAK0B,EAAU,OAAOjC,KAAKmC,QAAQ5B,GAEnC,IAAM6B,EAAO,IAAIC,EAAS9B,GAQ1B,OAPA6B,EAAKE,SAAWN,EAChBA,EAAatC,KAAO0C,EACpBA,EAAK1C,KAAOuC,EACZA,EAASK,SAAWF,EAEpBpC,KAAK0B,OAEEU,GAGDX,EAAAG,UAAAW,WAAA,SACNC,EACAR,EACAC,GAEA,IAAKO,EAAO/B,OAAQ,MAAO,GAE3B,IAAKuB,EAAc,OAAOhC,KAAKyC,YAAYD,GAE3C,IAAKP,EAAU,OAAOjC,KAAK0C,YAAYF,GAEvC,IAAMG,EAAO,IAAIlB,EASjB,OARAkB,EAAKD,YAAYF,GACjBG,EAAKd,MAAOS,SAAWN,EACvBA,EAAatC,KAAOiD,EAAKd,MACzBc,EAAKb,KAAMpC,KAAOuC,EAClBA,EAASK,SAAWK,EAAKb,KAEzB9B,KAAK0B,MAAQc,EAAO/B,OAEbkC,EAAKC,eAGNnB,EAAAG,UAAAiB,OAAA,SAAOT,GACb,OAAKA,EAAKE,SAELF,EAAK1C,MAEV0C,EAAKE,SAAS5C,KAAO0C,EAAK1C,KAC1B0C,EAAK1C,KAAK4C,SAAWF,EAAKE,SAE1BtC,KAAK0B,OAEEU,GAPgBpC,KAAK8C,WAFD9C,KAAK+C,YAYlCtB,EAAAG,UAAAoB,IAAA,SAAIzC,GAAJ,IAAA0C,EAAAjD,KACE,MAAO,CACLkD,MAAO,qBAACC,EAAA,GAAAC,EAAA,EAAAA,EAAA7B,UAAAd,OAAA2C,IAAAD,EAAAC,GAAA7B,UAAA6B,GACN,OAAAC,EAAAJ,EAAKK,UAASjD,KAAIkD,MAAAF,EAAA/B,EAAA,CAAC2B,EAAM1C,GAAU4C,KACrCK,OAAQ,qBAACL,EAAA,GAAAC,EAAA,EAAAA,EAAA7B,UAAAd,OAAA2C,IAAAD,EAAAC,GAAA7B,UAAA6B,GACP,OAAAC,EAAAJ,EAAKQ,WAAUpD,KAAIkD,MAAAF,EAAA/B,EAAA,CAAC2B,EAAM1C,GAAU4C,KACtCO,QAAS,SAACC,GAAqB,OAAAV,EAAKW,WAAWrD,EAAOoD,IACtDE,KAAM,WAAM,OAAAZ,EAAKf,QAAQ3B,IACzBuD,KAAM,WAAM,OAAAb,EAAKd,QAAQ5B,MAI7BkB,EAAAG,UAAAmC,QAAA,SAAQvB,GAAR,IAAAS,EAAAjD,KACE,MAAO,CACLkD,MAAO,qBAACC,EAAA,GAAAC,EAAA,EAAAA,EAAA7B,UAAAd,OAAA2C,IAAAD,EAAAC,GAAA7B,UAAA6B,GACN,OAAAC,EAAAJ,EAAKe,cAAa3D,KAAIkD,MAAAF,EAAA/B,EAAA,CAAC2B,EAAMT,GAAWW,KAC1CK,OAAQ,qBAACL,EAAA,GAAAC,EAAA,EAAAA,EAAA7B,UAAAd,OAAA2C,IAAAD,EAAAC,GAAA7B,UAAA6B,GACP,OAAAC,EAAAJ,EAAKgB,eAAc5D,KAAIkD,MAAAF,EAAA/B,EAAA,CAAC2B,EAAMT,GAAWW,KAC3CO,QAAS,SAACC,GAAqB,OAAAV,EAAKiB,eAAe1B,EAAQmB,IAC3DE,KAAM,WAAM,OAAAZ,EAAKR,YAAYD,IAC7BsB,KAAM,WAAM,OAAAb,EAAKP,YAAYF,MAMjCf,EAAAG,UAAA0B,SAAA,SAAS/C,EAAU4D,EAAoBC,QAAA,IAAAA,IAAAA,EAAAC,GACrC,IAAM/B,EAAWtC,KAAKsE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK7B,MAAO4D,MAEzD,OAAO7B,EAAWtC,KAAK+B,OAAOxB,EAAO+B,EAAUA,EAAS5C,MAAQM,KAAKmC,QAAQ5B,IAK/EkB,EAAAG,UAAA6B,UAAA,SAAUlD,EAAUgE,EAAgBH,QAAA,IAAAA,IAAAA,EAAAC,GAClC,IAAM3E,EAAOM,KAAKsE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK7B,MAAOgE,MAErD,OAAO7E,EAAOM,KAAK+B,OAAOxB,EAAOb,EAAK4C,SAAU5C,GAAQM,KAAKkC,QAAQ3B,IAGvEkB,EAAAG,UAAAgC,WAAA,SAAWrD,EAAUoD,GACnB,GAAIA,EAAW,EAAGA,GAAY3D,KAAK0B,UAC9B,GAAIiC,GAAY3D,KAAK0B,KAAM,OAAO1B,KAAKmC,QAAQ5B,GAEpD,GAAIoD,GAAY,EAAG,OAAO3D,KAAKkC,QAAQ3B,GAEvC,IAAMb,EAAOM,KAAKwE,IAAIb,GAEtB,OAAO3D,KAAK+B,OAAOxB,EAAOb,EAAK4C,SAAU5C,IAG3C+B,EAAAG,UAAAM,QAAA,SAAQ3B,GACN,IAAM6B,EAAO,IAAIC,EAAS9B,GAU1B,OARA6B,EAAK1C,KAAOM,KAAK6B,MAEb7B,KAAK6B,MAAO7B,KAAK6B,MAAMS,SAAWF,EACjCpC,KAAK8B,KAAOM,EAEjBpC,KAAK6B,MAAQO,EACbpC,KAAK0B,OAEEU,GAGTX,EAAAG,UAAAO,QAAA,SAAQ5B,GACN,IAAM6B,EAAO,IAAIC,EAAS9B,GAa1B,OAXIP,KAAK6B,OACPO,EAAKE,SAAWtC,KAAK8B,KACrB9B,KAAK8B,KAAMpC,KAAO0C,EAClBpC,KAAK8B,KAAOM,IAEZpC,KAAK6B,MAAQO,EACbpC,KAAK8B,KAAOM,GAGdpC,KAAK0B,OAEEU,GAKTX,EAAAG,UAAAoC,aAAA,SACExB,EACA2B,EACAC,QAAA,IAAAA,IAAAA,EAAAC,GAEA,IAAM/B,EAAWtC,KAAKsE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK7B,MAAO4D,MAEzD,OAAO7B,EAAWtC,KAAKuC,WAAWC,EAAQF,EAAUA,EAAS5C,MAAQM,KAAK0C,YAAYF,IAKxFf,EAAAG,UAAAqC,cAAA,SACEzB,EACA+B,EACAH,QAAA,IAAAA,IAAAA,EAAAC,GAEA,IAAM3E,EAAOM,KAAKsE,MAAK,SAAAlC,GAAQ,OAAAgC,EAAUhC,EAAK7B,MAAOgE,MAErD,OAAO7E,EAAOM,KAAKuC,WAAWC,EAAQ9C,EAAK4C,SAAU5C,GAAQM,KAAKyC,YAAYD,IAGhFf,EAAAG,UAAAsC,eAAA,SAAe1B,EAAamB,GAG1B,GAFIA,EAAW,IAAGA,GAAY3D,KAAK0B,MAE/BiC,GAAY,EAAG,OAAO3D,KAAKyC,YAAYD,GAE3C,GAAImB,GAAY3D,KAAK0B,KAAM,OAAO1B,KAAK0C,YAAYF,GAEnD,IAAM9C,EAAOM,KAAKwE,IAAIb,GAEtB,OAAO3D,KAAKuC,WAAWC,EAAQ9C,EAAK4C,SAAU5C,IAGhD+B,EAAAG,UAAAa,YAAA,SAAYD,GAAZ,IAAAS,EAAAjD,KACE,OAAOwC,EAAOiC,aAA2B,SAACC,EAAOnE,GAE/C,OADAmE,EAAMC,QAAQ1B,EAAKf,QAAQ3B,IACpBmE,IACN,KAGLjD,EAAAG,UAAAc,YAAA,SAAYF,GAAZ,IAAAS,EAAAjD,KACE,OAAOwC,EAAOoC,KAAI,SAAArE,GAAS,OAAA0C,EAAKd,QAAQ5B,OAG1CkB,EAAAG,UAAAiD,KAAA,WAAA,IAAA5B,EAAAjD,KACE,MAAO,CACL0D,QAAS,SAACC,GAAqB,OAAAV,EAAK6B,YAAYnB,IAChDoB,QAAS,eAAC,IAAA5B,EAAA,GAAAC,EAAA,EAAAA,EAAA7B,UAAAd,OAAA2C,IAAAD,EAAAC,GAAA7B,UAAA6B,GACR,OAAAH,EAAK+B,YAAYzB,MAAMN,EAAME,IAC/B8B,WAAY,eAAC,IAAA9B,EAAA,GAAAC,EAAA,EAAAA,EAAA7B,UAAAd,OAAA2C,IAAAD,EAAAC,GAAA7B,UAAA6B,GACX,OAAAH,EAAKiC,eAAe3B,MAAMN,EAAME,IAClCU,KAAM,WAAM,OAAAZ,EAAKF,YACjBe,KAAM,WAAM,OAAAb,EAAKH,cAIrBrB,EAAAG,UAAAuD,SAAA,SAASC,GAAT,IAAAnC,EAAAjD,KACE,MAAO,CACL0D,QAAS,SAACC,GAAqB,OAAAV,EAAKoC,gBAAgBD,EAAOzB,IAC3DE,KAAM,WAAM,OAAAZ,EAAKqC,aAAaF,IAC9BtB,KAAM,WAAM,OAAAb,EAAKsC,aAAaH,MAIlC3D,EAAAG,UAAAkD,YAAA,SAAYnB,GACNA,EAAW,IAAGA,GAAY3D,KAAK0B,MAEnC,IAAM8D,EAAUxF,KAAKwE,IAAIb,GAEzB,OAAO6B,EAAUxF,KAAK6C,OAAO2C,QAAWC,GAK1ChE,EAAAG,UAAAoD,YAAA,SAAYzE,EAAY6D,QAAA,IAAAA,IAAAA,EAAAC,GACtB,IAAMV,EAAW3D,KAAK0F,WAAU,SAAAtD,GAAQ,OAAAgC,EAAUhC,EAAK7B,MAAOA,MAE9D,OAAOoD,EAAW,OAAI8B,EAAYzF,KAAK8E,YAAYnB,IAKrDlC,EAAAG,UAAAsD,eAAA,SAAe3E,EAAY6D,QAAA,IAAAA,IAAAA,EAAAC,GAGzB,IAFA,IAAMsB,EAAyB,GAEtBH,EAAUxF,KAAK6B,MAAO8B,EAAW,EAAG6B,EAAS7B,IAAY6B,EAAUA,EAAQ9F,KAC9E0E,EAAUoB,EAAQjF,MAAOA,IAC3BoF,EAAQjF,KAAKV,KAAK8E,YAAYnB,EAAWgC,EAAQlF,SAIrD,OAAOkF,GAGTlE,EAAAG,UAAAmB,SAAA,WACE,IAAMc,EAAO7D,KAAK6B,MAElB,GAAIgC,EAQF,OAPA7D,KAAK6B,MAAQgC,EAAKnE,KAEdM,KAAK6B,MAAO7B,KAAK6B,MAAMS,cAAWmD,EACjCzF,KAAK8B,UAAO2D,EAEjBzF,KAAK0B,OAEEmC,GAMXpC,EAAAG,UAAAkB,SAAA,WACE,IAAMgB,EAAO9D,KAAK8B,KAElB,GAAIgC,EAQF,OAPA9D,KAAK8B,KAAOgC,EAAKxB,SAEbtC,KAAK8B,KAAM9B,KAAK8B,KAAKpC,UAAO+F,EAC3BzF,KAAK6B,WAAQ4D,EAElBzF,KAAK0B,OAEEoC,GAMXrC,EAAAG,UAAAyD,gBAAA,SAAgBD,EAAezB,GAC7B,GAAIyB,GAAS,EAAG,MAAO,GAEvB,GAAIzB,EAAW,EAAGA,EAAWiC,KAAKC,IAAIlC,EAAW3D,KAAK0B,KAAM,QACvD,GAAIiC,GAAY3D,KAAK0B,KAAM,MAAO,GAEvC0D,EAAQQ,KAAKE,IAAIV,EAAOpF,KAAK0B,KAAOiC,GAIpC,IAFA,IAAMgC,EAAyB,GAExBP,KAAS,CACd,IAAMI,EAAUxF,KAAKwE,IAAIb,GACzBgC,EAAQjF,KAAKV,KAAK6C,OAAO2C,IAG3B,OAAOG,GAGTlE,EAAAG,UAAA0D,aAAA,SAAaF,GACX,GAAIA,GAAS,EAAG,MAAO,GAEvBA,EAAQQ,KAAKE,IAAIV,EAAOpF,KAAK0B,MAI7B,IAFA,IAAMiE,EAAyB,GAExBP,KAASO,EAAQhB,QAAQ3E,KAAK+C,YAErC,OAAO4C,GAGTlE,EAAAG,UAAA2D,aAAA,SAAaH,GACX,GAAIA,GAAS,EAAG,MAAO,GAEvBA,EAAQQ,KAAKE,IAAIV,EAAOpF,KAAK0B,MAI7B,IAFA,IAAMiE,EAAyB,GAExBP,KAASO,EAAQjF,KAAKV,KAAK8C,YAElC,OAAO6C,GAGTlE,EAAAG,UAAA0C,KAAA,SAAKyB,GACH,IAAK,IAAIP,EAAUxF,KAAK6B,MAAO8B,EAAW,EAAG6B,EAAS7B,IAAY6B,EAAUA,EAAQ9F,KAClF,GAAIqG,EAAUP,EAAS7B,EAAU3D,MAAO,OAAOwF,GAMnD/D,EAAAG,UAAA8D,UAAA,SAAUK,GACR,IAAK,IAAIP,EAAUxF,KAAK6B,MAAO8B,EAAW,EAAG6B,EAAS7B,IAAY6B,EAAUA,EAAQ9F,KAClF,GAAIqG,EAAUP,EAAS7B,EAAU3D,MAAO,OAAO2D,EAGjD,OAAQ,GAGVlC,EAAAG,UAAAoE,QAAA,SAAqBC,GACnB,IAAK,IAAI7D,EAAOpC,KAAK6B,MAAO8B,EAAW,EAAGvB,EAAMuB,IAAYvB,EAAOA,EAAK1C,KACtEuG,EAAW7D,EAAMuB,EAAU3D,OAI/ByB,EAAAG,UAAA4C,IAAA,SAAIb,GACF,OAAO3D,KAAKsE,MAAK,SAACjF,EAAG6G,GAAU,OAAAvC,IAAauC,MAK9CzE,EAAAG,UAAAuE,QAAA,SAAQ5F,EAAY6D,GAClB,YADkB,IAAAA,IAAAA,EAAAC,GACXrE,KAAK0F,WAAU,SAAAtD,GAAQ,OAAAgC,EAAUhC,EAAK7B,MAAOA,OAGtDkB,EAAAG,UAAAwE,QAAA,WACE,IAAMC,EAAQ,IAAIC,MAAMtG,KAAK0B,MAI7B,OAFA1B,KAAKgG,SAAQ,SAAC5D,EAAM8D,GAAU,OAACG,EAAMH,GAAU9D,EAAK7B,SAE7C8F,GAGT5E,EAAAG,UAAAgB,YAAA,WACE,IAAMyD,EAAQ,IAAIC,MAAMtG,KAAK0B,MAI7B,OAFA1B,KAAKgG,SAAQ,SAAC5D,EAAM8D,GAAU,OAACG,EAAMH,GAAU9D,KAExCiE,GAGT5E,EAAAG,UAAA2E,SAAA,SAASC,GACP,YADO,IAAAA,IAAAA,EAA4BC,KAAKC,WACjC1G,KAAKoG,UACTxB,KAAI,SAAArE,GAAS,OAAAiG,EAASjG,MACtBoG,KAAK,UAITlF,EAAAG,UAAC9B,OAAOC,UAAT,mEACWqC,EAAOpC,KAAK6B,MAAkB,0BAAGO,EACxC,CAAA,EAAMA,EAAK7B,OADiC,CAAA,EAAA,UAC5C8C,EAAA9D,+BAD0D6C,EAAOA,EAAK1C","sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (p !== \"default\" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/* tslint:disable:no-non-null-assertion */\r\n\r\nimport compare from 'just-compare';\r\n\r\nexport class ListNode {\r\n next: ListNode | undefined;\r\n previous: ListNode | undefined;\r\n constructor(public readonly value: T) {}\r\n}\r\n\r\nexport class LinkedList {\r\n private first: ListNode | undefined;\r\n private last: ListNode | undefined;\r\n private size = 0;\r\n\r\n get head(): ListNode | undefined {\r\n return this.first;\r\n }\r\n get tail(): ListNode | undefined {\r\n return this.last;\r\n }\r\n get length(): number {\r\n return this.size;\r\n }\r\n\r\n private attach(\r\n value: T,\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode {\r\n if (!previousNode) return this.addHead(value);\r\n\r\n if (!nextNode) return this.addTail(value);\r\n\r\n const node = new ListNode(value);\r\n node.previous = previousNode;\r\n previousNode.next = node;\r\n node.next = nextNode;\r\n nextNode.previous = node;\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n private attachMany(\r\n values: T[],\r\n previousNode: ListNode | undefined,\r\n nextNode: ListNode | undefined,\r\n ): ListNode[] {\r\n if (!values.length) return [];\r\n\r\n if (!previousNode) return this.addManyHead(values);\r\n\r\n if (!nextNode) return this.addManyTail(values);\r\n\r\n const list = new LinkedList();\r\n list.addManyTail(values);\r\n list.first!.previous = previousNode;\r\n previousNode.next = list.first;\r\n list.last!.next = nextNode;\r\n nextNode.previous = list.last;\r\n\r\n this.size += values.length;\r\n\r\n return list.toNodeArray();\r\n }\r\n\r\n private detach(node: ListNode) {\r\n if (!node.previous) return this.dropHead();\r\n\r\n if (!node.next) return this.dropTail();\r\n\r\n node.previous.next = node.next;\r\n node.next.previous = node.previous;\r\n\r\n this.size--;\r\n\r\n return node;\r\n }\r\n\r\n add(value: T) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addAfter.call(this, value, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addBefore.call(this, value, ...params),\r\n byIndex: (position: number) => this.addByIndex(value, position),\r\n head: () => this.addHead(value),\r\n tail: () => this.addTail(value),\r\n };\r\n }\r\n\r\n addMany(values: T[]) {\r\n return {\r\n after: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyAfter.call(this, values, ...params),\r\n before: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.addManyBefore.call(this, values, ...params),\r\n byIndex: (position: number) => this.addManyByIndex(values, position),\r\n head: () => this.addManyHead(values),\r\n tail: () => this.addManyTail(values),\r\n };\r\n }\r\n\r\n addAfter(value: T, previousValue: T): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn): ListNode;\r\n addAfter(value: T, previousValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attach(value, previous, previous.next) : this.addTail(value);\r\n }\r\n\r\n addBefore(value: T, nextValue: T): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn): ListNode;\r\n addBefore(value: T, nextValue: any, compareFn: ListComparisonFn = compare): ListNode {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attach(value, next.previous, next) : this.addHead(value);\r\n }\r\n\r\n addByIndex(value: T, position: number): ListNode {\r\n if (position < 0) position += this.size;\r\n else if (position >= this.size) return this.addTail(value);\r\n\r\n if (position <= 0) return this.addHead(value);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attach(value, next.previous, next);\r\n }\r\n\r\n addHead(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n node.next = this.first;\r\n\r\n if (this.first) this.first.previous = node;\r\n else this.last = node;\r\n\r\n this.first = node;\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addTail(value: T): ListNode {\r\n const node = new ListNode(value);\r\n\r\n if (this.first) {\r\n node.previous = this.last;\r\n this.last!.next = node;\r\n this.last = node;\r\n } else {\r\n this.first = node;\r\n this.last = node;\r\n }\r\n\r\n this.size++;\r\n\r\n return node;\r\n }\r\n\r\n addManyAfter(values: T[], previousValue: T): ListNode[];\r\n addManyAfter(values: T[], previousValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyAfter(\r\n values: T[],\r\n previousValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const previous = this.find(node => compareFn(node.value, previousValue));\r\n\r\n return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values);\r\n }\r\n\r\n addManyBefore(values: T[], nextValue: T): ListNode[];\r\n addManyBefore(values: T[], nextValue: any, compareFn: ListComparisonFn): ListNode[];\r\n addManyBefore(\r\n values: T[],\r\n nextValue: any,\r\n compareFn: ListComparisonFn = compare,\r\n ): ListNode[] {\r\n const next = this.find(node => compareFn(node.value, nextValue));\r\n\r\n return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values);\r\n }\r\n\r\n addManyByIndex(values: T[], position: number): ListNode[] {\r\n if (position < 0) position += this.size;\r\n\r\n if (position <= 0) return this.addManyHead(values);\r\n\r\n if (position >= this.size) return this.addManyTail(values);\r\n\r\n const next = this.get(position)!;\r\n\r\n return this.attachMany(values, next.previous, next);\r\n }\r\n\r\n addManyHead(values: T[]): ListNode[] {\r\n return values.reduceRight[]>((nodes, value) => {\r\n nodes.unshift(this.addHead(value));\r\n return nodes;\r\n }, []);\r\n }\r\n\r\n addManyTail(values: T[]): ListNode[] {\r\n return values.map(value => this.addTail(value));\r\n }\r\n\r\n drop() {\r\n return {\r\n byIndex: (position: number) => this.dropByIndex(position),\r\n byValue: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValue.apply(this, params),\r\n byValueAll: (...params: [T] | [any, ListComparisonFn]) =>\r\n this.dropByValueAll.apply(this, params),\r\n head: () => this.dropHead(),\r\n tail: () => this.dropTail(),\r\n };\r\n }\r\n\r\n dropMany(count: number) {\r\n return {\r\n byIndex: (position: number) => this.dropManyByIndex(count, position),\r\n head: () => this.dropManyHead(count),\r\n tail: () => this.dropManyTail(count),\r\n };\r\n }\r\n\r\n dropByIndex(position: number): ListNode | undefined {\r\n if (position < 0) position += this.size;\r\n\r\n const current = this.get(position);\r\n\r\n return current ? this.detach(current) : undefined;\r\n }\r\n\r\n dropByValue(value: T): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn): ListNode | undefined;\r\n dropByValue(value: any, compareFn: ListComparisonFn = compare): ListNode | undefined {\r\n const position = this.findIndex(node => compareFn(node.value, value));\r\n\r\n return position < 0 ? undefined : this.dropByIndex(position);\r\n }\r\n\r\n dropByValueAll(value: T): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn): ListNode[];\r\n dropByValueAll(value: any, compareFn: ListComparisonFn = compare): ListNode[] {\r\n const dropped: ListNode[] = [];\r\n\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (compareFn(current.value, value)) {\r\n dropped.push(this.dropByIndex(position - dropped.length)!);\r\n }\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropHead(): ListNode | undefined {\r\n const head = this.first;\r\n\r\n if (head) {\r\n this.first = head.next;\r\n\r\n if (this.first) this.first.previous = undefined;\r\n else this.last = undefined;\r\n\r\n this.size--;\r\n\r\n return head;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropTail(): ListNode | undefined {\r\n const tail = this.last;\r\n\r\n if (tail) {\r\n this.last = tail.previous;\r\n\r\n if (this.last) this.last.next = undefined;\r\n else this.first = undefined;\r\n\r\n this.size--;\r\n\r\n return tail;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n dropManyByIndex(count: number, position: number): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n if (position < 0) position = Math.max(position + this.size, 0);\r\n else if (position >= this.size) return [];\r\n\r\n count = Math.min(count, this.size - position);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) {\r\n const current = this.get(position);\r\n dropped.push(this.detach(current!)!);\r\n }\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyHead(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.unshift(this.dropHead()!);\r\n\r\n return dropped;\r\n }\r\n\r\n dropManyTail(count: Exclude): ListNode[] {\r\n if (count <= 0) return [];\r\n\r\n count = Math.min(count, this.size);\r\n\r\n const dropped: ListNode[] = [];\r\n\r\n while (count--) dropped.push(this.dropTail()!);\r\n\r\n return dropped;\r\n }\r\n\r\n find(predicate: ListIteratorFn): ListNode | undefined {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return current;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n findIndex(predicate: ListIteratorFn): number {\r\n for (let current = this.first, position = 0; current; position++, current = current.next) {\r\n if (predicate(current, position, this)) return position;\r\n }\r\n\r\n return -1;\r\n }\r\n\r\n forEach(iteratorFn: ListIteratorFn) {\r\n for (let node = this.first, position = 0; node; position++, node = node.next) {\r\n iteratorFn(node, position, this);\r\n }\r\n }\r\n\r\n get(position: number): ListNode | undefined {\r\n return this.find((_, index) => position === index);\r\n }\r\n\r\n indexOf(value: T): number;\r\n indexOf(value: any, compareFn: ListComparisonFn): number;\r\n indexOf(value: any, compareFn: ListComparisonFn