diff --git a/.github/workflows/angular.yml b/.github/workflows/angular.yml index e42f3e58dd..ee66fbcf2c 100644 --- a/.github/workflows/angular.yml +++ b/.github/workflows/angular.yml @@ -10,11 +10,17 @@ on: branches: - 'rel-*' - 'dev' + types: + - opened + - synchronize + - reopened + - ready_for_review permissions: contents: read jobs: build-test-lint: + if: ${{ !github.event.pull_request.draft }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index bc7364a7e5..dda9340d7d 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -31,12 +31,18 @@ on: - 'templates/**/*.cshtml' - 'templates/**/*.csproj' - 'templates/**/*.razor' + types: + - opened + - synchronize + - reopened + - ready_for_review permissions: contents: read jobs: build-test: runs-on: windows-latest + if: ${{ !github.event.pull_request.draft }} steps: - uses: actions/checkout@v2 - uses: actions/setup-dotnet@master diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e3127f21b1..d1f6c0c503 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -9,26 +9,32 @@ on: push: branches: [dev, rel-*] paths: - - 'abp/**/*.js' - - 'abp/**/*.cs' - - 'abp/**/*.cshtml' - - 'abp/**/*.csproj' - - 'abp/**/*.razor' + - "abp/**/*.js" + - "abp/**/*.cs" + - "abp/**/*.cshtml" + - "abp/**/*.csproj" + - "abp/**/*.razor" pull_request: # The branches below must be a subset of the branches above branches: [dev] paths: - - 'abp/**/*.js' - - 'abp/**/*.cs' - - 'abp/**/*.cshtml' - - 'abp/**/*.csproj' - - 'abp/**/*.razor' + - "abp/**/*.js" + - "abp/**/*.cs" + - "abp/**/*.cshtml" + - "abp/**/*.csproj" + - "abp/**/*.razor" + types: + - opened + - synchronize + - reopened + - ready_for_review permissions: contents: read jobs: analyze: + if: ${{ !github.event.pull_request.draft }} permissions: actions: read # for github/codeql-action/init to get workflow details contents: read # for actions/checkout to fetch code @@ -41,48 +47,48 @@ jobs: matrix: # Override automatic language detection by changing the below list # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] - language: ['csharp', 'javascript'] + language: ["csharp", "javascript"] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/image-compression.yml b/.github/workflows/image-compression.yml index 9cbaa00d90..4556622e4a 100644 --- a/.github/workflows/image-compression.yml +++ b/.github/workflows/image-compression.yml @@ -1,21 +1,26 @@ -name: Compress Images -on: - pull_request: - paths: - - '**.jpg' - - '**.jpeg' - - '**.png' - - '**.webp' -jobs: - build: - if: github.event.pull_request.head.repo.full_name == github.repository - name: calibreapp/image-actions - runs-on: ubuntu-latest - steps: - - name: Checkout Repo - uses: actions/checkout@v2 - - - name: Compress Images - uses: calibreapp/image-actions@main - with: - githubToken: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file +name: Compress Images +on: + pull_request: + paths: + - "**.jpg" + - "**.jpeg" + - "**.png" + - "**.webp" + types: + - opened + - synchronize + - reopened + - ready_for_review +jobs: + build: + if: github.event.pull_request.head.repo.full_name == github.repository && !github.event.pull_request.draft + name: calibreapp/image-actions + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v2 + + - name: Compress Images + uses: calibreapp/image-actions@main + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json index 6583ae731f..98f6ed0820 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json @@ -73,6 +73,7 @@ "DeveloperFocused": "Developer Focused", "ShareYourExperiences": "Share your experiences with the ABP Framework", "LatestPosts": "Latest Posts", + "LatestVideos": "Latest Videos", "Views": "Views", "LearnLatestNewsAboutABPFramework": "Get information about happenings in ABP like new releases, free sources, posts, and more.", "DeveloperTools": "Developer Tools", @@ -98,6 +99,7 @@ "Logout": "Logout", "Home": "Home", "Posts": "Posts", + "Videos": "Videos", "JoinTheABPCommunity": "Join the ABP Community", "SubmitYourPost": "Submit Your Post", "Modules": "Modules", @@ -171,6 +173,10 @@ "BuyOrRenewLicenseToGetExtra2Months": "Buy or Renew License Now and Get 2 Extra Months! HURRY UP! ⏰ Last Day: {0}", "HurryUp": "HURRY UP!", "LastDay": "Last Day: {0}", - "BuyNewLicenseBetweenDatesToGetBenefit": "Buy a new license between {0} and {1} to get benefit for extra 2 months!" + "BuyNewLicenseBetweenDatesToGetBenefit": "Buy a new license between {0} and {1} to get benefit for extra 2 months!", + "CheckAllCommunityTalks": "Check All Community Posts", + "ReadMore": "Read More", + "Post": "Post", + "ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "Explore the contents created by the core ABP team and the ABP community." } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json index c4aa5f4926..4ba89108ce 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json @@ -73,6 +73,7 @@ "DeveloperFocused": "以开发者为中心", "ShareYourExperiences": "分享您使用 ABP 框架的经验", "LatestPosts": "最新的帖子", + "LatestVideos": "最新的视频", "Views": "意见", "LearnLatestNewsAboutABPFramework": "获取有关 ABP 的最新相关信息,例如新版本、免费资源、帖子等。", "DeveloperTools": "开发者工具", @@ -98,6 +99,7 @@ "Logout": "登出", "Home": "主页", "Posts": "帖子", + "Videos": "视频", "JoinTheABPCommunity": "加入 ABP 社区", "SubmitYourPost": "提交您的帖子", "Modules": "模块", @@ -168,6 +170,10 @@ "BuyOrRenewLicenseToGetExtra2Months": "立即购买或续订 ABP 商业许可证(适用于所有版本)并额外获得 2 个月!", "HurryUp": "赶快下单!", "LastDay": "活动截止日期: {0}", - "BuyNewLicenseBetweenDatesToGetBenefit": "在 {0} 和 {1} 之间购买一个新的许可证以获得额外 2 个月的收益!" + "BuyNewLicenseBetweenDatesToGetBenefit": "在 {0} 和 {1} 之间购买一个新的许可证以获得额外 2 个月的收益!", + "CheckAllCommunityTalks": "检查所有社区帖子", + "ReadMore": "阅读更多", + "Post": "邮政", + "ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "探索核心 ABP 团队和 ABP 社区创建的内容。" } } \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json index b8e8d9b135..c73da26137 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json @@ -150,7 +150,6 @@ "GetStarted": "Get Started", "SourceCode": "Source Code", "LeaveComment": "Leave Comment", - "ReadMore": "Read more", "ShowMore": "Show More", "NoPublishedPostsYet": "No published posts yet.", "Name": "Name", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json index 3513a37dde..8196d567a1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json @@ -150,7 +150,6 @@ "GetStarted": "开始使用", "SourceCode": "源代码", "LeaveComment": "发表评论", - "ReadMore": "阅读更多", "ShowMore": "展示更多", "NoPublishedPostsYet": "还没有发布的帖子。", "Name": "名字", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 2a5f9a2584..0b9dfab886 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -293,7 +293,6 @@ "ExploreDocumentationAndGuides": "Explore the comprehensive documentation and guides.", "Documentations": "Documentation", "Views": "Views", - "ReadMore": "Read More", "EnterYouEmailToGetNews": "Enter your email to get the latest news about the ABP Framework", "Tiered": "Tiered", "SeparateIdentityServer": "Separate Identity Server", @@ -378,6 +377,13 @@ "IntroducingTheSolution": "Introducing the eShopOnAbp Solution", "RunningTheSolution": "Running the Solution", "UnderstandingTheAuthenticationSystem": "Understanding the Authentication System", + "ExploringTheApplications": "Exploring the Applications", + "UnderstandingTheAPIGateways": "Understanding the API Gateways", + "DevelopingTheMicroservices": "Developing the Microservices", + "UnderstandingTheInfrastructure": "Understanding the Infrastructure", + "DiggingInTheUseCases": "Digging in the Use Cases", + "DeployingTheSolution": "Deploying the Solution", + "ThisBookIsInDraftStageAndIsNotCompletedYet": "This book is in draft stage and is not completed yet.", "Authors": "Authors", "MicroserviceEBook": "Microservice E-Book", "SelectUITheme": "Select UI Theme", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json index 01fe9f8b7b..a4a6e142a9 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json @@ -279,6 +279,7 @@ "SubscribeToNewsletter": "ABP.IO Platform'u ile ilgili yeni haberler, makaleler, teklifler ve daha fazlası gibi gelişmeler hakkında bilgi almak için bültene abone olun.", "FirstEdition": "İlk Baskı", "ThankYou": "Teşekkürler!", - "CheckboxMandatory": "Devam etmek için bunu kontrol etmeniz gerekiyor!" + "CheckboxMandatory": "Devam etmek için bunu kontrol etmeniz gerekiyor!", + "ThisBookIsInDraftStageAndIsNotCompletedYet": "Bu kitap taslak aşamasındadır ve henüz tamamlanmamıştır." } } \ 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 9a1373f76b..7826f00ca2 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json @@ -293,7 +293,6 @@ "ExploreDocumentationAndGuides": "探索全面的文档和指南。", "Documentations": "文档", "Views": "意见", - "ReadMore": "阅读更多", "EnterYouEmailToGetNews": "输入您的电子邮件以获取有关 ABP 框架的最新消息", "Tiered": "分层", "SeparateIdentityServer": "独立的身份服务器", @@ -372,6 +371,7 @@ "MasteringAbpFramework_Book_What_You_Will_Learn_8": "使用 ABP 框架编写单元、集成和 UI 测试。", "MasteringAbpFramework_Book_WhoIsThisBookFor": "这本书是给谁看的", "MasteringAbpFramework_Book_WhoIsThisBookFor_Description": "本书适用于希望学习软件架构和最佳实践的 Web 开发人员,以使用 Microsoft 技术和 ABP 框架构建\n 可维护的基于 Web 的解决方案。 C#\n 和 ASP.NET Core 的基本知识是开始阅读本书所必需的。", - "ComputersAndTechnology": "计算机与技术" + "ComputersAndTechnology": "计算机与技术", + "ThisBookIsInDraftStageAndIsNotCompletedYet": "这本书正在草案阶段,还没有完成。" } } \ No newline at end of file diff --git a/docs/en/CLI.md b/docs/en/CLI.md index 8dc6d425dc..7a5e59a62a 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -124,7 +124,7 @@ For more samples, go to [ABP CLI Create Solution Samples](CLI-New-Command-Sample * `--separate-auth-server`: The Identity Server project comes as a separate project and runs at a different endpoint. It separates the Identity Server from the API Host application. If not specified, you will have a single endpoint in the server side. * `--mobile` or `-m`: Specifies the mobile application framework. If not specified, no mobile application will be created. Available options: * `react-native`: React Native. - * `maui`: MAUI. + * `maui`: MAUI. This mobile option is only available for ABP Commercial. * `--database-provider` or `-d`: Specifies the database provider. Default provider is `ef`. Available providers: * `ef`: Entity Framework Core. * `mongodb`: MongoDB. @@ -145,7 +145,8 @@ For more samples, go to [ABP CLI Create Solution Samples](CLI-New-Command-Sample * `mongodb`: MongoDB. * `--theme`: Specifes the theme. Default theme is `leptonx-lite`. Available themes: * `leptonx-lite`: [LeptonX Lite Theme](/Themes/LeptonXLite/mvc.md). - * `basic`: [Basic Theme](/UI/AspNetCore/Basic-Theme.md). + * `basic`: [Basic Theme](/UI/AspNetCore/Basic-Theme.md). + * **`maui`**: .NET MAUI. A minimalist .NET MAUI application will be created if you specify this option. * `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory. * `--version` or `-v`: Specifies the ABP & template version. It can be a [release tag](https://github.com/abpframework/abp/releases) or a [branch name](https://github.com/abpframework/abp/branches). Uses the latest release if not specified. Most of the times, you will want to use the latest version. * `--preview`: Use latest preview version. @@ -161,6 +162,7 @@ For more samples, go to [ABP CLI Create Solution Samples](CLI-New-Command-Sample * `PostgreSQL` * `--local-framework-ref --abp-path`: Uses local projects references to the ABP framework instead of using the NuGet packages. This can be useful if you download the ABP Framework source code and have a local reference to the framework from your application. * `--no-random-port`: Uses template's default ports. +* `--skip-installing-libs` or `-sib`: Skip installing client side packages. See some [examples for the new command](CLI-New-Command-Samples.md) here. @@ -244,7 +246,7 @@ It can also create a new module for your solution and add it to your solution. S > A business module generally consists of several packages (because of layering, different database provider options or other reasons). Using `add-module` command dramatically simplifies adding a module to a solution. However, each module may require some additional configurations which is generally indicated in the documentation of the related module. -Usage +Usage: ````bash abp add-module [options] @@ -278,7 +280,7 @@ abp add-module ProductManagement --new --add-to-solution-file Lists names of open-source application modules. -Usage +Usage: ````bash abp list-modules [options] @@ -294,11 +296,21 @@ abp list-modules * `--include-pro-modules`: Includes commercial (pro) modules in the output. +### list-templates + +Lists all available templates to create a solution. + +Usage: + +```bash +abp list-templates +``` + ### get-source Downloads the source code of a module to your computer. -Usage +Usage: ````bash abp get-source [options] diff --git a/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/How-to-Design-Multi-Lingual-Entity.md b/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/How-to-Design-Multi-Lingual-Entity.md new file mode 100644 index 0000000000..2c4b860c95 --- /dev/null +++ b/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/How-to-Design-Multi-Lingual-Entity.md @@ -0,0 +1,690 @@ +# How to Design Multi-Lingual Entity + +## Introduction + +If you want to open up to the global market these days, end-to-end localization is a must. ABP provides an already established infrastructure for static texts. However, this may not be sufficient for many applications. You may need to fully customize your app for a particular language and region. + +Let's take a look at a few quotes from Christian Arno's article "[How Foreign-Language Internet Strategies Boost Sales](https://www.mediapost.com/publications/article/155250/how-foreign-language-internet-strategies-boost-sal.html)" to better understand the impact of this: + +- 82% of European consumers are less likely to buy online if the site is not in their native tongue ([Eurobarometer survey](http://europa.eu/rapid/pressReleasesAction.do?reference=IP/11/556)). +- 72.4% of global consumers are more likely to buy a product if the information is available in their own language ([Common Sense Advisory](http://www.commonsenseadvisory.com/)). +- The English language currently only accounts for 31% of all online use, and more than half of all searches are in languages other than English. +- Today, 42% of all Internet users are in Asia, while almost one-quarter are in Europe and just over 10% are in Latin America. + +- Foreign languages have experienced exponential growth in online usage in the past decade -- with Chinese now officially the [second-most-prominent-language](http://english.peopledaily.com.cn/90001/90776/90882/7438489.html) on the Web. [Arabic](http://www.internetworldstats.com/stats7.htm) has increased by a whopping 2500%, while English has only risen by 204% + +If you are looking for ways to expand your market share by fully customizing your application for a particular language and region, in this article I will explain how you can do it with ABP framework. + +### Source Code + +You can find the source code of the application at [abpframework/abp-samples](https://github.com/abpframework/abp-samples/tree/master/AcmeBookStoreMultiLingual). + +### Demo of the Final Application + +At the end of this article, we will have created an application same as in the gif below. + +![data-model](./result.gif) + +## Development + +In order to keep the article short and get rid of unrelated information in the article (like defining entities etc.), we'll be using the [BookStore](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore) example, which is used in the "[Web Application Development Tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1?UI=MVC&DB=EF)" documentation of ABP Framework and we will make the Book entity as multi-lingual. If you do not want to finish this tutorial, you can find the application [here](https://github.com/abpframework/abp-samples/tree/master/BookStore-Mvc-EfCore). + +### Determining the data model + +We need a robust, maintainable, and efficient data model to store content in multiple languages. + +> I read many articles to determine the data model correctly, and as a result, I decided to use one of the many approaches that suit us. +> However, as in everything, there is a trade-off here. If you are wondering about the advantages and disadvantages of the model we will implement compared to other models, I recommend you to read [this article](https://vertabelo.com/blog/data-modeling-for-multiple-languages-how-to-design-a-localization-ready-system/). + +![data-model](./data-model.png) + +As a result of the tutorial, we already have the `Book` and `Author` entities, as an extra, we will just add the `BookTranslation`. + +> In the article, we will make the Name property of the Book entity multi-lingual, but the article is independent of the Book entity, you can make the entity you want multi-lingual with similar codes according to your requirements. + +#### Acme.BookStore.Domain.Shared + +Create a folder named `MultiLingualObjects` and create the following interfaces in its contents. + +We will use the `IObjectTranslation` interface to mark the translation of a multi-lingual entity: + +```csharp +public interface IObjectTranslation +{ + string Language { get; set; } +} +``` + +We will use the `IMultiLingualObject` interface to mark multi-lingual entities: + +```csharp +public interface IMultiLingualObject + where TTranslation : class, IObjectTranslation +{ + ICollection Translations { get; set; } +} +``` + +#### Acme.BookStore.Domain + +In the `Books` folder, create the `BookTranslation` class as follows: + +```csharp +public class BookTranslation : Entity, IObjectTranslation +{ + public Guid BookId { get; set; } + + public string Name { get; set; } + + public string Language { get; set; } + + public override object[] GetKeys() + { + return new object[] {BookId, Language}; + } +} +``` + +`BookTranslation` contains the `Language` property, which contains a language code for translation and a reference to the multi-lingual entity. We also have the `BookId` foreign key to help us know which book is translated. + +Implement `IMultiLingualObject` in the `Book` class as follows: + +```csharp +public class Book : AuditedAggregateRoot, IMultiLingualObject +{ + public Guid AuthorId { get; set; } + + public string Name { get; set; } + + public BookType Type { get; set; } + + public DateTime PublishDate { get; set; } + + public float Price { get; set; } + + public ICollection Translations { get; set; } +} +``` + +Create a folder named `MultiLingualObjects` and add the following class inside of this folder: + +```csharp +public class MultiLingualObjectManager : ITransientDependency +{ + protected const int MaxCultureFallbackDepth = 5; + + public async Task FindTranslationAsync( + TMultiLingual multiLingual, + string culture = null, + bool fallbackToParentCultures = true) + where TMultiLingual : IMultiLingualObject + where TTranslation : class, IObjectTranslation + { + culture ??= CultureInfo.CurrentUICulture.Name; + + if (multiLingual.Translations.IsNullOrEmpty()) + { + return null; + } + + var translation = multiLingual.Translations.FirstOrDefault(pt => pt.Language == culture); + if (translation != null) + { + return translation; + } + + if (fallbackToParentCultures) + { + translation = GetTranslationBasedOnCulturalRecursive( + CultureInfo.CurrentUICulture.Parent, + multiLingual.Translations, + 0 + ); + + if (translation != null) + { + return translation; + } + } + + return null; + } + + protected TTranslation GetTranslationBasedOnCulturalRecursive( + CultureInfo culture, ICollection translations, int currentDepth) + where TTranslation : class, IObjectTranslation + { + if (culture == null || + culture.Name.IsNullOrWhiteSpace() || + translations.IsNullOrEmpty() || + currentDepth > MaxCultureFallbackDepth) + { + return null; + } + + var translation = translations.FirstOrDefault(pt => pt.Language.Equals(culture.Name, StringComparison.OrdinalIgnoreCase)); + return translation ?? GetTranslationBasedOnCulturalRecursive(culture.Parent, translations, currentDepth + 1); + } +} +``` + +With `MultiLingualObjectManager`'s `FindTranslationAsync` method, we get the translated version of the book according to `CurrentUICulture`. If no translation of culture is found, we return null. + +> Every thread in .NET has `CurrentCulture` and `CurrentUICulture` objects. + +#### Acme.BookStore.EntityFrameworkCore + +In the `OnModelCreating` method of the `BookStoreDbContext` class, configure the `BookTranslation` as follows: + +```csharp +builder.Entity(b => +{ + b.ToTable(BookStoreConsts.DbTablePrefix + "BookTranslations", + BookStoreConsts.DbSchema); + + b.ConfigureByConvention(); + + b.HasKey(x => new {x.BookId, x.Language}); +}); +``` + +> I haven't explicitly set up a one-to-many relationship between `Book` and `BookTranslation` here, but the entity framework will do it for us. + +After that, you can just run the following command in a command-line terminal to add a new database migration (in the directory of the `EntityFrameworkCore` project): + +```bash +dotnet ef migrations add Added_BookTranslation +``` + +This will add a new migration class to your project. You can then run the following command (or run the `.DbMigrator` application) to apply changes to the database: + +```bash +dotnet ef database update +``` + +Add the following code to the `ConfigureServices` method of the `BookStoreEntityFrameworkCoreModule`: + +```csharp + Configure(options => + { + options.Entity(bookOptions => + { + bookOptions.DefaultWithDetailsFunc = query => query.Include(o => o.Translations); + }); +}); +``` + +Now we can use `WithDetailsAsync` without any parameters on `BookAppService` knowing that `Translations` will be included. + +#### Acme.BookStore.Application.Contracts + +Implement `IObjectTranslation` in the `BookDto` class as follows: + +```csharp +public class BookDto : AuditedEntityDto, IObjectTranslation +{ + public Guid AuthorId { get; set; } + + public string AuthorName { get; set; } + + public string Name { get; set; } + + public BookType Type { get; set; } + + public DateTime PublishDate { get; set; } + + public float Price { get; set; } + + public string Language { get; set; } +} +``` + +`Language` property is required to understand which language the translated book name belongs to in the UI. + +Create the `AddBookTranslationDto` class in the `Books` folder as follows: + +```csharp +public class AddBookTranslationDto : IObjectTranslation +{ + [Required] + public string Language { get; set; } + + [Required] + public string Name { get; set; } +} +``` + +Add the `AddTranslationsAsync` method to the `IBookAppService` as follows: + +```csharp +public interface IBookAppService : + ICrudAppService< + BookDto, + Guid, + PagedAndSortedResultRequestDto, + CreateUpdateBookDto> +{ + Task> GetAuthorLookupAsync(); + + Task AddTranslationsAsync(Guid id, AddBookTranslationDto input); // added this line +} +``` + +#### Acme.BookStore.Application + +Now, we need to implement the `AddTranslationsAsync` method in `BookAppService` and include `Translations` in the `Book` entity, for this you can change the `BookAppService` as follows: + +```csharp +[Authorize(BookStorePermissions.Books.Default)] +public class BookAppService : + CrudAppService< + Book, //The Book entity + BookDto, //Used to show books + Guid, //Primary key of the book entity + PagedAndSortedResultRequestDto, //Used for paging/sorting + CreateUpdateBookDto>, //Used to create/update a book + IBookAppService //implement the IBookAppService +{ + private readonly IAuthorRepository _authorRepository; + + public BookAppService( + IRepository repository, + IAuthorRepository authorRepository) + : base(repository) + { + _authorRepository = authorRepository; + GetPolicyName = BookStorePermissions.Books.Default; + GetListPolicyName = BookStorePermissions.Books.Default; + CreatePolicyName = BookStorePermissions.Books.Create; + UpdatePolicyName = BookStorePermissions.Books.Edit; + DeletePolicyName = BookStorePermissions.Books.Create; + } + + public override async Task GetAsync(Guid id) + { + //Get the IQueryable from the repository + var queryable = await Repository.WithDetailsAsync(); // this line changed + + //Prepare a query to join books and authors + var query = from book in queryable + join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id + where book.Id == id + select new { book, author }; + + //Execute the query and get the book with author + var queryResult = await AsyncExecuter.FirstOrDefaultAsync(query); + if (queryResult == null) + { + throw new EntityNotFoundException(typeof(Book), id); + } + + var bookDto = ObjectMapper.Map(queryResult.book); + bookDto.AuthorName = queryResult.author.Name; + return bookDto; + } + + public override async Task> GetListAsync(PagedAndSortedResultRequestDto input) + { + //Get the IQueryable from the repository + var queryable = await Repository.WithDetailsAsync(); // this line changed + + //Prepare a query to join books and authors + var query = from book in queryable + join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id + select new {book, author}; + + //Paging + query = query + .OrderBy(NormalizeSorting(input.Sorting)) + .Skip(input.SkipCount) + .Take(input.MaxResultCount); + + //Execute the query and get a list + var queryResult = await AsyncExecuter.ToListAsync(query); + + //Convert the query result to a list of BookDto objects + var bookDtos = queryResult.Select(x => + { + var bookDto = ObjectMapper.Map(x.book); + bookDto.AuthorName = x.author.Name; + return bookDto; + }).ToList(); + + //Get the total count with another query + var totalCount = await Repository.GetCountAsync(); + + return new PagedResultDto( + totalCount, + bookDtos + ); + } + + public async Task> GetAuthorLookupAsync() + { + var authors = await _authorRepository.GetListAsync(); + + return new ListResultDto( + ObjectMapper.Map, List>(authors) + ); + } + + public async Task AddTranslationsAsync(Guid id, AddBookTranslationDto input) + { + var queryable = await Repository.WithDetailsAsync(); + + var book = await AsyncExecuter.FirstOrDefaultAsync(queryable, x => x.Id == id); + + if (book.Translations.Any(x => x.Language == input.Language)) + { + throw new UserFriendlyException($"Translation already available for {input.Language}"); + } + + book.Translations.Add(new BookTranslation + { + BookId = book.Id, + Name = input.Name, + Language = input.Language + }); + + await Repository.UpdateAsync(book); + } + + private static string NormalizeSorting(string sorting) + { + if (sorting.IsNullOrEmpty()) + { + return $"book.{nameof(Book.Name)}"; + } + + if (sorting.Contains("authorName", StringComparison.OrdinalIgnoreCase)) + { + return sorting.Replace( + "authorName", + "author.Name", + StringComparison.OrdinalIgnoreCase + ); + } + + return $"book.{sorting}"; + } +} +``` + +Create the `MultiLingualBookObjectMapper` class as follows: + +```csharp +public class MultiLingualBookObjectMapper : IObjectMapper, ITransientDependency +{ + private readonly MultiLingualObjectManager _multiLingualObjectManager; + + private readonly ISettingProvider _settingProvider; + + public MultiLingualBookObjectMapper( + MultiLingualObjectManager multiLingualObjectManager, + ISettingProvider settingProvider) + { + _multiLingualObjectManager = multiLingualObjectManager; + _settingProvider = settingProvider; + } + + public BookDto Map(Book source) + { + var translation = AsyncHelper.RunSync(() => + _multiLingualObjectManager.FindTranslationAsync(source)); + + return new BookDto + { + Id = source.Id, + AuthorId = source.AuthorId, + Type = source.Type, + Name = translation?.Name ?? source.Name, + PublishDate = source.PublishDate, + Price = source.Price, + Language = translation?.Language ?? AsyncHelper.RunSync(() => _settingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage)), + CreationTime = source.CreationTime, + CreatorId = source.CreatorId, + LastModificationTime = source.LastModificationTime, + LastModifierId = source.LastModifierId + }; + } + + public BookDto Map(Book source, BookDto destination) + { + return default; + } +} +``` + +To map the multi-lingual `Book` entity to `BookDto`, we implement custom mapping using the `IObjectMapper` interface. If no translation is found, default values are returned. + +So far we have created the entire infrastructure. We don't need to change anything in the UI, if there is a translation according to the language chosen by the user, the list view will change. However, I want to create a simple modal where we can add new translations to an existing book in order to see what we have done. + +#### Acme.BookStore.Web + +Create a new razor page named `AddTranslationModal` in the `Books` folder as below. + +**View** + +```html +@page +@using Microsoft.AspNetCore.Mvc.TagHelpers +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@model Acme.BookStore.Web.Pages.Books.AddTranslationModal + +@{ + Layout = null; +} + +
+ + Translations + + + + + + + + + +
+``` + +**Model** + +```csharp +public class AddTranslationModal : BookStorePageModel +{ + [HiddenInput] + [BindProperty(SupportsGet = true)] + public Guid Id { get; set; } + + public List Languages { get; set; } + + [BindProperty] + public BookTranslationViewModel TranslationViewModel { get; set; } + + private readonly IBookAppService _bookAppService; + private readonly ILanguageProvider _languageProvider; + + public AddTranslationModal( + IBookAppService bookAppService, + ILanguageProvider languageProvider) + { + _bookAppService = bookAppService; + _languageProvider = languageProvider; + } + + public async Task OnGetAsync() + { + Languages = await GetLanguagesSelectItem(); + + TranslationViewModel = new BookTranslationViewModel(); + } + + public async Task OnPostAsync() + { + await _bookAppService.AddTranslationsAsync(Id, ObjectMapper.Map(TranslationViewModel)); + + return NoContent(); + } + + private async Task> GetLanguagesSelectItem() + { + var result = await _languageProvider.GetLanguagesAsync(); + + return result.Select( + languageInfo => new SelectListItem + { + Value = languageInfo.CultureName, + Text = languageInfo.DisplayName + " (" + languageInfo.CultureName + ")" + } + ).ToList(); + } + + public class BookTranslationViewModel + { + [Required] + [SelectItems(nameof(Languages))] + public string Language { get; set; } + + [Required] + public string Name { get; set; } + + } +} +``` + +Then, we can open the `BookStoreWebAutoMapperProfile` class and define the required mapping as follows: + +```csharp +CreateMap(); +``` + +Finally, change the content of `index.js` in the `Books` folder as follows: + +```javascript +$(function () { + var l = abp.localization.getResource('BookStore'); + var createModal = new abp.ModalManager(abp.appPath + 'Books/CreateModal'); + var editModal = new abp.ModalManager(abp.appPath + 'Books/EditModal'); + var addTranslationModal = new abp.ModalManager(abp.appPath + 'Books/AddTranslationModal'); // added this line + + var dataTable = $('#BooksTable').DataTable( + abp.libs.datatables.normalizeConfiguration({ + serverSide: true, + paging: true, + order: [[1, "asc"]], + searching: false, + scrollX: true, + ajax: abp.libs.datatables.createAjax(acme.bookStore.books.book.getList), + columnDefs: [ + { + title: l('Actions'), + rowAction: { + items: + [ + { + text: l('Edit'), + visible: abp.auth.isGranted('BookStore.Books.Edit'), + action: function (data) { + editModal.open({ id: data.record.id }); + } + }, + { + text: l('Add Translation'), // added this action + visible: abp.auth.isGranted('BookStore.Books.Edit'), + action: function (data) { + addTranslationModal.open({ id: data.record.id }); + } + }, + { + text: l('Delete'), + visible: abp.auth.isGranted('BookStore.Books.Delete'), + confirmMessage: function (data) { + return l( + 'BookDeletionConfirmationMessage', + data.record.name + ); + }, + action: function (data) { + acme.bookStore.books.book + .delete(data.record.id) + .then(function() { + abp.notify.info( + l('SuccessfullyDeleted') + ); + dataTable.ajax.reload(); + }); + } + } + ] + } + }, + { + title: l('Name'), + data: "name" + }, + { + title: l('Author'), + data: "authorName" + }, + { + title: l('Type'), + data: "type", + render: function (data) { + return l('Enum:BookType:' + data); + } + }, + { + title: l('PublishDate'), + data: "publishDate", + render: function (data) { + return luxon + .DateTime + .fromISO(data, { + locale: abp.localization.currentCulture.name + }).toLocaleString(); + } + }, + { + title: l('Price'), + data: "price" + }, + { + title: l('CreationTime'), + data: "creationTime", + render: function (data) { + return luxon + .DateTime + .fromISO(data, { + locale: abp.localization.currentCulture.name + }).toLocaleString(luxon.DateTime.DATETIME_SHORT); + } + } + ] + }) + ); + + createModal.onResult(function () { + dataTable.ajax.reload(); + }); + + editModal.onResult(function () { + dataTable.ajax.reload(); + }); + + $('#NewBookButton').click(function (e) { + e.preventDefault(); + createModal.open(); + }); +}); +``` + +## Conclusion + +With a multi-lingual application, you can expand your market share, but if not designed well, may your application will be unusable. So, I've tried to explain how to design a sustainable multi-lingual entity in this article. + +### Source Code + +You can find source code of the example solution used in this article [here](https://github.com/abpframework/abp-samples/tree/master/AcmeBookStoreMultiLingual). diff --git a/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/data-model.png b/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/data-model.png new file mode 100644 index 0000000000..c7e02bc2cd Binary files /dev/null and b/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/data-model.png differ diff --git a/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/result.gif b/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/result.gif new file mode 100644 index 0000000000..0bc41cb8f1 Binary files /dev/null and b/docs/en/Community-Articles/15-08-2022-How-to-Design-Multi-Lingual-Entity/result.gif differ diff --git a/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md b/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md index 308358bb67..8e46bd6944 100644 --- a/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md +++ b/docs/en/Community-Articles/2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md @@ -1,9 +1,13 @@ # How to Add Custom Properties to the User Entity +> **Note:** If your application is greater than version 4.3.3, please follow [this article](../2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md). + ## Introduction In this step-by-step article, I will explain how you can customize the user entity class, which is available in every web application you create using the ABP framework, according to your needs. When you read this article, you will learn how to override the services of built-in modules, extend the entities, extend data transfer objects and customize the user interface in the applications you develop using the ABP framework. +> **Note:** This article is not about customizing the `Login` page. If you have such a need, please follow [this article](../2020-05-09-Customize-the-Login-Page-for-MVC-Razor-Page-Applications/POST.md). + You can see the screenshots below which we will reach at the end of the article. ![custom-identity-user-list](./custom-identity-user-list.png) diff --git a/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md new file mode 100644 index 0000000000..7c119c6e66 --- /dev/null +++ b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md @@ -0,0 +1,154 @@ +# How to Add Custom Properties to the User Entity + +> **Note:** If your application is less than version 4.4.x, please follow [this article](../2020-10-08-How-To-Add-Custom-Property-To-The-User-Entity/How-To-Add-Custom-Property-To-The-User-Entity.md). + +## Introduction + +In this step-by-step article, I will explain how you can customize the user entity class, which is available in every web application you create using the ABP framework, according to your needs. When you read this article, you will learn how to override the services of built-in modules, extend the entities, extend data transfer objects and customize the user interface in the applications you develop using the ABP framework. + +> **Note:** This article is not about customizing the `Login` page. If you have such a need, please follow [this article](../2020-05-09-Customize-the-Login-Page-for-MVC-Razor-Page-Applications/POST.md). + +You can see the screenshots below which we will reach at the end of the article. + +![custom-identity-user-list](./custom-identity-user-list.png) + +![new-user](./new-user.png) + +## Preparing the Project + +### Startup template and the initial run + +Abp Framework offers startup templates to get into the work faster. We can create a new startup template using Abp CLI: + +`abp new CustomizeUserDemo` + +> In this article, I will go through the MVC application, but it will work also in the [Angular](https://docs.abp.io/en/abp/latest/Getting-Started?UI=NG&DB=EF&Tiered=No), [Blazor Server](https://docs.abp.io/en/abp/latest/Getting-Started?UI=BlazorServer&DB=EF&Tiered=No), and [Blazor WebAssembly](https://docs.abp.io/en/abp/latest/Getting-Started?UI=Blazor&DB=EF&Tiered=No) application. + +After the download is finished, we can run **CustomizeUserDemo.DbMigrator** project to create the database migrations and seed the initial data (admin user, role, etc). Then we can run `CustomizeUserDemo.Web` to see that our application is working. + +> Default admin username is **admin** and password is **1q2w3E\*** + +![initial-project](./initial-project.png) + +In this article, we will go through a scenario together and find the solutions to our questions through this scenario. However, since the scenario is not a real-life scenario, it may be strange, please don't get too about this issue :) + +## Step-1 + +Create the Users folder in the **CustomizeUserDemo.Domain.Shared** project, create the class `UserConsts` inside the folder and update the class you created as below: + +```csharp +public static class UserConsts +{ + public const string TitlePropertyName = "Title"; + + public const string ReputationPropertyName = "Reputation"; + + public const int MaxTitleLength = 64; + + public const double MaxReputationValue = 1_000; + + public const double MinReputationValue = 1; +} +``` + +## Step-2 + +Update the `CustomizeUserDemoEfCoreEntityExtensionMappings` class in the **CustomizeUserDemo.EntityFramework** project in the EntityFrameworkCore folder as below: + +```csharp +public static class CustomizeUserDemoEfCoreEntityExtensionMappings +{ + private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); + + public static void Configure() + { + CustomizeUserDemoGlobalFeatureConfigurator.Configure(); + CustomizeUserDemoModuleExtensionConfigurator.Configure(); + + OneTimeRunner.Run(() => + { + ObjectExtensionManager.Instance + .MapEfCoreProperty( + UserConsts.TitlePropertyName, + (_, propertyBuilder) => + { + propertyBuilder.HasDefaultValue(""); + propertyBuilder.HasMaxLength(UserConsts.MaxTitleLength); + } + ).MapEfCoreProperty( + UserConsts.ReputationPropertyName, + (_, propertyBuilder) => + { + propertyBuilder.HasDefaultValue(UserConsts.MinReputationValue); + } + ); + }); + } +} +``` + +This class can be used to map these extra properties to table fields in the database. Please read [this](https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities) article to improve your understanding of what we are doing. + +So far, we have added our extra features to the `User` entity and matched these features with the `ef core`. + +Now we need to add migration to see what has changed in our database. This for, open the Package Manager Console (PMC) under the menu Tools > NuGet Package Manager. + +![nuget-package-manager](./nuget-package-manager.png) + +Select the **CustomizeUserDemo.EntityFramework** as the **default project** and execute the following command: + +```bash +Add-Migration "Updated-User-Entity" +``` + +![added-new-migration](./added-new-migration.png) + +This will create a new migration class inside the `Migrations` folder of the **CustomizeUserDemo.EntityFrameworkCore** project. + +> If you are using another IDE than the Visual Studio, you can use `dotnet-ef` tool as [documented here](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli#create-a-migration). + +Finally, run the **CustomizeUserDemo.DbMigrator** project to update the database. + +When we updated the database, you can see that the `Title` and `Reputation` columns are added to the `Users` table. + +![user-table](./user-table.png) + +## Step-3 +Open the `CustomizeUserDemoModuleExtensionConfigurator` in the **CustomizeUserDemo.Domain.Shared** project, and change the contents of the `ConfigureExtraProperties` method as shown below: +```csharp +private static void ConfigureExtraProperties() +{ + ObjectExtensionManager.Instance.Modules().ConfigureIdentity(identity => + { + identity.ConfigureUser(user => + { + user.AddOrUpdateProperty( + UserConsts.TitlePropertyName, + options => + { + options.Attributes.Add(new RequiredAttribute()); + options.Attributes.Add( + new StringLengthAttribute(UserConsts.MaxTitleLength) + ); + } + ); + user.AddOrUpdateProperty( + UserConsts.ReputationPropertyName, + options => + { + options.DefaultValue = UserConsts.MinReputationValue; + options.Attributes.Add( + new RangeAttribute(UserConsts.MinReputationValue, UserConsts.MaxReputationValue) + ); + } + ); + }); + }); +} +``` + +That's it. Now let's run the application and look at the Identity user page. You can also try to edit and recreate a record if you want, it will work even though we haven't done anything extra. Here is the magic code behind ABP framework. + +If there is a situation you want to add, you can click the contribute button or make a comment. Also, if you like the article, don't forget to share it :) + +Happy coding :) diff --git a/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/added-new-migration.png b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/added-new-migration.png new file mode 100755 index 0000000000..d459fdeed2 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/added-new-migration.png differ diff --git a/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/custom-identity-user-list.png b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/custom-identity-user-list.png new file mode 100644 index 0000000000..896ed947aa Binary files /dev/null and b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/custom-identity-user-list.png differ diff --git a/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/initial-project.png b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/initial-project.png new file mode 100755 index 0000000000..b64e93a99f Binary files /dev/null and b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/initial-project.png differ diff --git a/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/new-user.png b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/new-user.png new file mode 100644 index 0000000000..d3a5c66198 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/new-user.png differ diff --git a/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/nuget-package-manager.png b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/nuget-package-manager.png new file mode 100755 index 0000000000..680bc9d2e7 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/nuget-package-manager.png differ diff --git a/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/user-table.png b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/user-table.png new file mode 100755 index 0000000000..5bb71b8325 Binary files /dev/null and b/docs/en/Community-Articles/2022-07-19-How-To-Add-Custom-Property-To-The-User-Entity/user-table.png differ diff --git a/docs/en/Deploy-azure-app-service.md b/docs/en/Deploy-azure-app-service.md new file mode 100644 index 0000000000..9e0309f3b9 --- /dev/null +++ b/docs/en/Deploy-azure-app-service.md @@ -0,0 +1,452 @@ +# Deploying ABP Project to Azure App Service + +In this document, you will learn how to create and deploy your first ABP web app to [Azure App Service](https://docs.microsoft.com/en-us/azure/app-service/overview). The App Service supports various versions of .NET apps, and provides a highly scalable, self-patching web hosting service. ABP web apps are cross-platform and can be hosted on Linux, Windows or MacOS. + +****Prerequisites**** + +- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/dotnet). +- A GitHub account [Create an account for free](http://github.com/). + + + +## Creating a new ABP application + +Create a repository on [GitHub.com](https://github.com/) (keep all settings as default). + +Open the command prompt and clone the repository into a folder on your computer + +```bash +git clone https://github.com/your-username/your-repository-name.git +``` + +Check your dotnet version. It should be at least 3.1.x + +```bash +dotnet --version +``` + +Install or update the [ABP CLI](https://docs.abp.io/en/abp/latest/cli) with the following command: + +```bash +dotnet tool install -g Volo.Abp.Cli || dotnet tool update -g Volo.Abp.Cli +``` + +Open the command prompt in the *GitHub repository folder* and create a new ABP Blazor solution with the command below: + +```bash +abp new YourAppName -u blazor +``` + + + +## Running the application + +Open the command prompt in the *[YourAppName].DbMigrator* project and enter the command below to apply the database migrations: + +```bash +dotnet run +``` + +Open the command prompt in the *[YourAppName].HttpApi.Host* project to run the API project: + +```bash +dotnet run +``` + +Navigate to the *applicationUrl* specified in *the launchSettings.json* file of the *[YourAppName].HttpApi.Host project*. You should get the *Swagger window* + +Open the command prompt in the *[YourAppName].Blazor* folder and enter the command below to run the Blazor project: + +```bash +dotnet run +``` + +Navigate to the *applicationUrl* specified in the *launchSettings.json* file of the *[YourAppName].Blazor* project and you should see the landing page. + +Stop both the *API* and the *Blazor* project by pressing **CTRL+C** + + + +## Committing to GitHub + +Before the GitHub commit, you have to delete the line "**/wwwroot/libs/*" at *.gitignore* file. + +![azdevops-23](images/azdevops-23.png) + +Open the command prompt in the root folder of your project and *add, commit and push* all your changes to your GitHub repository: + +```bash +git add . +git commit -m initialcommit +git push +``` + + + +## Configuring Azure database connection string + +Create a SQL database on Azure and change the connection string in all the *appsettings.json* files. + +* Login into [Azure Portal](https://portal.azure.com/) + +* Click **Create a resource** + +* Search for *SQL Database* + +* Click the **Create** button in the *SQL Database window* + +* Create a new resource group. Name it *rg[YourAppName]* + +* Enter *[YourAppName]Db* as database name + +* Create a new Server and name it *[yourappname]server* + +* Enter a serveradmin login and passwords. Click the **OK** button + +* Select your *Location* + +* Check *Allow Azure services to access server* + +* Click **Configure database**. Go to the *Basic* version and click the **Apply** button + +* Click the **Review + create** button. Click **Create** + +* Click **Go to resource** and click **SQL server** when the SQL Database is created + +* Click **Networking** under Security left side menu + +* Select **Selected networks** and click **Add your client IP$ address** at the Firewall rules + +* Select **Allow Azure and resources to access this seerver** and save + +* Go to your **SQL database**, click **Connection strings** and copy the connection string + +* Copy/paste the *appsettings.json* files of the *[YourAppName].HttpApi.Host* and the *[YourAppName].DbMigrator* project + +* Do not forget to replace {your_password} with the correct server password you entered in Azure SQL Database + + + +## Running DB Migrations + +Open the command prompt in the *[YourAppName].DbMigrator* project again and enter the command below to apply the database migrations: + +```bash +dotnet run +``` + +Open the command prompt in the *[YourAppName].HttpApi.Host* project and enter the command below to check your API is working: + +```bash +dotnet run +``` + +Stop the *[YourAppName].HttpApi.Host* by pressing CTRL+C. + + + +## Committing to GitHub + +Open the command prompt in the root folder of your project and add, commit and push all your changes to your GitHub repository + +```bash +git add . +git commit -m initialcommit +git push +``` + + + +## Setting up the Build pipeline in AzureDevops and publish the Build Artifacts + +* Sign in Azure DevOps + +* Click **New organization** and follow the steps to create a new organisation. Name it [YourAppName]org + +* Enter [YourAppName]Proj as project name in the ***Create a project to get started*** window + +* Select **Public visibility** and click the **Create project** button + +* Click the **Pipelines** button to continue + +* Click the **Create Pipeline** button + + Select GitHub in the Select your repository window + +![azdevops-1](images/azdevops-1.png) + +* Enter the Connection name. *[YourAppName]GitHubConnection* and click **Authorize using OAuth** + +* Select your **GitHub** [YourAppName]repo and click Continue + +* Search for **ASP.NET** in the ***Select a template*** window + +![azdevops-2](images/azdevops-2.png) + +* Select the ASP.NET Core template and click the **Apply** button + +* Add the below commands block as a first step in the pipeline + + ``` + - task: UseDotNet@2 + inputs: + packageType: 'sdk' + version: '6.0.106' + ``` + +![azdevops-18](images/azdevops-18.png) + +* Select **Settings** on the second task(Nugetcommand@2) in the pipeline + +* Select **Feeds in my Nuget.config** and type **Nuget.config** in the text box + +![azdevops-3](images/azdevops-3.png) + +* Add the below commands block to the end of the pipeline + + ``` + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact' + inputs: + PathtoPublish: '$(build.artifactstagingdirectory)' + ArtifactName: '$(Parameters.ArtifactName)' + condition: succeededOrFailed() + ``` + + ![azdevops-4](images/azdevops-4.png) + +``` +# ASP.NET +# Build and test ASP.NET projects. +# Add steps that publish symbols, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/apps/aspnet/build-aspnet-4 + +trigger: +- main + +pool: + vmImage: 'windows-latest' + +variables: + solution: '**/*.sln' + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + +steps: +- task: UseDotNet@2 + inputs: + packageType: 'sdk' + version: '6.0.106' + +- task: NuGetToolInstaller@1 + +- task: NuGetCommand@2 + inputs: + command: 'restore' + restoreSolution: '$(solution)' + feedsToUse: 'config' + nugetConfigPath: 'NuGet.config' + +- task: VSBuild@1 + inputs: + solution: '$(solution)' + msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"' + platform: '$(buildPlatform)' + configuration: '$(buildConfiguration)' + +- task: VSTest@2 + inputs: + platform: '$(buildPlatform)' + configuration: '$(buildConfiguration)' + +- task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact' + inputs: + PathtoPublish: '$(build.artifactstagingdirectory)' + ArtifactName: '$(Parameters.ArtifactName)' + publishLocation: 'Container' + condition: succeededOrFailed() +``` + +* Click **Save & queue** in the top menu. Click **Save & queue** again and click **Save and run** to run the Build pipeline + +* When the Build pipeline has finished. Click **1 published; 1 consumed** + + + +## Creating a Web App in the Azure Portal to deploy [YourAppName].HttpApi.Host project + +* Search for Web App in the *Search the Marketplace* field + +* Click the **Create** button in the Web App window + +* Select rg[YourAppName] in the *Resource Group* dropdown + +* Enter [YourAppName]API in the *Name input* field + +* Select code, .NET Core 3.1 (LTS) and windows as *Operating System* + +* Enter [YourAppName]API in the *Name input* field + +* Select .NET Core 3.1 (LTS) in the *Runtime stack* dropdown + +* Select Windows as *Operating System* + +* Select the same *Region* as in the SQL server you created in Part 3 + +![azdevops-5](images/azdevops-5.png) + +* Click **Create new** in the Windows Plan. Name it [YourAppName]ApiWinPlan + +* Click **Change size** in Sku and size. Go to the Dev/Test Free F1 version and click the **Apply** button + +![azdevops-6](images/azdevops-6.png) + +* Click the **Review + create** button. Click the **Create** button + +* Click **Go to resource** when the Web App has been created + + + +## Creating a release pipeline in the AzureDevops and deploy [YourAppName].HttpApi.Host project + +* Sign in into [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) + +* Click [YourAppName]Proj and click **Releases** in the *Pipelines* menu + +* Click the **New pipeline** button in the *No release pipelines found* window + +* Select *Azure App Service deployment* and click the **Apply** button + +![azdevops-7](images/azdevops-7.png) + +* Enter *[YourAppName]staging* in the *Stage name* field in the *Stage* window. And close the window + +* Click **+ Add an artifact** in the *Pipeline* tab + +* Select the **Build** icon as *Source type* in the *Add an artifact* window + +* Select Build pipeline in the *Source (build pipeline)* dropdown and click the **Add** button + +![azdevops-8](images/azdevops-8.png) + +* Click the **Continuous deployment trigger (thunderbolt icon)** + +* Set the toggle to **Enabled** in the the *Continuous deployment trigger* window + +* Click **+ Add** in *No filters added*. Select **Include** in the *Type* dropdown. Select your branch in the *Build branch* dropdown and close the window + +![azdevops-9](images/azdevops-9.png) + +* Click **the little red circle with the exclamation mark** in the *Tasks* tab menu + +* Select your subscription in the *Azure subscription* dropdown. + +![azdevops-10](images/azdevops-10.png) + +* Click **Authorize** and enter your credentials in the next screens + +* After Authorization, select the **[YourAppName]API** in the *App service name* dropdown + +* Click the **Deploy Azure App Service** task + +* Select **[YourAppName].HttpApi.Host.zip** in the *Package or folder* input field + +![azdevops-11](images/azdevops-11.png) + +* Click the **Save** icon in the top menu and click **OK** + +* Click **Create release** in the top menu. Click **Create** to create a release + +* Click the *Pipeline* tab and wait until the Deployment succeeds + +![azdevops-12](images/azdevops-12.png) + +* Open a browser and navigate to the URL of your Web App + +``` +https://[YourAppName]api.azurewebsites.net +``` + +![azdevops-13](images/azdevops-13.png) + + + +## Creating a Web App in Azure Portal to deploy [YourAppName].Blazor project + +* Login into [Azure Portal](https://portal.azure.com/) + +* Click **Create a resource** + +* Search for *Web App* in the *Search the Marketplace* field + +* Click the **Create** button in the *Web App* window + +* Select *rg[YourAppName]* in the *Resource Group* dropdown + +* Enter *[YourAppName]Blazor* in the *Name* input field + +* Select *.NET Core 3.1 (LTS)* in the *Runtime stack* dropdown + +* Select *Windows* as *Operating System* + +* Select the same region as the SQL server you created in Part 3 + +* Select the [YourAppName]ApiWinPlan in the *Windows Plan* dropdown + +![azdevops-14](images/azdevops-14.png) + +* Click the **Review + create** button. Click **Create** button + +* Click **Go to resource** when the Web App has been created + +* Copy the URL of the Blazor Web App for later use + +``` +https://[YourAppName]blazor.azurewebsites.net +``` + + +## Changing the Web App configuration for the Azure App Service + +Copy the URL of the Api Host and Blazor Web App. Change appsettings.json files in the Web App as follows images. + +![azdevops-19](images/azdevops-19.png) + +![azdevops-20](images/azdevops-20.png) + +![azdevops-21](images/azdevops-21.png) + + + +## Adding an extra Stage in the Release pipeline in the AzureDevops to deploy [YourAppName].Blazor project + +* Go to the *Release* pipeline in [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) and click **Edit** + +* Click the **+ Add** link and add a **New Stage** + +![azdevops-15](images/azdevops-15.png) + +* Select *Azure App Service deployment* and click the **Apply** button + +* Enter *BlazorDeployment* in the *Stage name* input field and close the *Stage* window + +* Click the **little red circle with the exclamation mark** in the BlazorDeployment stage + +* Select your subscription in the *Azure subscription* dropdown + +* Select your Blazor Web App in the *App service name* dropdown + +* Click the **Deploy Azure App Service task** + +* Select *[YourAppName].Blazor.zip* in the *Package or folder* input field + +![azdevops-16](images/azdevops-16.png) + +* Click **Save** in the top menu and click the **OK** button after + +* Click **Create release** in the top menu and click the **Create** button + +![azdevops-17](images/azdevops-17.png) + +![azdevops-22](images/azdevops-22.png) diff --git a/docs/en/Deployment/Deploy-Azure-App-Service.md b/docs/en/Deployment/Deploy-Azure-App-Service.md new file mode 100644 index 0000000000..e7536947bf --- /dev/null +++ b/docs/en/Deployment/Deploy-Azure-App-Service.md @@ -0,0 +1,425 @@ +# Deploy Abp Webapp to Azure App Service + +> In this document, you'll learn how to create and deploy your first abp web app to [Azure App Service](https://docs.microsoft.com/en-us/azure/app-service/overview). The App Service supports various versions of .NET apps, and provides a highly scalable, self-patching web hosting service. Abp web apps are cross-platform and can be hosted on Linux and Windows. + +****Prerequisites**** + +- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/dotnet). +- A GitHub account [Create an account for free](http://github.com/). + + +## Create a new ABP Framework application + +Create a repository on [GitHub.com](https://github.com/) (keep all the default settings) + +Open the command prompt and clone the repository into a folder on your computer + +```bash +git clone https://github.com/your-username/your-repository-name.git +``` +Check your dotnet version. It should be at least 3.1.x +```bash +dotnet --version +``` +Install or update the *ABP CLI* using a command line window + +```bash +dotnet tool install -g Volo.Abp.Cli || dotnet tool update -g Volo.Abp.Cli +``` + +Open the command prompt in the *GitHub repository folder* and create a *new abp Blazor solution* with the command below + +```bash +abp new YourAppName -u blazor +``` + +Open the command prompt in the *[YourAppName].DbMigrator* project and enter the command below to apply the database migrations + +```bash +dotnet run +``` + +Open the command prompt in the *[YourAppName].HttpApi.Host* project to run the API project + +```bash +dotnet run +``` + +Navigate to the *applicationUrl* specified in *the launchSettings.json* file of the *[YourAppName].HttpApi.Host project*. You should get the *Swagger window* + +Open the command prompt in the *[YourAppName].Blazor* folder and enter the command below to run the Blazor project + +```bash +dotnet run +``` + +Navigate to the *applicationUrl* specified in the *launchSettings.json* file of the *[YourAppName].Blazor* project. You should get the *ABP Framework Welcome window* + +Stop both the *API* and the *Blazor* project by pressing **CTRL+C** + +Before the github commit, you have to delete "**/wwwroot/libs/*" at *.gitignore* file. + +![azdevops-23](../images/azdevops-23.png) + +Open the command prompt in the root folder of your project and *add, commit and push* all your changes to your GitHub repository + +```bash +git add . +git commit -m initialcommit +git push +``` + + +## Create a SQL Database on Azure and change the connection string in the appsettings.json files + +* Login into [Azure Portal](https://portal.azure.com/) + +* Click **Create a resource** + +* Search for *SQL Database* + +* Click the **Create** button in the *SQL Database window* + +* Create a new resource group. Name it *rg[YourAppName]* + +* Enter *[YourAppName]Db* as database name + +* Create a new Server and name it *[yourappname]server* + +* Enter a serveradmin login and passwords. Click the **OK** button + +* Select your *Location* + +* Check *Allow Azure services to access server* + +* Click **Configure database**. Go to the *Basic* version and click the **Apply** button + +* Click the **Review + create** button. Click **Create** + +* Click **Go to resource** and click **SQL server** when the SQL Database is created + +* Click **Networking** under Security left side menu + +* Select **Selected networks** and click **Add your client IP$ address** at the Firewall rules + +* Select **Allow Azure and resources to access this seerver** and save + +* Go to your **SQL database**, click **Connection strings** and copy the connection string + +* Copy/paste the appsettings.json files of the [YourAppName].HttpApi.Host and the [YourAppName].DbMigrator project + +* Do not forget to replace {your_password} with the correct server password you entered in Azure SQL Database + +Open the command prompt in the [YourAppName].DbMigrator project again and enter the command below to apply the database migrations + +```bash +dotnet run +``` +Open the command prompt in the [YourAppName].HttpApi.Host project and enter the command below to check your API is working + +```bash +dotnet run +``` + +Stop the [YourAppName].HttpApi.Host by entering CTRL+C + +Open the command prompt in the root folder of your project and add, commit and push all your changes to your GitHub repository +```bash +git add . +git commit -m initialcommit +git push +``` + + +## Set up the Build pipeline in AzureDevops and publish the Build Artifacts + +* Sign in into Azure DevOps + +* Click **New organization** and follow the steps to create a new organisation. Name it [YourAppName]org + +* Enter [YourAppName]Proj as project name in the ***Create a project to get started*** window + +* Select **Public visibility** and click the **Create project** button + +* Click the **Pipelines** button to continue + +* Click the **Create Pipeline** button + + Select GitHub in the Select your repository window + +![azdevops-1](../images/azdevops-1.png) + +* Enter the Connection name. [YourAppName]GitHubConnection and click **Authorize using OAuth** + +* Select your **GitHub** [YourAppName]repo and click Continue + +* Search for **ASP.NET** in the ***Select a template*** window + +![azdevops-2](../images/azdevops-2.png) + +* Select the ASP.NET Core template and click the **Apply** button + +* Add the below commands block as a first step in the pipeline + + ``` + - task: UseDotNet@2 + inputs: + packageType: 'sdk' + version: '6.0.106' + ``` + +![azdevops-18](../images/azdevops-18.png) + +* Select **Settings** on the second task(Nugetcommand@2) in the pipeline + +* Select **Feeds in my Nuget.config** and type **Nuget.config** in the text box + +![azdevops-3](../images/azdevops-3.png) + +* Add the below commands block to the end of the pipeline + + ``` + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact' + inputs: + PathtoPublish: '$(build.artifactstagingdirectory)' + ArtifactName: '$(Parameters.ArtifactName)' + condition: succeededOrFailed() + ``` +![azdevops-4](../images/azdevops-4.png) + +``` +# ASP.NET +# Build and test ASP.NET projects. +# Add steps that publish symbols, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/apps/aspnet/build-aspnet-4 + +trigger: +- main + +pool: + vmImage: 'windows-latest' + +variables: + solution: '**/*.sln' + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + +steps: +- task: UseDotNet@2 + inputs: + packageType: 'sdk' + version: '6.0.106' + +- task: NuGetToolInstaller@1 + +- task: NuGetCommand@2 + inputs: + command: 'restore' + restoreSolution: '$(solution)' + feedsToUse: 'config' + nugetConfigPath: 'NuGet.config' + +- task: VSBuild@1 + inputs: + solution: '$(solution)' + msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"' + platform: '$(buildPlatform)' + configuration: '$(buildConfiguration)' + +- task: VSTest@2 + inputs: + platform: '$(buildPlatform)' + configuration: '$(buildConfiguration)' + +- task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact' + inputs: + PathtoPublish: '$(build.artifactstagingdirectory)' + ArtifactName: '$(Parameters.ArtifactName)' + publishLocation: 'Container' + condition: succeededOrFailed() +``` + +* Click **Save & queue** in the top menu. Click **Save & queue** again and click **Save and run** to run the Build pipeline + +* When the Build pipeline has finished. Click **1 published; 1 consumed** + + + +## Create a Web App in the Azure Portal to deploy [YourAppName].HttpApi.Host project + +* Search for Web App in the *Search the Marketplace* field + +* Click the **Create** button in the Web App window + +* Select rg[YourAppName] in the *Resource Group* dropdown + +* Enter [YourAppName]API in the *Name input* field + +* Select code, .NET Core 3.1 (LTS) and windows as *Operating System* + +* Enter [YourAppName]API in the *Name input* field + +* Select .NET Core 3.1 (LTS) in the *Runtime stack* dropdown + +* Select Windows as *Operating System* + +* Select the same *Region* as in the SQL server you created in Part 3 + +![azdevops-5](../images/azdevops-5.png) + +* Click **Create new** in the Windows Plan. Name it [YourAppName]ApiWinPlan + +* Click **Change size** in Sku and size. Go to the Dev/Test Free F1 version and click the **Apply** button + +![azdevops-6](../images/azdevops-6.png) + +* Click the **Review + create** button. Click the **Create** button + +* Click **Go to resource** when the Web App has been created + + + +## Create a Release pipeline in the AzureDevops and deploy [YourAppName].HttpApi.Host project + +* Sign in into [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) + +* Click [YourAppName]Proj and click **Releases** in the *Pipelines* menu + +* Click the **New pipeline** button in the *No release pipelines found* window + +* Select *Azure App Service deployment* and click the **Apply** button + +![azdevops-7](../images/azdevops-7.png) + +* Enter *[YourAppName]staging* in the *Stage name* field in the *Stage* window. And close the window + +* Click **+ Add an artifact** in the *Pipeline* tab + +* Select the **Build** icon as *Source type* in the *Add an artifact* window + +* Select Build pipeline in the *Source (build pipeline)* dropdown and click the **Add** button + +![azdevops-8](../images/azdevops-8.png) + +* Click the **Continuous deployment trigger (thunderbolt icon)** + +* Set the toggle to **Enabled** in the the *Continuous deployment trigger* window + +* Click **+ Add** in *No filters added*. Select **Include** in the *Type* dropdown. Select your branch in the *Build branch* dropdown and close the window + +![azdevops-9](../images/azdevops-9.png) + +* Click **the little red circle with the exclamation mark** in the *Tasks* tab menu + +* Select your subscription in the *Azure subscription* dropdown. + +![azdevops-10](../images/azdevops-10.png) + +* Click **Authorize** and enter your credentials in the next screens + +* After Authorization, select the **[YourAppName]API** in the *App service name* dropdown + +* Click the **Deploy Azure App Service** task + +* Select **[YourAppName].HttpApi.Host.zip** in the *Package or folder* input field + +![azdevops-11](../images/azdevops-11.png) + +* Click the **Save** icon in the top menu and click **OK** + +* Click **Create release** in the top menu. Click **Create** to create a release + +* Click the *Pipeline* tab and wait until the Deployment succeeds + +![azdevops-12](../images/azdevops-12.png) + +* Open a browser and navigate to the URL of your Web App + +``` +https://[YourAppName]api.azurewebsites.net +``` + +![azdevops-13](../images/azdevops-13.png) + + + +## Create a Web App in Azure Portal to deploy [YourAppName].Blazor project + +* Login into [Azure Portal](https://portal.azure.com/) + +* Click **Create a resource** + +* Search for *Web App* in the *Search the Marketplace* field + +* Click the **Create** button in the *Web App* window + +* Select *rg[YourAppName]* in the *Resource Group* dropdown + +* Enter *[YourAppName]Blazor* in the *Name* input field + +* Select *.NET Core 3.1 (LTS)* in the *Runtime stack* dropdown + +* Select *Windows* as *Operating System* + +* Select the same region as the SQL server you created in Part 3 + +* Select the [YourAppName]ApiWinPlan in the *Windows Plan* dropdown + +![azdevops-14](../images/azdevops-14.png) + +* Click the **Review + create** button. Click **Create** button + +* Click **Go to resource** when the Web App has been created + +* Copy the URL of the Blazor Web App for later use + +``` +https://[YourAppName]blazor.azurewebsites.net +``` + + +## Change the Web App configuration for the Azure App Service + +Copy the URL of the Api Host and Blazor Web App. Change appsettings.json files in the Web App as follows images. + +![azdevops-19](../images/azdevops-19.png) + +![azdevops-20](../images/azdevops-20.png) + +![azdevops-21](../images/azdevops-21.png) + + + +## Add an extra Stage in the Release pipeline in the AzureDevops to deploy [YourAppName].Blazor project + +* Go to the *Release* pipeline in [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) and click **Edit** + +* Click the **+ Add** link and add a **New Stage** + +![azdevops-15](../images/azdevops-15.png) + +* Select *Azure App Service deployment* and click the **Apply** button + +* Enter *BlazorDeployment* in the *Stage name* input field and close the *Stage* window + +* Click the **little red circle with the exclamation mark** in the BlazorDeployment stage + +* Select your subscription in the *Azure subscription* dropdown + +* Select your Blazor Web App in the *App service name* dropdown + +* Click the **Deploy Azure App Service task** + +* Select *[YourAppName].Blazor.zip* in the *Package or folder* input field + +![azdevops-16](../images/azdevops-16.png) + +* Click **Save** in the top menu and click the **OK** button after + +* Click **Create release** in the top menu and click the **Create** button + +![azdevops-17](../images/azdevops-17.png) + +![azdevops-22](../images/azdevops-22.png) \ No newline at end of file diff --git a/docs/en/Deployment/Index.md b/docs/en/Deployment/Index.md index dc1cca300e..a1c2e2d5f8 100644 --- a/docs/en/Deployment/Index.md +++ b/docs/en/Deployment/Index.md @@ -6,4 +6,7 @@ However, there are some topics that you should care about when you are deploying ## Guides -* [Deploying to a clustered environment](Clustered-Environment.md): Explains how to configure your application when you want to run multiple instances of your application concurrently. \ No newline at end of file +* [Deploying to a clustered environment](Clustered-Environment.md): Explains how to configure your application when you want to run multiple instances of your application concurrently. + + +* [Deploy Abp Webapp to Azure App Service](Deploy-Azure-App-Service.md): Explains how to create and deploy your first abp web app to [Azure App Service](https://docs.microsoft.com/en-us/azure/app-service/overview). \ No newline at end of file diff --git a/docs/en/Modules/OpenIddict.md b/docs/en/Modules/OpenIddict.md index 9e603f76a8..6dc1224e59 100644 --- a/docs/en/Modules/OpenIddict.md +++ b/docs/en/Modules/OpenIddict.md @@ -4,6 +4,14 @@ This module implements the domain logic and database integrations, but not provides any UI. Management UI is useful if you need to add applications and scopes on the fly. In this case, you may build the management UI yourself or consider to purchase the [ABP Commercial](https://commercial.abp.io/) which provides the management UI for this module. +## How to Install + +This module comes as pre-installed (as NuGet/NPM packages) when you [create a new solution](https://abp.io/get-started) with the ABP Framework. You can continue to use it as package and get updates easily, or you can include its source code into your solution (see `get-source` [CLI](../CLI.md) command) to develop your custom module. + +### The Source Code + +The source code of this module can be accessed [here](https://github.com/abpframework/abp/tree/dev/modules/openiddict). The source code is licensed with [MIT](https://choosealicense.com/licenses/mit/), so you can freely use and customize it. + ## Relations to Other Modules This module is based on the [Identity Module](Identity.md) and have an [integration package](https://www.nuget.org/packages/Volo.Abp.Account.Web.OpenIddict) with the [Account Module](Account.md). @@ -206,6 +214,10 @@ If you need to customize OpenIddict, you need to replace/delete/add new handlers Please refer to: https://documentation.openiddict.com/guides/index.html#events-model +## Migrating Guide + +[Migrating from IdentityServer to OpenIddict Step by Step Guide ](../Migration-Guides/OpenIddict-Step-by-Step.md) + ## Sponsor Please consider sponsoring this project: https://github.com/sponsors/kevinchalet diff --git a/docs/en/Modules/Setting-Management.md b/docs/en/Modules/Setting-Management.md index e54993cf79..354fbdd539 100644 --- a/docs/en/Modules/Setting-Management.md +++ b/docs/en/Modules/Setting-Management.md @@ -118,7 +118,13 @@ The order of the providers are important. Providers are executed in the reverse ## Setting Management UI -Setting Mangement module provided the email setting UI by default, and it is extensible; You can add your tabs to this page for your application settings. +Setting Mangement module provided the email setting UI by default. + +![EmailSettingUi](../images/setting-management-email-ui.png) + +> You can click the Send test email button to send a test email to check your email settings. + +Setting it is extensible; You can add your tabs to this page for your application settings. ### MVC UI @@ -302,5 +308,4 @@ export class AppComponent { Navigate to `/setting-management` route to see the changes: -![Custom Settings Tab](../images/custom-settings.png) - +![Custom Settings Tab](../images/custom-settings.png) \ No newline at end of file diff --git a/docs/en/UI/Angular/Theming.md b/docs/en/UI/Angular/Theming.md index c7f303763d..435acc6930 100644 --- a/docs/en/UI/Angular/Theming.md +++ b/docs/en/UI/Angular/Theming.md @@ -16,10 +16,11 @@ In order to accomplish these goals, ABP Framework; ### Current Themes -Currently, two themes are **officially provided**: +Currently, three themes are **officially provided**: * The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/commercial/angular) and [lite](../../Themes/LeptonXLite/Angular.md) choices. ## Overall diff --git a/docs/en/UI/AspNetCore/Overall.md b/docs/en/UI/AspNetCore/Overall.md index 8cd9dd3f5e..bc24c56fb8 100644 --- a/docs/en/UI/AspNetCore/Overall.md +++ b/docs/en/UI/AspNetCore/Overall.md @@ -32,10 +32,11 @@ ABP Framework provides a complete [Theming](Theming.md) system with the followin ### Current Themes -Currently, two themes are **officially provided**: +Currently, three themes are **officially provided**: * The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/commercial/mvc) and [lite](../../Themes/LeptonXLite/AspNetCore.md) choices. There are also some community-driven themes for the ABP Framework (you can search on the web). diff --git a/docs/en/UI/AspNetCore/Page-Header.md b/docs/en/UI/AspNetCore/Page-Header.md index f6ec3074de..8b045c89ab 100644 --- a/docs/en/UI/AspNetCore/Page-Header.md +++ b/docs/en/UI/AspNetCore/Page-Header.md @@ -23,6 +23,8 @@ Page Title can be set as shown in the example below: ### Breadcrumb > **The [Basic Theme](Basic-Theme.md) currently doesn't implement the breadcrumbs.** +> +> The [LeptonX Lite Theme](../../Themes/LeptonXLite/AspNetCore.md) supports breadcrumbs. Breadcrumb items can be added to the `PageLayout.Content.BreadCrumb`. @@ -48,11 +50,13 @@ Any item that you add is inserted between Home and Current Page items. You can a ### The Selected Menu Item > **The [Basic Theme](Basic-Theme.md) currently doesn't implement the selected menu item since it is not applicable to the top menu which is the only option for the Basic Theme for now.** +> +> The [LeptonX Lite Theme](../../Themes/LeptonXLite/AspNetCore.md) supports selected menu item. You can set the Menu Item name related to this page: -````csharp +```csharp PageLayout.Content.MenuItemName = "BookStore.Books"; -```` +``` Menu item name should match a unique menu item name defined using the [Navigation / Menu](Navigation-Menu.md) system. In this case, it is expected from the theme to make the menu item "active" in the main menu. \ No newline at end of file diff --git a/docs/en/UI/AspNetCore/Toolbars.md b/docs/en/UI/AspNetCore/Toolbars.md index d82150b47e..975157151f 100644 --- a/docs/en/UI/AspNetCore/Toolbars.md +++ b/docs/en/UI/AspNetCore/Toolbars.md @@ -8,6 +8,12 @@ There is only one **standard toolbar** named "Main" (defined as a constant: `Sta In the screenshot above, there are two items added to the main toolbar: Language switch component & user menu. You can add your own items here. +Also, [LeptonX Lite Theme](../../Themes/LeptonXLite/AspNetCore.md) has 2 different toolbars for desktop and mobile views which defined as constants: `LeptonXLiteToolbars.Main`, `LeptonXLiteToolbars.MainMobile`. + +| LeptonXLiteToolbars.Main | LeptonXLiteToolbars.MainMobile | +| :---: | :---: | +| ![leptonx](../../images/leptonxlite-toolbar-main-example.png) | ![leptonx](../../images/leptonxlite-toolbar-mainmobile-example.png) | + ## Example: Add a Notification Icon In this example, we will add a **notification (bell) icon** to the left of the language switch item. A item in the toolbar should be a **view component**. So, first, create a new view component in your project: diff --git a/docs/en/UI/Blazor/Overall.md b/docs/en/UI/Blazor/Overall.md index ff361d6784..402d61acb0 100644 --- a/docs/en/UI/Blazor/Overall.md +++ b/docs/en/UI/Blazor/Overall.md @@ -75,10 +75,11 @@ ABP Framework provides a complete [Theming](Theming.md) system with the followin ### Current Themes -Currently, two themes are **officially provided**: +Currently, three themes are **officially provided**: * The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**. * The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license. +* The [LeptonX Theme](https://x.leptontheme.com/) is a theme that has both [commercial](https://docs.abp.io/en/commercial/latest/themes/lepton-x/commercial/blazor) and [lite](../../Themes/LeptonXLite/Blazor.md) choices. ### Base Libraries diff --git a/docs/en/UI/Blazor/Page-Header.md b/docs/en/UI/Blazor/Page-Header.md index 29cb006bd3..1bdc9c93c0 100644 --- a/docs/en/UI/Blazor/Page-Header.md +++ b/docs/en/UI/Blazor/Page-Header.md @@ -16,6 +16,8 @@ Once you add the `PageHeader` component to your page, you can control the relate ## Breadcrumb > **The [Basic Theme](Basic-Theme.md) currently doesn't implement the breadcrumbs.** +> +> The [LeptonX Lite Theme](../../Themes/LeptonXLite/Blazor.md) supports breadcrumbs. Breadcrumbs can be added using the `BreadcrumbItems` property. diff --git a/docs/en/UI/Blazor/Page-Layout.md b/docs/en/UI/Blazor/Page-Layout.md index 49ed1659f4..c6f3d62000 100644 --- a/docs/en/UI/Blazor/Page-Layout.md +++ b/docs/en/UI/Blazor/Page-Layout.md @@ -42,6 +42,10 @@ Menu item name can be set on runtime too. } ``` + +![leptonx selected menu item](../../images/leptonx-selected-menu-item-example.gif) + + > Be aware, The [Basic Theme](../Blazor/Basic-Theme.md) currently doesn't support the selected menu item since it is not applicable to the top menu. ## BreadCrumbs diff --git a/docs/en/UI/Blazor/Toolbars.md b/docs/en/UI/Blazor/Toolbars.md index 3ff1b7f135..c0878f080a 100644 --- a/docs/en/UI/Blazor/Toolbars.md +++ b/docs/en/UI/Blazor/Toolbars.md @@ -8,6 +8,12 @@ There is only one **standard toolbar** named "Main" (defined as a constant: `Sta In the screenshot above, there are two items added to the main toolbar: Language switch component & user menu. You can add your own items here. +Also, [LeptonX Lite Theme](../../Themes/LeptonXLite/Blazor.md) has 2 different toolbars for desktop and mobile views which defined as constants: `LeptonXLiteToolbars.Main`, `LeptonXLiteToolbars.MainMobile`. + +| LeptonXLiteToolbars.Main | LeptonXLiteToolbars.MainMobile | +| :---: | :---: | +| ![leptonx](../../images/leptonxlite-toolbar-main-example.png) | ![leptonx](../../images/leptonxlite-toolbar-mainmobile-example.png) | + ## Example: Add a Notification Icon In this example, we will add a **notification (bell) icon** to the left of the language switch item. A item in the toolbar should be a **Razor Component**. So, first, create a new razor component in your project (the location of the component doesn't matter): diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index db63a7136b..4b82495a00 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -43,6 +43,10 @@ "text": "WPF Application", "path": "Startup-Templates/WPF.md" }, + { + "text": "MAUI", + "path": "Startup-Templates/MAUI.md" + }, { "text": "Empty Web Project", "path": "Getting-Started-AspNetCore-Application.md" @@ -1278,6 +1282,10 @@ { "text": "Deploying to a Clustered Environment", "path": "Deployment/Clustered-Environment.md" + }, + { + "text": "Deploy Abp Webapp to Azure App Service", + "path": "Deployment/Deploy-Azure-App-Service.md" } ] }, diff --git a/docs/en/images/azdevops-1.png b/docs/en/images/azdevops-1.png new file mode 100644 index 0000000000..78181e4b7c Binary files /dev/null and b/docs/en/images/azdevops-1.png differ diff --git a/docs/en/images/azdevops-10.png b/docs/en/images/azdevops-10.png new file mode 100644 index 0000000000..75a273ba52 Binary files /dev/null and b/docs/en/images/azdevops-10.png differ diff --git a/docs/en/images/azdevops-11.png b/docs/en/images/azdevops-11.png new file mode 100644 index 0000000000..422a0ddbc0 Binary files /dev/null and b/docs/en/images/azdevops-11.png differ diff --git a/docs/en/images/azdevops-12.png b/docs/en/images/azdevops-12.png new file mode 100644 index 0000000000..e1bc1399f9 Binary files /dev/null and b/docs/en/images/azdevops-12.png differ diff --git a/docs/en/images/azdevops-13.png b/docs/en/images/azdevops-13.png new file mode 100644 index 0000000000..e83f972b20 Binary files /dev/null and b/docs/en/images/azdevops-13.png differ diff --git a/docs/en/images/azdevops-14.png b/docs/en/images/azdevops-14.png new file mode 100644 index 0000000000..a4bd3b65d0 Binary files /dev/null and b/docs/en/images/azdevops-14.png differ diff --git a/docs/en/images/azdevops-15.png b/docs/en/images/azdevops-15.png new file mode 100644 index 0000000000..ed4b9dc6a0 Binary files /dev/null and b/docs/en/images/azdevops-15.png differ diff --git a/docs/en/images/azdevops-16.png b/docs/en/images/azdevops-16.png new file mode 100644 index 0000000000..402f6b7d5e Binary files /dev/null and b/docs/en/images/azdevops-16.png differ diff --git a/docs/en/images/azdevops-17.png b/docs/en/images/azdevops-17.png new file mode 100644 index 0000000000..5441a87035 Binary files /dev/null and b/docs/en/images/azdevops-17.png differ diff --git a/docs/en/images/azdevops-18.png b/docs/en/images/azdevops-18.png new file mode 100644 index 0000000000..8e358172d5 Binary files /dev/null and b/docs/en/images/azdevops-18.png differ diff --git a/docs/en/images/azdevops-19.png b/docs/en/images/azdevops-19.png new file mode 100644 index 0000000000..ff282de4d5 Binary files /dev/null and b/docs/en/images/azdevops-19.png differ diff --git a/docs/en/images/azdevops-2.png b/docs/en/images/azdevops-2.png new file mode 100644 index 0000000000..9982431409 Binary files /dev/null and b/docs/en/images/azdevops-2.png differ diff --git a/docs/en/images/azdevops-20.png b/docs/en/images/azdevops-20.png new file mode 100644 index 0000000000..f8a00be927 Binary files /dev/null and b/docs/en/images/azdevops-20.png differ diff --git a/docs/en/images/azdevops-21.png b/docs/en/images/azdevops-21.png new file mode 100644 index 0000000000..7d55d11150 Binary files /dev/null and b/docs/en/images/azdevops-21.png differ diff --git a/docs/en/images/azdevops-22.png b/docs/en/images/azdevops-22.png new file mode 100644 index 0000000000..f103c8f56f Binary files /dev/null and b/docs/en/images/azdevops-22.png differ diff --git a/docs/en/images/azdevops-23.png b/docs/en/images/azdevops-23.png new file mode 100644 index 0000000000..7318b82d13 Binary files /dev/null and b/docs/en/images/azdevops-23.png differ diff --git a/docs/en/images/azdevops-3.png b/docs/en/images/azdevops-3.png new file mode 100644 index 0000000000..0ede96f42a Binary files /dev/null and b/docs/en/images/azdevops-3.png differ diff --git a/docs/en/images/azdevops-4.png b/docs/en/images/azdevops-4.png new file mode 100644 index 0000000000..52e025913c Binary files /dev/null and b/docs/en/images/azdevops-4.png differ diff --git a/docs/en/images/azdevops-5.png b/docs/en/images/azdevops-5.png new file mode 100644 index 0000000000..31384e5de5 Binary files /dev/null and b/docs/en/images/azdevops-5.png differ diff --git a/docs/en/images/azdevops-6.png b/docs/en/images/azdevops-6.png new file mode 100644 index 0000000000..cc493dfd43 Binary files /dev/null and b/docs/en/images/azdevops-6.png differ diff --git a/docs/en/images/azdevops-7.png b/docs/en/images/azdevops-7.png new file mode 100644 index 0000000000..e5f0cda151 Binary files /dev/null and b/docs/en/images/azdevops-7.png differ diff --git a/docs/en/images/azdevops-8.png b/docs/en/images/azdevops-8.png new file mode 100644 index 0000000000..5c2f996cf8 Binary files /dev/null and b/docs/en/images/azdevops-8.png differ diff --git a/docs/en/images/azdevops-9.png b/docs/en/images/azdevops-9.png new file mode 100644 index 0000000000..0c8a7b557e Binary files /dev/null and b/docs/en/images/azdevops-9.png differ diff --git a/docs/en/images/breadcrumbs-example.png b/docs/en/images/breadcrumbs-example.png index 17ae5f8ba5..8b4bbc62d7 100644 Binary files a/docs/en/images/breadcrumbs-example.png and b/docs/en/images/breadcrumbs-example.png differ diff --git a/docs/en/images/leptonx-selected-menu-item-example.gif b/docs/en/images/leptonx-selected-menu-item-example.gif new file mode 100644 index 0000000000..8f1170cd55 Binary files /dev/null and b/docs/en/images/leptonx-selected-menu-item-example.gif differ diff --git a/docs/en/images/leptonxlite-toolbar-main-example.png b/docs/en/images/leptonxlite-toolbar-main-example.png new file mode 100644 index 0000000000..30edcf547b Binary files /dev/null and b/docs/en/images/leptonxlite-toolbar-main-example.png differ diff --git a/docs/en/images/leptonxlite-toolbar-mainmobile-example.png b/docs/en/images/leptonxlite-toolbar-mainmobile-example.png new file mode 100644 index 0000000000..95815b5843 Binary files /dev/null and b/docs/en/images/leptonxlite-toolbar-mainmobile-example.png differ diff --git a/docs/en/images/setting-management-email-ui.png b/docs/en/images/setting-management-email-ui.png new file mode 100644 index 0000000000..f8f1270c15 Binary files /dev/null and b/docs/en/images/setting-management-email-ui.png differ diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index f890534795..f108bbcfec 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -123,6 +123,7 @@ abp new Acme.BookStore * `module`: [Module template](Startup-Templates/Module.md). 其他选项: * `--no-ui`: 不包含UI.仅创建服务模块(也称为微服务 - 没有UI). * **`console`**: [Console template](Startup-Templates/Console.md). + * **`maui`**: [Maui template](Startup-Templates/MAUI.md). * **`app-nolayers`**: 应用程序单层模板 * `--ui` 或者 `-u`: 指定ui框架.默认`mvc`框架.其他选项: * `mvc`: ASP.NET Core MVC. diff --git a/docs/zh-Hans/Modules/Setting-Management.md b/docs/zh-Hans/Modules/Setting-Management.md index c99397e4b4..242553c2c9 100644 --- a/docs/zh-Hans/Modules/Setting-Management.md +++ b/docs/zh-Hans/Modules/Setting-Management.md @@ -87,7 +87,13 @@ namespace Demo ## Setting Management UI. -设置管理模块默认提供了邮件设置页面并且它是可扩展的; 你可以为你的应用程序设置添加设置标签到设置页面. +设置管理模块默认提供了邮件设置页面. + +![EmailSettingUi](../images/setting-management-email-ui.png) + +> 你可以点击发送测试邮件按钮发送一封测试邮件来检查你的邮件设置. + +设置UI是可扩展的; 你可以为你的应用程序设置添加设置标签到设置页面. ### MVC UI diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json index 203000c6c6..be30753fb3 100644 --- a/docs/zh-Hans/docs-nav.json +++ b/docs/zh-Hans/docs-nav.json @@ -61,6 +61,10 @@ { "text": "WPF", "path": "Startup-Templates/WPF.md" + }, + { + "text": "MAUI", + "path": "Startup-Templates/MAUI.md" } ] }, diff --git a/docs/zh-Hans/images/setting-management-email-ui.png b/docs/zh-Hans/images/setting-management-email-ui.png new file mode 100644 index 0000000000..f8f1270c15 Binary files /dev/null and b/docs/zh-Hans/images/setting-management-email-ui.png differ diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj index 2ccb77a253..cad3da097a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Demo.csproj @@ -26,7 +26,7 @@ - + diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs index dd9e6cfe62..c0c56053d3 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AspNetCoreAuditLogContributor.cs @@ -1,11 +1,14 @@ using System; +using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.AspNetCore.WebClientInfo; using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; +using Volo.Abp.ExceptionHandling; namespace Volo.Abp.AspNetCore.Auditing; @@ -57,28 +60,46 @@ public class AspNetCoreAuditLogContributor : AuditLogContributor, ITransientDepe public override void PostContribute(AuditLogContributionContext context) { + if (context.AuditInfo.HttpStatusCode != null) + { + return; + } + var httpContext = context.ServiceProvider.GetRequiredService().HttpContext; if (httpContext == null) { return; } - if (context.AuditInfo.HttpStatusCode == null) + if (context.AuditInfo.Exceptions.Any()) { - context.AuditInfo.HttpStatusCode = httpContext.Response.StatusCode; + var httpExceptionStatusCodeFinder = context.ServiceProvider.GetRequiredService(); + foreach (var auditInfoException in context.AuditInfo.Exceptions) + { + var statusCode = httpExceptionStatusCodeFinder.GetStatusCode(httpContext, auditInfoException); + context.AuditInfo.HttpStatusCode = (int) statusCode; + } + + if (context.AuditInfo.HttpStatusCode != null) + { + return; + } } + + context.AuditInfo.HttpStatusCode = httpContext.Response.StatusCode; } protected virtual string BuildUrl(HttpContext httpContext) { //TODO: Add options to include/exclude query, schema and host - var uriBuilder = new UriBuilder(); - - uriBuilder.Scheme = httpContext.Request.Scheme; - uriBuilder.Host = httpContext.Request.Host.Host; - uriBuilder.Path = httpContext.Request.Path.ToString(); - uriBuilder.Query = httpContext.Request.QueryString.ToString(); + var uriBuilder = new UriBuilder + { + Scheme = httpContext.Request.Scheme, + Host = httpContext.Request.Host.Host, + Path = httpContext.Request.Path.ToString(), + Query = httpContext.Request.QueryString.ToString() + }; return uriBuilder.Uri.AbsolutePath; } diff --git a/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo.Abp.Caching.StackExchangeRedis.csproj b/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo.Abp.Caching.StackExchangeRedis.csproj index 2e36b1cef0..d1faed8f5c 100644 --- a/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo.Abp.Caching.StackExchangeRedis.csproj +++ b/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo.Abp.Caching.StackExchangeRedis.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo/Abp/Caching/StackExchangeRedis/AbpRedisCache.cs b/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo/Abp/Caching/StackExchangeRedis/AbpRedisCache.cs index d52a40e5b5..68a59aab2d 100644 --- a/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo/Abp/Caching/StackExchangeRedis/AbpRedisCache.cs +++ b/framework/src/Volo.Abp.Caching.StackExchangeRedis/Volo/Abp/Caching/StackExchangeRedis/AbpRedisCache.cs @@ -15,18 +15,18 @@ namespace Volo.Abp.Caching.StackExchangeRedis; [DisableConventionalRegistration] public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems { - protected static readonly string SetScript; protected static readonly string AbsoluteExpirationKey; protected static readonly string SlidingExpirationKey; protected static readonly string DataKey; protected static readonly long NotPresent; - private static readonly FieldInfo RedisDatabaseField; - private static readonly MethodInfo ConnectMethod; - private static readonly MethodInfo ConnectAsyncMethod; - private static readonly MethodInfo MapMetadataMethod; - private static readonly MethodInfo GetAbsoluteExpirationMethod; - private static readonly MethodInfo GetExpirationInSecondsMethod; + private readonly static FieldInfo SetScriptField; + private readonly static FieldInfo RedisDatabaseField; + private readonly static MethodInfo ConnectMethod; + private readonly static MethodInfo ConnectAsyncMethod; + private readonly static MethodInfo MapMetadataMethod; + private readonly static MethodInfo GetAbsoluteExpirationMethod; + private readonly static MethodInfo GetExpirationInSecondsMethod; protected IDatabase RedisDatabase => GetRedisDatabase(); private IDatabase _redisDatabase; @@ -36,9 +36,11 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems static AbpRedisCache() { var type = typeof(RedisCache); - + RedisDatabaseField = type.GetField("_cache", BindingFlags.Instance | BindingFlags.NonPublic); + SetScriptField = type.GetField("_setScript", BindingFlags.Instance | BindingFlags.NonPublic); + ConnectMethod = type.GetMethod("Connect", BindingFlags.Instance | BindingFlags.NonPublic); ConnectAsyncMethod = type.GetMethod("ConnectAsync", BindingFlags.Instance | BindingFlags.NonPublic); @@ -51,9 +53,6 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems GetExpirationInSecondsMethod = type.GetMethod("GetExpirationInSeconds", BindingFlags.Static | BindingFlags.NonPublic); - SetScript = type.GetField("SetScript", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) - .ToString(); - AbsoluteExpirationKey = type.GetField("AbsoluteExpirationKey", BindingFlags.Static | BindingFlags.NonPublic) ?.GetValue(null).ToString(); @@ -83,14 +82,14 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems ConnectMethod.Invoke(this, Array.Empty()); } - protected virtual Task ConnectAsync(CancellationToken token = default) + protected virtual async Task ConnectAsync(CancellationToken token = default) { if (GetRedisDatabase() != null) { - return Task.CompletedTask; + return; } - return (Task)ConnectAsyncMethod.Invoke(this, new object[] { token }); + await (Task)ConnectAsyncMethod.Invoke(this, new object[] { token }); } public byte[][] GetMany( @@ -283,7 +282,7 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems for (var i = 0; i < itemArray.Length; i++) { - tasks[i] = RedisDatabase.ScriptEvaluateAsync(SetScript, new RedisKey[] { Instance + itemArray[i].Key }, + tasks[i] = RedisDatabase.ScriptEvaluateAsync(GetSetScript(), new RedisKey[] { Instance + itemArray[i].Key }, new RedisValue[] { absoluteExpiration?.Ticks ?? NotPresent, @@ -333,4 +332,9 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems return _redisDatabase; } + + private string GetSetScript() + { + return SetScriptField?.GetValue(this).ToString(); + } } diff --git a/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj b/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj index 62aebd1056..4022d38fee 100644 --- a/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj +++ b/framework/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj @@ -15,7 +15,7 @@ - + diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index 1cffbfe407..cc64d73ff2 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -85,7 +85,13 @@ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransien ConfigureNpmPackagesForTheme(projectArgs); await RunGraphBuildForMicroserviceServiceTemplate(projectArgs); await CreateInitialMigrationsAsync(projectArgs); - await RunInstallLibsForWebTemplateAsync(projectArgs); + + var skipInstallLibs = commandLineArgs.Options.ContainsKey(Options.SkipInstallingLibs.Long) || commandLineArgs.Options.ContainsKey(Options.SkipInstallingLibs.Short); + if (!skipInstallLibs) + { + await RunInstallLibsForWebTemplateAsync(projectArgs); + } + await ConfigurePwaSupportForAngular(projectArgs); OpenRelatedWebPage(projectArgs, template, isTiered, commandLineArgs); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs index b3064146fc..6bd8a78cc8 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs @@ -709,6 +709,12 @@ public abstract class ProjectCreationCommandBase public const string Long = "create-solution-folder"; } + public static class SkipInstallingLibs + { + public const string Short = "sib"; + public const string Long = "skip-installing-libs"; + } + public static class Tiered { public const string Long = "tiered"; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs index 916f861460..33ecad0719 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs @@ -285,14 +285,12 @@ public class ChangeThemeStep : ProjectBuildPipelineStep {"Domain.Shared", "MyCompanyName.MyProjectName.Domain.Shared.csproj"}, {"Application", "MyCompanyName.MyProjectName.Application.csproj"}, {"Application.Contracts", "MyCompanyName.MyProjectName.Application.Contracts.csproj"}, - {"Blazor.WebAssembly", "MyCompanyName.MyProjectName.Blazor.csproj"}, - {"Blazor.Server", "MyCompanyName.MyProjectName.Blazor.Server.csproj"}, {"HttpApi", "MyCompanyName.MyProjectName.HttpApi.csproj"}, - {"HttpApi.Client", "MyCompanyName.MyProjectName.HttpApi.Client.csproj"}, - {"Web.Host", "MyCompanyName.MyProjectName.Web.Host.csproj"}, - {"Web", "MyCompanyName.MyProjectName.Web.csproj"}, + {"HttpApi.Client", "MyCompanyName.MyProjectName.HttpApi.Client.csproj"} }; - + + AddUiProjectToProjects(projects, context); + foreach (var project in projects) { AddLeptonThemeManagementReference(context, project); @@ -314,6 +312,28 @@ public class ChangeThemeStep : ProjectBuildPipelineStep AddLeptonThemeManagementReference(context, microserviceServiceProject); } } + + private void AddUiProjectToProjects(Dictionary projects, ProjectBuildContext context) + { + if (projects.IsNullOrEmpty()) + { + return; + } + + switch (context.BuildArgs.UiFramework) + { + case UiFramework.Mvc: + projects["Web.Host"] = "MyCompanyName.MyProjectName.Web.Host.csproj"; + projects["Web"] = "MyCompanyName.MyProjectName.Web.csproj"; + break; + case UiFramework.Blazor: + projects["Blazor.WebAssembly"] = "MyCompanyName.MyProjectName.Blazor.csproj"; + break; + case UiFramework.BlazorServer: + projects["Blazor.Server"] = "MyCompanyName.MyProjectName.Blazor.csproj"; + break; + } + } private void AddLeptonThemeManagementReference(ProjectBuildContext context, KeyValuePair projectInfo) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/TemplateCodeDeleteStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/TemplateCodeDeleteStep.cs index 44f6d3e0bd..ce61d9775f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/TemplateCodeDeleteStep.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/TemplateCodeDeleteStep.cs @@ -14,6 +14,8 @@ public class TemplateCodeDeleteStep : ProjectBuildPipelineStep file.Name.EndsWith(".json") || file.Name.EndsWith(".gitignore") || file.Name.EndsWith(".yml") || + file.Name.EndsWith(".yaml") || + file.Name.EndsWith(".md") || file.Name.EndsWith(".ps1") || file.Name.EndsWith(".html") || file.Name.EndsWith(".ts") || 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 71f090a576..c6a15389ef 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 @@ -130,6 +130,8 @@ public abstract class MicroserviceTemplateBase : TemplateInfo steps.Add(new RemoveFolderStep("/apps/blazor")); steps.Add(new RemoveProjectFromTyeStep("blazor")); steps.Add(new RemoveProjectFromTyeStep("blazor-server")); + + context.Symbols.Add("ui:angular"); break; case UiFramework.Blazor: @@ -147,7 +149,8 @@ public abstract class MicroserviceTemplateBase : TemplateInfo null, "/apps/blazor/src/MyCompanyName.MyProjectName.Blazor.Server")); steps.Add(new RemoveProjectFromTyeStep("blazor-server")); - + + context.Symbols.Add("ui:blazor"); break; case UiFramework.BlazorServer: @@ -169,7 +172,8 @@ public abstract class MicroserviceTemplateBase : TemplateInfo steps.Add(new TemplateProjectRenameStep("MyCompanyName.MyProjectName.Blazor.Server", "MyCompanyName.MyProjectName.Blazor")); steps.Add(new RenameProjectInTyeStep("blazor-server", "blazor")); - + + context.Symbols.Add("ui:blazor-server"); break; case UiFramework.Mvc: @@ -186,6 +190,8 @@ public abstract class MicroserviceTemplateBase : TemplateInfo steps.Add(new RemoveProjectFromTyeStep("blazor-server")); steps.Add(new RemoveFolderStep("/apps/angular")); + + context.Symbols.Add("ui:mvc"); break; } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index e6c21544b3..7f2831351a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -489,6 +489,7 @@ public class SolutionModuleAdder : ITransientDependency args.Options.Add("t", newProTemplate ? ModuleProTemplate.TemplateName : ModuleTemplate.TemplateName); args.Options.Add("v", version); args.Options.Add("o", Path.Combine(modulesFolderInSolution, module.Name)); + args.Options.Add("sib", true.ToString()); await NewCommand.ExecuteAsync(args); } diff --git a/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj b/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj index 1781a23468..65a67b86bc 100644 --- a/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj +++ b/framework/src/Volo.Abp.Cli/Volo.Abp.Cli.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/AbpConfigurationBuilderOptions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/AbpConfigurationBuilderOptions.cs index f922f2b7da..f9f2ca23ad 100644 --- a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/AbpConfigurationBuilderOptions.cs +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/AbpConfigurationBuilderOptions.cs @@ -21,6 +21,16 @@ public class AbpConfigurationBuilderOptions /// public string FileName { get; set; } = "appsettings"; + /// + /// Whether the file is optional, Default value: true. + /// + public bool Optional { get; set; } = true; + + /// + /// Whether the configuration should be reloaded if the file changes, Default value: true. + /// + public bool ReloadOnChange { get; set; } = true; + /// /// Environment name. Generally used "Development", "Staging" or "Production". /// diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs index 8a14528e03..28ea8326ac 100644 --- a/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/Configuration/ConfigurationHelper.cs @@ -18,11 +18,11 @@ public static class ConfigurationHelper var builder = new ConfigurationBuilder() .SetBasePath(options.BasePath) - .AddJsonFile(options.FileName + ".json", optional: true, reloadOnChange: true); + .AddJsonFile(options.FileName + ".json", optional: options.Optional, reloadOnChange: options.ReloadOnChange); if (!options.EnvironmentName.IsNullOrEmpty()) { - builder = builder.AddJsonFile($"{options.FileName}.{options.EnvironmentName}.json", optional: true, reloadOnChange: true); + builder = builder.AddJsonFile($"{options.FileName}.{options.EnvironmentName}.json", optional: options.Optional, reloadOnChange: options.ReloadOnChange); } if (options.EnvironmentName == "Development") diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj index 4e79126174..e208ecf533 100644 --- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj +++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj @@ -15,10 +15,10 @@ - + - - + + diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs index 363c3b3885..3aff8a78ad 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/AbpLazyServiceProvider.cs @@ -1,19 +1,13 @@ using System; -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; namespace Volo.Abp.DependencyInjection; -public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDependency +[ExposeServices(typeof(IAbpLazyServiceProvider))] +public class AbpLazyServiceProvider : CachedServiceProviderBase, IAbpLazyServiceProvider, ITransientDependency { - protected IDictionary CachedServices { get; set; } - - protected IServiceProvider ServiceProvider { get; set; } - public AbpLazyServiceProvider(IServiceProvider serviceProvider) + : base(serviceProvider) { - ServiceProvider = serviceProvider; - CachedServices = new Dictionary(); } public virtual T LazyGetRequiredService() @@ -23,7 +17,7 @@ public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDepende public virtual object LazyGetRequiredService(Type serviceType) { - return CachedServices.GetOrAdd(serviceType, () => ServiceProvider.GetRequiredService(serviceType)); + return GetService(serviceType); } public virtual T LazyGetService() @@ -33,7 +27,7 @@ public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDepende public virtual object LazyGetService(Type serviceType) { - return CachedServices.GetOrAdd(serviceType, () => ServiceProvider.GetService(serviceType)); + return GetService(serviceType); } public virtual T LazyGetService(T defaultValue) @@ -53,6 +47,9 @@ public class AbpLazyServiceProvider : IAbpLazyServiceProvider, ITransientDepende public virtual object LazyGetService(Type serviceType, Func factory) { - return CachedServices.GetOrAdd(serviceType, () => factory(ServiceProvider)); + return CachedServices.GetOrAdd( + serviceType, + _ => new Lazy(() => factory(ServiceProvider)) + ).Value; } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs index d543493ce9..c261d3a3bb 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/CachedServiceProviderBase.cs @@ -5,21 +5,21 @@ namespace Volo.Abp.DependencyInjection; public abstract class CachedServiceProviderBase { - private readonly IServiceProvider _serviceProvider; - private readonly ConcurrentDictionary> _cachedServices; + protected IServiceProvider ServiceProvider { get; } + protected ConcurrentDictionary> CachedServices { get; } protected CachedServiceProviderBase(IServiceProvider serviceProvider) { - _serviceProvider = serviceProvider; - _cachedServices = new ConcurrentDictionary>(); - _cachedServices.TryAdd(typeof(IServiceProvider), new Lazy(() => _serviceProvider)); + ServiceProvider = serviceProvider; + CachedServices = new ConcurrentDictionary>(); + CachedServices.TryAdd(typeof(IServiceProvider), new Lazy(() => ServiceProvider)); } public virtual object GetService(Type serviceType) { - return _cachedServices.GetOrAdd( + return CachedServices.GetOrAdd( serviceType, - _ => new Lazy(() => _serviceProvider.GetService(serviceType)) + _ => new Lazy(() => ServiceProvider.GetService(serviceType)) ).Value; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/pt-BR.json b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/pt-BR.json index b1f3878b88..c0d6227e48 100644 --- a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/pt-BR.json +++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/pt-BR.json @@ -9,7 +9,7 @@ "DisplayName:Abp.Mailing.Smtp.Password": "Senha", "DisplayName:Abp.Mailing.Smtp.Domain": "Domínio", "DisplayName:Abp.Mailing.Smtp.EnableSsl": "Habilitar SSL", - "DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Use credenciais padrão", + "DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Usar credenciais padrão", "Description:Abp.Mailing.DefaultFromAddress": "O endereço de origem padrão", "Description:Abp.Mailing.DefaultFromDisplayName": "O nome de exibição padrão", "Description:Abp.Mailing.Smtp.Host": "O nome ou endereço IP do host usado para transações SMTP.", diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj b/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj index cc55a077c4..b1d60e60c7 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo.Abp.ExceptionHandling.csproj @@ -19,7 +19,7 @@ - + diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json index aa915a704f..03855ec698 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json @@ -1,10 +1,10 @@ { "culture": "pt-BR", "texts": { - "Languages": "línguas", + "Languages": "Idiomas", "AreYouSure": "Você tem certeza?", "Cancel": "Cancelar", - "Clear": "Claro", + "Clear": "Limpar", "Yes": "Sim", "No": "Não", "Ok": "OK", @@ -16,7 +16,7 @@ "SuccessfullyDeleted": "Excluído com sucesso", "Edit": "Editar", "Refresh": "Atualizar", - "Language": "Língua", + "Language": "Idioma", "LoadMore": "Carregar mais", "ProcessingWithThreeDot": "Processando...", "LoadingWithThreeDot": "Carregando...", diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/pt-BR.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/pt-BR.json index 4adbd81e80..1168a19317 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/pt-BR.json +++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/pt-BR.json @@ -24,6 +24,8 @@ "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Este campo deve ser do tipo palavra ou matriz com comprimento mínimo de '{0}'.", "ThisFieldIsNotAValidPhoneNumber.": "Número de telefone inválido.", "ThisFieldMustBeBetween{0}And{1}": "Este campo deve estar entre {0} e {1}.", + "ThisFieldMustBeGreaterThanOrEqual{0}": "Este campo deve ser maior ou igual a {0}.", + "ThisFieldMustBeLessOrEqual{0}": "Este campo deve ser menor ou igual a {0}.", "ThisFieldMustMatchTheRegularExpression{0}": "Este campo deve ser compatível com a expressão regular: '{0}'.", "ThisFieldIsRequired.": "Campo Obrigatório.", "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Campo com no máximo {0} caracteres.", diff --git a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj index adba125cd3..64425620dc 100644 --- a/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj +++ b/framework/src/Volo.Abp.VirtualFileSystem/Volo.Abp.VirtualFileSystem.csproj @@ -17,7 +17,7 @@ - + diff --git a/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj b/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj index 5aca466d38..6863fb0242 100644 --- a/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj +++ b/framework/test/SimpleConsoleDemo/SimpleConsoleDemo.csproj @@ -18,7 +18,7 @@ - + diff --git a/framework/test/Volo.Abp.BlobStoring.Aliyun.Tests/Volo.Abp.BlobStoring.Aliyun.Tests.csproj b/framework/test/Volo.Abp.BlobStoring.Aliyun.Tests/Volo.Abp.BlobStoring.Aliyun.Tests.csproj index a2c31d4791..00d58302bd 100644 --- a/framework/test/Volo.Abp.BlobStoring.Aliyun.Tests/Volo.Abp.BlobStoring.Aliyun.Tests.csproj +++ b/framework/test/Volo.Abp.BlobStoring.Aliyun.Tests/Volo.Abp.BlobStoring.Aliyun.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AbpLazyServiceProvider_Tests.cs b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AbpLazyServiceProvider_Tests.cs new file mode 100644 index 0000000000..c78dc9c989 --- /dev/null +++ b/framework/test/Volo.Abp.Core.Tests/Volo/Abp/DependencyInjection/AbpLazyServiceProvider_Tests.cs @@ -0,0 +1,50 @@ +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Modularity; +using Volo.Abp.Testing.Utils; +using Xunit; + +namespace Volo.Abp.DependencyInjection; + +public class AbpLazyServiceProvider_Tests +{ + [Fact] + public void LazyServiceProvider_Should_Cache_Services() + { + using (var application = AbpApplicationFactory.Create()) + { + application.Initialize(); + + var lazyServiceProvider = application.ServiceProvider.GetRequiredService(); + + var transientTestService1 = lazyServiceProvider.LazyGetRequiredService(); + var transientTestService2 = lazyServiceProvider.LazyGetRequiredService(); + transientTestService1.ShouldBeSameAs(transientTestService2); + + var testCounter = application.ServiceProvider.GetRequiredService(); + testCounter.GetValue(nameof(TransientTestService)).ShouldBe(1); + } + } + + [DependsOn(typeof(AbpTestBaseModule))] + private class TestModule : AbpModule + { + public TestModule() + { + SkipAutoServiceRegistration = true; + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddType(); + } + } + + private class TransientTestService : ITransientDependency + { + public TransientTestService(ITestCounter counter) + { + counter.Increment(nameof(TransientTestService)); + } + } +} diff --git a/framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj b/framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj index 68f49b10b1..f43cebafaf 100644 --- a/framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj +++ b/framework/test/Volo.Abp.Sms.Aliyun.Tests/Volo.Abp.Sms.Aliyun.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj index fc07aebd46..2d845fd6cc 100644 --- a/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj +++ b/framework/test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj @@ -16,7 +16,7 @@ - + diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.csproj b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.csproj index 4b5029d234..d6b87b957d 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.csproj +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo.Abp.Account.Application.Contracts.csproj @@ -21,7 +21,7 @@ - + diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/AbpAccountApplicationContractsModule.cs b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/AbpAccountApplicationContractsModule.cs index 4cfe025e1c..1400fd5f25 100644 --- a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/AbpAccountApplicationContractsModule.cs +++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/AbpAccountApplicationContractsModule.cs @@ -3,6 +3,9 @@ using Volo.Abp.Identity; using Volo.Abp.Localization; using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.ObjectExtending.Modularity; +using Volo.Abp.Threading; using Volo.Abp.Validation.Localization; using Volo.Abp.VirtualFileSystem; @@ -13,6 +16,8 @@ namespace Volo.Abp.Account; )] public class AbpAccountApplicationContractsModule : AbpModule { + private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner(); + public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => @@ -33,4 +38,17 @@ public class AbpAccountApplicationContractsModule : AbpModule options.MapCodeNamespace("Volo.Account", typeof(AccountResource)); }); } + + public override void PostConfigureServices(ServiceConfigurationContext context) + { + OneTimeRunner.Run(() => + { + ModuleExtensionConfigurationHelper.ApplyEntityConfigurationToApi( + IdentityModuleExtensionConsts.ModuleName, + IdentityModuleExtensionConsts.EntityNames.User, + getApiTypes: new[] { typeof(ProfileDto) }, + updateApiTypes: new[] { typeof(UpdateProfileDto) } + ); + }); + } } diff --git a/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj b/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj index 69e0f258a7..812ea46e23 100644 --- a/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj +++ b/modules/account/src/Volo.Abp.Account.Application/Volo.Abp.Account.Application.csproj @@ -25,7 +25,7 @@ - + diff --git a/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs index 8838cee634..af59d75321 100644 --- a/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs +++ b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorAutoMapperProfile.cs @@ -10,10 +10,11 @@ public class AbpAccountBlazorAutoMapperProfile : Profile public AbpAccountBlazorAutoMapperProfile() { CreateMap() + .MapExtraProperties() .Ignore(x => x.PhoneNumberConfirmed) .Ignore(x => x.EmailConfirmed); CreateMap() - .Ignore(x => x.ExtraProperties); + .MapExtraProperties(); } } diff --git a/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs index c1e52e9b5f..61b42e1807 100644 --- a/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs +++ b/modules/account/src/Volo.Abp.Account.Blazor/AbpAccountBlazorModule.cs @@ -1,8 +1,12 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Account.Blazor.Pages.Account; using Volo.Abp.AspNetCore.Components.Web.Theming; using Volo.Abp.AspNetCore.Components.Web.Theming.Routing; using Volo.Abp.AutoMapper; using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.ObjectExtending.Modularity; +using Volo.Abp.Threading; using Volo.Abp.UI.Navigation; namespace Volo.Abp.Account.Blazor; @@ -14,6 +18,8 @@ namespace Volo.Abp.Account.Blazor; )] public class AbpAccountBlazorModule : AbpModule { + private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner(); + public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAutoMapperObjectMapper(); @@ -33,4 +39,17 @@ public class AbpAccountBlazorModule : AbpModule options.AdditionalAssemblies.Add(typeof(AbpAccountBlazorModule).Assembly); }); } + + public override void PostConfigureServices(ServiceConfigurationContext context) + { + OneTimeRunner.Run(() => + { + ModuleExtensionConfigurationHelper + .ApplyEntityConfigurationToUi( + IdentityModuleExtensionConsts.ModuleName, + IdentityModuleExtensionConsts.EntityNames.User, + editFormTypes: new[] { typeof(PersonalInfoModel) } + ); + }); + } } diff --git a/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor index a3a4e76b58..2a625f3e35 100644 --- a/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor +++ b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor @@ -1,5 +1,9 @@ @page "/account/manage-profile" @using Microsoft.AspNetCore.Components.Forms +@using Volo.Abp.Account.Localization +@using Volo.Abp.AspNetCore.Components.Web +@using Volo.Abp.BlazoriseUI.Components.ObjectExtending +@inject AbpBlazorMessageLocalizerHelper LH @inherits AbpAccountComponentBase @@ -58,6 +62,7 @@ @L["DisplayName:PhoneNumber"] + diff --git a/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor.cs b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor.cs index 3a0aff243b..567363843b 100644 --- a/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor.cs +++ b/modules/account/src/Volo.Abp.Account.Blazor/Pages/Account/AccountManage.razor.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Components; using Volo.Abp.AspNetCore.Components.Messages; using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; namespace Volo.Abp.Account.Blazor.Pages.Account; @@ -58,7 +59,7 @@ public partial class AccountManage await UiMessageService.Success(L["PasswordChanged"]); } - protected async Task UpdatePersonalInfoAsync() + protected virtual async Task UpdatePersonalInfoAsync() { await ProfileAppService.UpdateAsync( ObjectMapper.Map(PersonalInfoModel) @@ -86,7 +87,7 @@ public class ChangePasswordModel } } -public class PersonalInfoModel +public class PersonalInfoModel : ExtensibleObject { public string UserName { get; set; } diff --git a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj index bd52bfd5f9..2e2b28fcc6 100644 --- a/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj +++ b/modules/account/src/Volo.Abp.Account.Web.IdentityServer/Volo.Abp.Account.Web.IdentityServer.csproj @@ -38,7 +38,7 @@ - + diff --git a/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Volo.Abp.Account.Web.OpenIddict.csproj b/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Volo.Abp.Account.Web.OpenIddict.csproj index a88df575e1..6fa9812461 100644 --- a/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Volo.Abp.Account.Web.OpenIddict.csproj +++ b/modules/account/src/Volo.Abp.Account.Web.OpenIddict/Volo.Abp.Account.Web.OpenIddict.csproj @@ -28,7 +28,7 @@ - + diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs index 329f8f7ac1..cdc92e8b19 100644 --- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs +++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebAutomapperProfile.cs @@ -9,6 +9,7 @@ public class AbpAccountWebAutoMapperProfile : Profile { public AbpAccountWebAutoMapperProfile() { - CreateMap(); + CreateMap() + .MapExtraProperties(); } } diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs index 0dc4f2fc48..9f670ffc82 100644 --- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs +++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountWebModule.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Account.Localization; using Volo.Abp.Account.Web.Pages.Account; +using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo; using Volo.Abp.Account.Web.ProfileManagement; using Volo.Abp.AspNetCore.Mvc.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bundling; @@ -12,6 +13,9 @@ using Volo.Abp.ExceptionHandling; using Volo.Abp.Http.ProxyScripting.Generators.JQuery; using Volo.Abp.Identity.AspNetCore; using Volo.Abp.Modularity; +using Volo.Abp.ObjectExtending; +using Volo.Abp.ObjectExtending.Modularity; +using Volo.Abp.Threading; using Volo.Abp.UI.Navigation; using Volo.Abp.VirtualFileSystem; @@ -26,6 +30,8 @@ namespace Volo.Abp.Account.Web; )] public class AbpAccountWebModule : AbpModule { + private readonly static OneTimeRunner OneTimeRunner = new OneTimeRunner(); + public override void PreConfigureServices(ServiceConfigurationContext context) { context.Services.PreConfigure(options => @@ -95,4 +101,17 @@ public class AbpAccountWebModule : AbpModule }); } + + public override void PostConfigureServices(ServiceConfigurationContext context) + { + OneTimeRunner.Run(() => + { + ModuleExtensionConfigurationHelper + .ApplyEntityConfigurationToUi( + IdentityModuleExtensionConsts.ModuleName, + IdentityModuleExtensionConsts.EntityNames.User, + editFormTypes: new[] { typeof(AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel) } + ); + }); + } } diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/AccountProfilePersonalInfoManagementGroupViewComponent.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/AccountProfilePersonalInfoManagementGroupViewComponent.cs index 45705eb7f5..0dea3bc6eb 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/AccountProfilePersonalInfoManagementGroupViewComponent.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/AccountProfilePersonalInfoManagementGroupViewComponent.cs @@ -5,6 +5,7 @@ using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc.UI.Widgets; using Volo.Abp.Domain.Entities; using Volo.Abp.Identity; +using Volo.Abp.ObjectExtending; using Volo.Abp.Validation; namespace Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo; @@ -30,7 +31,7 @@ public class AccountProfilePersonalInfoManagementGroupViewComponent : AbpViewCom return View("~/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml", model); } - public class PersonalInfoModel : IHasConcurrencyStamp + public class PersonalInfoModel : ExtensibleObject, IHasConcurrencyStamp { [Required] [DynamicStringLength(typeof(IdentityUserConsts), nameof(IdentityUserConsts.MaxUserNameLength))] @@ -54,7 +55,6 @@ public class AccountProfilePersonalInfoManagementGroupViewComponent : AbpViewCom [Display(Name = "DisplayName:PhoneNumber")] public string PhoneNumber { get; set; } - [HiddenInput] - public string ConcurrencyStamp { get; set; } + [HiddenInput] public string ConcurrencyStamp { get; set; } } -} +} \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml index ba695a8557..b9b0783ab9 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.cshtml @@ -1,13 +1,24 @@ @using Volo.Abp.Account.Localization @using Volo.Abp.Users @using Microsoft.AspNetCore.Mvc.Localization +@using Microsoft.AspNetCore.Mvc.TagHelpers +@using Microsoft.Extensions.Localization +@using Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Alert +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid @using Volo.Abp.AspNetCore.Mvc.UI.Theming +@using Volo.Abp.Data @using Volo.Abp.Identity.Settings +@using Volo.Abp.Localization +@using Volo.Abp.ObjectExtending @using Volo.Abp.Settings @inject IHtmlLocalizer L @inject ICurrentUser CurrentUser @inject ISettingProvider SettingManager @inject IThemeManager ThemeManager +@inject IStringLocalizerFactory StringLocalizerFactory @model Volo.Abp.Account.Web.Pages.Account.Components.ProfileManagementGroup.PersonalInfo.AccountProfilePersonalInfoManagementGroupViewComponent.PersonalInfoModel @{ var isUserNameUpdateEnabled = string.Equals(await SettingManager.GetOrNullAsync(IdentitySettingNames.User.IsUserNameUpdateEnabled), "true", @@ -19,8 +30,8 @@

@L["PersonalSettings"]


- - + + @@ -37,5 +48,39 @@ + @foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties()) + { + if (!propertyInfo.Name.EndsWith("_Text")) + { + if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty()) + { + if (propertyInfo.Type.IsEnum) + { + Model.ExtraProperties.ToEnum(propertyInfo.Name, propertyInfo.Type); + } + + + } + else + { + + } + } + } + - + \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js index 55a88e52e3..c8ff17ec67 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Components/ProfileManagementGroup/PersonalInfo/Default.js @@ -9,7 +9,7 @@ return false; } - var input = $('#PersonalSettingsForm').serializeFormToObject(); + var input = $('#PersonalSettingsForm').serializeFormToObject(false); volo.abp.account.profile.update(input).then(function (result) { abp.notify.success(l('PersonalSettingsSaved')); diff --git a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj index b9e85e2c7f..0a19b8e1a0 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj +++ b/modules/account/src/Volo.Abp.Account.Web/Volo.Abp.Account.Web.csproj @@ -44,7 +44,7 @@ - + diff --git a/modules/blogging/src/Volo.Blogging.Admin.Web/Volo.Blogging.Admin.Web.csproj b/modules/blogging/src/Volo.Blogging.Admin.Web/Volo.Blogging.Admin.Web.csproj index a6754b1dfe..6afb71c7e9 100644 --- a/modules/blogging/src/Volo.Blogging.Admin.Web/Volo.Blogging.Admin.Web.csproj +++ b/modules/blogging/src/Volo.Blogging.Admin.Web/Volo.Blogging.Admin.Web.csproj @@ -24,7 +24,7 @@ - + diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj index 96c14f8da0..c56b888d38 100644 --- a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo.Blogging.Domain.Shared.csproj @@ -21,7 +21,7 @@ - + diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/pt-BR.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/pt-BR.json index f26b339d71..bb19760972 100644 --- a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/pt-BR.json +++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/pt-BR.json @@ -37,7 +37,7 @@ "Edit": "Editar", "BLOG": "BLOG", "CommentDeletionWarningMessage": "O comentário será excluído.", - "PostDeletionWarningMessage": "O post será excluído.", + "PostDeletionWarningMessage": "A postagem será excluída.", "BlogDeletionWarningMessage": "O Blog será excluído.", "AreYouSure": "Você tem certeza?", "CommentWithCount": "{0} comentários", @@ -54,8 +54,10 @@ "Blogs": "Blogs", "Tags": "Etiquetas", "ShareOn": "Compartilhar no", - "TitleLengthWarning": "Mantenha o tamanho do título abaixo de 60 caracteres para ser SEO amigável!", + "TitleLengthWarning": "Mantenha o tamanho do título abaixo de 60 caracteres para ser amigável ao SEO!", "ClearCache": "Limpar cache", - "ClearCacheConfirmationMessage": "Tem certeza de que deseja limpar o cache?" + "ClearCacheConfirmationMessage": "Tem certeza de que deseja limpar o cache?", + "MarkdownSupported": "Markdown é suportado", + "FileUploadInfo": "Arrastar, soltar, ou colar uma imagem copiada." } } \ No newline at end of file diff --git a/modules/blogging/src/Volo.Blogging.Web/Volo.Blogging.Web.csproj b/modules/blogging/src/Volo.Blogging.Web/Volo.Blogging.Web.csproj index 4077e7cad8..0ba240d8c2 100644 --- a/modules/blogging/src/Volo.Blogging.Web/Volo.Blogging.Web.csproj +++ b/modules/blogging/src/Volo.Blogging.Web/Volo.Blogging.Web.csproj @@ -24,7 +24,7 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagSetDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagSetDto.cs index 245526cfc2..11466463f8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagSetDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Tags/EntityTagSetDto.cs @@ -1,15 +1,40 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using Volo.Abp.Validation.Localization; +using Volo.CmsKit.Localization; +using Volo.CmsKit.Tags; namespace Volo.CmsKit.Admin.Tags; [Serializable] -public class EntityTagSetDto +public class EntityTagSetDto : IValidatableObject { public string EntityId { get; set; } + public string EntityType { get; set; } + + [Required] public List Tags { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + var l = validationContext.GetRequiredService>(); + + foreach (var tag in Tags) + { + if (tag.Length > TagConsts.MaxNameLength) + { + yield return new ValidationResult( + l[ + "ThisFieldMustBeAStringWithAMaximumLengthOf{0}", + TagConsts.MaxNameLength + ], + new[] { nameof(Tags) } + ); + } + } + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs index 7cd17b7696..5736048076 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogAdminAppService.cs @@ -1,16 +1,19 @@ -using Microsoft.AspNetCore.Authorization; -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Blogs; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] [Authorize(CmsKitAdminPermissions.Blogs.Default)] public class BlogAdminAppService : CmsKitAdminAppServiceBase, IBlogAdminAppService diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminAppService.cs index 823f569bed..774f28634d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminAppService.cs @@ -1,15 +1,18 @@ -using Microsoft.AspNetCore.Authorization; -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Blogs; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] [Authorize(CmsKitAdminPermissions.Blogs.Features)] public class BlogFeatureAdminAppService : CmsKitAdminAppServiceBase, IBlogFeatureAdminAppService diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs index 9d8fcfd917..297e70344f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Blogs/BlogPostAdminAppService.cs @@ -1,19 +1,22 @@ -using Microsoft.AspNetCore.Authorization; -using System; +using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.Abp.Users; using Volo.CmsKit.Admin.MediaDescriptors; using Volo.CmsKit.Blogs; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; using Volo.CmsKit.Users; namespace Volo.CmsKit.Admin.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] [Authorize(CmsKitAdminPermissions.BlogPosts.Default)] public class BlogPostAdminAppService : CmsKitAppServiceBase, IBlogPostAdminAppService @@ -66,18 +69,18 @@ public class BlogPostAdminAppService : CmsKitAppServiceBase, IBlogPostAdminAppSe public virtual async Task UpdateAsync(Guid id, UpdateBlogPostDto input) { var blogPost = await BlogPostRepository.GetAsync(id); - + blogPost.SetTitle(input.Title); blogPost.SetShortDescription(input.ShortDescription); blogPost.SetContent(input.Content); blogPost.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); - + if (blogPost.CoverImageMediaId != null && input.CoverImageMediaId == null) { await MediaDescriptorAdminAppService.DeleteAsync(blogPost.CoverImageMediaId.Value); } blogPost.CoverImageMediaId = input.CoverImageMediaId; - + if (blogPost.Slug != input.Slug) { await BlogPostManager.SetSlugUrlAsync(blogPost, input.Slug); @@ -146,12 +149,12 @@ public class BlogPostAdminAppService : CmsKitAppServiceBase, IBlogPostAdminAppSe { var blogPost = await CreateAsync(input); await CurrentUnitOfWork.SaveChangesAsync(); - + await PublishAsync(blogPost.Id); blogPost.Status = BlogPostStatus.Published; return blogPost; } - + [Authorize(CmsKitAdminPermissions.BlogPosts.Create)] public virtual async Task SendToReviewAsync(Guid id) { @@ -159,13 +162,13 @@ public class BlogPostAdminAppService : CmsKitAppServiceBase, IBlogPostAdminAppSe blogPost.SetWaitingForReview(); await BlogPostRepository.UpdateAsync(blogPost); } - + [Authorize(CmsKitAdminPermissions.BlogPosts.Create)] public virtual async Task CreateAndSendToReviewAsync(CreateBlogPostDto input) { var blogPost = await CreateAsync(input); await CurrentUnitOfWork.SaveChangesAsync(); - + await SendToReviewAsync(blogPost.Id); blogPost.Status = BlogPostStatus.WaitingForReview; return blogPost; diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs index 5295557860..973a74b58e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Comments/CommentAdminAppService.cs @@ -3,14 +3,17 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Comments; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; using Volo.CmsKit.Users; namespace Volo.CmsKit.Admin.Comments; +[RequiresFeature(CmsKitFeatures.CommentEnable)] [RequiresGlobalFeature(typeof(CommentsFeature))] [Authorize(CmsKitAdminPermissions.Comments.Default)] public class CommentAdminAppService : CmsKitAdminAppServiceBase, ICommentAdminAppService diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminAppService.cs index a78a21de41..c5b63db6c3 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminAppService.cs @@ -1,13 +1,16 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Services; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.GlobalResources; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.GlobalResources; +[RequiresFeature(CmsKitFeatures.GlobalResourceEnable)] [RequiresGlobalFeature(typeof(GlobalResourcesFeature))] [Authorize(CmsKitAdminPermissions.GlobalResources.Default)] public class GlobalResourceAdminAppService : ApplicationService, IGlobalResourceAdminAppService @@ -18,10 +21,11 @@ public class GlobalResourceAdminAppService : ApplicationService, IGlobalResource { GlobalResourceManager = globalResourceManager; } - + public async Task GetAsync() { - return new GlobalResourcesDto { + return new GlobalResourcesDto + { StyleContent = (await GlobalResourceManager.GetGlobalStyleAsync()).Value, ScriptContent = (await GlobalResourceManager.GetGlobalScriptAsync()).Value }; diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs index cc785adac0..af347bcc55 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs @@ -1,12 +1,15 @@ using System; using System.Threading.Tasks; using Volo.Abp.BlobStoring; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.MediaDescriptors; namespace Volo.CmsKit.Admin.MediaDescriptors; +[RequiresFeature(CmsKitFeatures.MediaEnable)] [RequiresGlobalFeature(typeof(MediaFeature))] public class MediaDescriptorAdminAppService : CmsKitAdminAppServiceBase, IMediaDescriptorAdminAppService { diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs index 8ef6ce0346..3ba2a4b5b9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Menus/MenuItemAdminAppService.cs @@ -1,12 +1,12 @@ -using Microsoft.AspNetCore.Authorization; -using System; +using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Menus; using Volo.CmsKit.Pages; @@ -14,6 +14,7 @@ using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Menus; +[RequiresFeature(CmsKitFeatures.MenuEnable)] [RequiresGlobalFeature(typeof(MenuFeature))] [Authorize(CmsKitAdminPermissions.Menus.Default)] public class MenuItemAdminAppService : CmsKitAdminAppServiceBase, IMenuItemAdminAppService diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs index 68f0690555..647568e561 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Pages/PageAdminAppService.cs @@ -1,18 +1,19 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using AutoMapper; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; -using Volo.CmsKit.Admin.Menus; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Pages; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Pages; +[RequiresFeature(CmsKitFeatures.PageEnable)] [RequiresGlobalFeature(typeof(PagesFeature))] [Authorize(CmsKitAdminPermissions.Pages.Default)] public class PageAdminAppService : CmsKitAdminAppServiceBase, IPageAdminAppService diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs index 8d106b70e0..3cdc4dc093 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/EntityTagAdminAppService.cs @@ -1,10 +1,13 @@ using System.Threading.Tasks; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Tags; namespace Volo.CmsKit.Admin.Tags; +[RequiresFeature(CmsKitFeatures.TagEnable)] [RequiresGlobalFeature(typeof(TagsFeature))] public class EntityTagAdminAppService : CmsKitAdminAppServiceBase, IEntityTagAdminAppService { diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs index f6de1ac5b9..46324937cc 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/Tags/TagAdminAppService.cs @@ -1,18 +1,21 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.Extensions.Localization; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Localization; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; using Volo.CmsKit.Tags; namespace Volo.CmsKit.Admin.Tags; +[RequiresFeature(CmsKitFeatures.TagEnable)] [Authorize(CmsKitAdminPermissions.Tags.Default)] [RequiresGlobalFeature(typeof(TagsFeature))] public class TagAdminAppService : CmsKitAppServiceBase, ITagAdminAppService diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs index 094c1b1b5a..e7d59ddbcd 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogAdminController.cs @@ -1,15 +1,18 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System; +using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminController.cs index e3cc3c5e73..93bdced888 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogFeatureAdminController.cs @@ -1,16 +1,19 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Blogs; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs index 563d90c254..923f9a4036 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Blogs/BlogPostAdminController.cs @@ -1,15 +1,18 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System; +using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] @@ -61,7 +64,7 @@ public class BlogPostAdminController : CmsKitAdminController, IBlogPostAdminAppS { return BlogPostAdminAppService.UpdateAsync(id, input); } - + [HttpPost] [Route("{id}/publish")] [Authorize(CmsKitAdminPermissions.BlogPosts.Publish)] @@ -69,7 +72,7 @@ public class BlogPostAdminController : CmsKitAdminController, IBlogPostAdminAppS { return BlogPostAdminAppService.PublishAsync(id); } - + [HttpPost] [Route("{id}/draft")] [Authorize(CmsKitAdminPermissions.BlogPosts.Update)] @@ -86,7 +89,7 @@ public class BlogPostAdminController : CmsKitAdminController, IBlogPostAdminAppS { return BlogPostAdminAppService.CreateAndPublishAsync(input); } - + [HttpPost] [Route("{id}/send-to-review")] [Authorize(CmsKitAdminPermissions.BlogPosts.Create)] @@ -94,7 +97,7 @@ public class BlogPostAdminController : CmsKitAdminController, IBlogPostAdminAppS { return BlogPostAdminAppService.SendToReviewAsync(id); } - + [HttpPost] [Route("create-and-send-to-review")] [Authorize(CmsKitAdminPermissions.BlogPosts.Create)] @@ -102,7 +105,7 @@ public class BlogPostAdminController : CmsKitAdminController, IBlogPostAdminAppS { return BlogPostAdminAppService.CreateAndSendToReviewAsync(input); } - + [HttpGet] [Route("has-blogpost-waiting-for-review")] [Authorize(CmsKitAdminPermissions.BlogPosts.Publish)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Comments/CommentAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Comments/CommentAdminController.cs index 6082ad3794..f4813f61ad 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Comments/CommentAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Comments/CommentAdminController.cs @@ -4,12 +4,15 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Comments; +[RequiresFeature(CmsKitFeatures.CommentEnable)] [Authorize(CmsKitAdminPermissions.Comments.Default)] [RequiresGlobalFeature(typeof(CommentsFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminController.cs index 3bfe51a600..b1ae9b3f2e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/GlobalResources/GlobalResourceAdminController.cs @@ -2,18 +2,21 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.GlobalResources; +[RequiresFeature(CmsKitFeatures.GlobalResourceEnable)] [RequiresGlobalFeature(typeof(GlobalResourcesFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] [Authorize(CmsKitAdminPermissions.Menus.Default)] [Route("api/cms-kit-admin/global-resources")] -public class GlobalResourceAdminController: CmsKitAdminController, IGlobalResourceAdminAppService +public class GlobalResourceAdminController : CmsKitAdminController, IGlobalResourceAdminAppService { private readonly IGlobalResourceAdminAppService _globalResourceAdminAppService; @@ -21,7 +24,7 @@ public class GlobalResourceAdminController: CmsKitAdminController, IGlobalResour { _globalResourceAdminAppService = globalResourceAdminAppService; } - + [HttpGet] public Task GetAsync() { diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs index f95d2a86b2..c304c5c684 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs @@ -1,16 +1,15 @@ using System; -using System.Net; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; -using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.MediaDescriptors; +[RequiresFeature(CmsKitFeatures.MediaEnable)] [RequiresGlobalFeature(typeof(MediaFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs index de36883ff7..a0325f4f27 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Menus/MenuItemAdminController.cs @@ -1,16 +1,19 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System; +using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Menus; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Menus; +[RequiresFeature(CmsKitFeatures.MenuEnable)] [RequiresGlobalFeature(typeof(MenuFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Pages/PageAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Pages/PageAdminController.cs index 7936b206e6..5acccb07aa 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Pages/PageAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Pages/PageAdminController.cs @@ -4,13 +4,15 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; -using Volo.CmsKit.Admin.Menus; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Pages; +[RequiresFeature(CmsKitFeatures.PageEnable)] [RequiresGlobalFeature(typeof(PagesFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/EntityTagAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/EntityTagAdminController.cs index 9df9394fdd..c57e7bb0a7 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/EntityTagAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/EntityTagAdminController.cs @@ -1,13 +1,14 @@ -using Microsoft.AspNetCore.Authorization; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using System.Threading.Tasks; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; -using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.Tags; +[RequiresFeature(CmsKitFeatures.TagEnable)] [RequiresGlobalFeature(typeof(TagsFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs index c34107b742..db0131ba2f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/Tags/TagAdminController.cs @@ -1,18 +1,20 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; -using Volo.CmsKit.Admin.Tags; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Permissions; using Volo.CmsKit.Tags; namespace Volo.CmsKit.Admin.Tags; +[RequiresFeature(CmsKitFeatures.TagEnable)] [RequiresGlobalFeature(typeof(TagsFeature))] [RemoteService(Name = CmsKitAdminRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitAdminRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenuContributor.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenuContributor.cs index bc9bbfb310..9cc76c080c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenuContributor.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Menus/CmsKitAdminMenuContributor.cs @@ -2,8 +2,10 @@ using System.Linq; using System.Threading.Tasks; using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.Abp.UI.Navigation; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Localization; using Volo.CmsKit.Permissions; @@ -36,6 +38,7 @@ public class CmsKitAdminMenuContributor : IMenuContributor l["Pages"].Value, "/Cms/Pages", "fa fa-file-alt") + .RequireFeatures(CmsKitFeatures.PageEnable) .RequireGlobalFeatures(typeof(PagesFeature)) .RequirePermissions(CmsKitAdminPermissions.Pages.Default)); @@ -44,6 +47,7 @@ public class CmsKitAdminMenuContributor : IMenuContributor l["Blogs"], "/Cms/Blogs", "fa fa-blog") + .RequireFeatures(CmsKitFeatures.BlogEnable) .RequireGlobalFeatures(typeof(BlogsFeature)) .RequirePermissions(CmsKitAdminPermissions.Blogs.Default)); @@ -52,6 +56,7 @@ public class CmsKitAdminMenuContributor : IMenuContributor l["BlogPosts"], "/Cms/BlogPosts", "fa fa-file-signature") + .RequireFeatures(CmsKitFeatures.BlogEnable) .RequireGlobalFeatures(typeof(BlogsFeature)) .RequirePermissions(CmsKitAdminPermissions.BlogPosts.Default)); @@ -60,6 +65,7 @@ public class CmsKitAdminMenuContributor : IMenuContributor l["Tags"].Value, "/Cms/Tags", "fa fa-tags") + .RequireFeatures(CmsKitFeatures.TagEnable) .RequireGlobalFeatures(typeof(TagsFeature)) .RequirePermissions(CmsKitAdminPermissions.Tags.Default)); @@ -68,6 +74,7 @@ public class CmsKitAdminMenuContributor : IMenuContributor l["Comments"].Value, "/Cms/Comments", "fa fa-comments") + .RequireFeatures(CmsKitFeatures.CommentEnable) .RequireGlobalFeatures(typeof(CommentsFeature)) .RequirePermissions(CmsKitAdminPermissions.Comments.Default)); @@ -76,6 +83,7 @@ public class CmsKitAdminMenuContributor : IMenuContributor l["Menus"], "/Cms/Menus/Items", "fa fa-stream") + .RequireFeatures(CmsKitFeatures.MenuEnable) .RequireGlobalFeatures(typeof(MenuFeature)) .RequirePermissions(CmsKitAdminPermissions.Menus.Default)); @@ -84,6 +92,7 @@ public class CmsKitAdminMenuContributor : IMenuContributor l["GlobalResources"], "/Cms/GlobalResources", "fa fa-newspaper") + .RequireFeatures(CmsKitFeatures.GlobalResourceEnable) .RequireGlobalFeatures(typeof(GlobalResourcesFeature)) .RequirePermissions(CmsKitAdminPermissions.GlobalResources.Default)); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Volo.CmsKit.Admin.Web.csproj b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Volo.CmsKit.Admin.Web.csproj index 58aa5ac95d..03a1542d46 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Volo.CmsKit.Admin.Web.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Volo.CmsKit.Admin.Web.csproj @@ -18,7 +18,7 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentParser.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentParser.cs index 9c6aafc0d0..aea5cc2a82 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentParser.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Application/Volo/CmsKit/Contents/ContentParser.cs @@ -20,11 +20,11 @@ public class ContentParser : ITransientDependency public Task> ParseAsync(string content) { - if (!_options.WidgetConfigs.Any()) + if (!_options.WidgetConfigs.Any() || content is null) { return Task.FromResult(new List { - new ContentFragment { Type = Markdown }.SetProperty(Content, content), + new ContentFragment { Type = Markdown }.SetProperty(Content, content ?? string.Empty), }); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Renderers/MarkdownToHtmlRenderer.cs b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Renderers/MarkdownToHtmlRenderer.cs index 5e0a2e89f5..83317c2111 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Renderers/MarkdownToHtmlRenderer.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Renderers/MarkdownToHtmlRenderer.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -using Markdig; using System.Threading.Tasks; using System.Web; -using Volo.Abp.DependencyInjection; using Ganss.XSS; +using Markdig; +using Volo.Abp.DependencyInjection; namespace Volo.CmsKit.Web.Renderers; @@ -20,7 +20,7 @@ public class MarkdownToHtmlRenderer : IMarkdownToHtmlRenderer, ITransientDepende _htmlSanitizer = new HtmlSanitizer(); } - public async Task RenderAsync(string rawMarkdown, bool allowHtmlTags = true, bool preventXSS = true) + public Task RenderAsync(string rawMarkdown, bool allowHtmlTags = true, bool preventXSS = true) { if (!allowHtmlTags) { @@ -34,7 +34,7 @@ public class MarkdownToHtmlRenderer : IMarkdownToHtmlRenderer, ITransientDepende html = _htmlSanitizer.Sanitize(html); } - return html; + return Task.FromResult(html); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Volo.CmsKit.Common.Web.csproj b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Volo.CmsKit.Common.Web.csproj index b47c66f5c7..8e86d9eee4 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Common.Web/Volo.CmsKit.Common.Web.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Common.Web/Volo.CmsKit.Common.Web.csproj @@ -19,7 +19,7 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.csproj b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.csproj index 22160272fd..d117a4e080 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo.CmsKit.Domain.Shared.csproj @@ -12,7 +12,8 @@ - + + diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatureDefinitionProvider.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatureDefinitionProvider.cs new file mode 100644 index 0000000000..597e5240e8 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatureDefinitionProvider.cs @@ -0,0 +1,73 @@ +using Volo.Abp.Features; +using Volo.Abp.Localization; +using Volo.Abp.Validation.StringValues; +using Volo.CmsKit.Localization; + +namespace Volo.CmsKit.Features; +public class CmsKitFeatureDefinitionProvider : FeatureDefinitionProvider +{ + public override void Define(IFeatureDefinitionContext context) + { + var group = context.AddGroup(CmsKitFeatures.GroupName, + L("Feature:CmsKitGroup")); + + group.AddFeature(CmsKitFeatures.BlogEnable, + "true", + L("Feature:BlogEnable"), + L("Feature:BlogEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.CommentEnable, + "true", + L("Feature:CommentEnable"), + L("Feature:CommentEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.GlobalResourceEnable, + "true", + L("Feature:GlobalResourceEnable"), + L("Feature:GlobalResourceEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.MediaEnable, + "true", + L("Feature:MediaEnable"), + L("Feature:MediaEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.MenuEnable, + "true", + L("Feature:MenuEnable"), + L("Feature:MenuEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.PageEnable, + "true", + L("Feature:PageEnable"), + L("Feature:PageEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.RatingEnable, + "true", + L("Feature:RatingEnable"), + L("Feature:RatingEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.ReactionEnable, + "true", + L("Feature:ReactionEnable"), + L("Feature:ReactionEnableDescription"), + new ToggleStringValueType()); + + group.AddFeature(CmsKitFeatures.TagEnable, + "true", + L("Feature:TagEnable"), + L("Feature:TagEnableDescription"), + new ToggleStringValueType()); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatures.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatures.cs new file mode 100644 index 0000000000..1dbf642755 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Features/CmsKitFeatures.cs @@ -0,0 +1,15 @@ +namespace Volo.CmsKit.Features; +public static class CmsKitFeatures +{ + public const string GroupName = "CmsKit"; + + public const string BlogEnable = GroupName + ".BlogEnable"; + public const string CommentEnable = GroupName + ".CommentEnable"; + public const string GlobalResourceEnable = GroupName + ".GlobalResourceEnable"; + public const string MediaEnable = GroupName + ".MediaEnable"; + public const string MenuEnable = GroupName + ".MenuEnable"; + public const string PageEnable = GroupName + ".PageEnable"; + public const string RatingEnable = GroupName + ".RatingEnable"; + public const string ReactionEnable = GroupName + ".ReactionEnable"; + public const string TagEnable = GroupName + ".TagEnable"; +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalResources/GlobalResourceConsts.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalResources/GlobalResourceConsts.cs index 47f20e1d72..7787d0c69d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalResources/GlobalResourceConsts.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/GlobalResources/GlobalResourceConsts.cs @@ -1,6 +1,6 @@ namespace Volo.CmsKit.GlobalResources; -public class GlobalResourceConsts +public static class GlobalResourceConsts { public const string GlobalStyleName = "GlobalStyle"; diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json index 922059463f..3119bf618c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ar.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "هل أنت متأكد من حذف هذه الصفحة؟", "PageId": "صفحة", "Pages": "الصفحات", - "PageSlugInformation": "سبيكة تستخدم على url. سيكون عنوان url الخاص بك هو \"/pages/{{slug}}\".", + "PageSlugInformation": "سبيكة تستخدم على url. سيكون عنوان url الخاص بك هو \"/{slug}}\".", "Permission:BlogManagement": "إدارة المدونة", "Permission:BlogManagement.Create": "إنشاء", "Permission:BlogManagement.Delete": "حذف", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json index 9192b48abe..8ae9479b06 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/cs.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Opravdu chcete smazat tuto stránku?", "PageId": "Strana", "Pages": "stránky", - "PageSlugInformation": "Na adrese URL je použit Slug. Vaše adresa URL bude '/pages/{{slug}}'.", + "PageSlugInformation": "Na adrese URL je použit Slug. Vaše adresa URL bude '/{{slug}}'.", "Permission:BlogManagement": "Správa blogu", "Permission:BlogManagement.Create": "Vytvořit", "Permission:BlogManagement.Delete": "Vymazat", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json index 903a7e3d0a..857f7f1e1a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de-DE.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Möchten Sie diese Seite wirklich löschen?", "PageId": "Buchseite", "Pages": "Seiten", - "PageSlugInformation": "Slug wird auf URL verwendet. Ihre URL lautet '/pages/{{slug}}'.", + "PageSlugInformation": "Slug wird auf URL verwendet. Ihre URL lautet '/{{slug}}'.", "Permission:BlogManagement": "Blog-Verwaltung", "Permission:BlogManagement.Create": "Schaffen", "Permission:BlogManagement.Delete": "Löschen", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json index 222cbe0fbd..7a838b120a 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/el.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Είστε βέβαιοι ότι θα διαγράψετε αυτήν τη σελίδα;", "PageId": "Σελίδα", "Pages": "Σελίδες", - "PageSlugInformation": "Το Slug χρησιμοποιείται στο url. Το url σας θα είναι '/pages/{{slug}}'.", + "PageSlugInformation": "Το Slug χρησιμοποιείται στο url. Το url σας θα είναι '/{{slug}}'.", "Permission:BlogManagement": "Διαχείριση ιστολογίου", "Permission:BlogManagement.Create": "Δημιουργώ", "Permission:BlogManagement.Delete": "Διαγράφω", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json index 8da6be8bd5..0faaf04e81 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Are you sure to delete this page?", "PageId": "Page", "Pages": "Pages", - "PageSlugInformation": "Slug is used on url. Your url will be '/pages/{{slug}}'.", + "PageSlugInformation": "Slug is used on url. Your url will be '/{{slug}}'.", "Permission:BlogManagement": "Blog Management", "Permission:BlogManagement.Create": "Create", "Permission:BlogManagement.Delete": "Delete", @@ -185,8 +185,27 @@ "Add": "Add", "AddWidget": "Add Widget", "PleaseConfigureWidgets": "Please configure widgets", - "SelectAnAuthor":"Select an Author", - "InThisDocument":"In This Document", - "GoToTop":"Go To Top" + "SelectAnAuthor": "Select an Author", + "InThisDocument": "In This Document", + "GoToTop": "Go To Top", + "Feature:CmsKitGroup": "Cms Kit", + "Feature:BlogEnable": "Enabled blog page", + "Feature:BlogEnableDescription": "Enable blog page in the application.", + "Feature:CommentEnable": "Enabled commenting", + "Feature:CommentEnableDescription": "Enable comment in the application.", + "Feature:GlobalResourceEnable": "Enabled global resourcing", + "Feature:GlobalResourceEnableDescription": "Enable global resource in the application.", + "Feature:MediaEnable": "Enabled media", + "Feature:MediaEnableDescription": "Enable media in the application.", + "Feature:MenuEnable": "Enabled menu", + "Feature:MenuEnableDescription": "Enable menu in the application.", + "Feature:PageEnable": "Enabled paging page", + "Feature:PageEnableDescription": "Enable paging page in the application.", + "Feature:RatingEnable": "Enabled rating", + "Feature:RatingEnableDescription": "Enable rating in the application.", + "Feature:ReactionEnable": "Enabled reaction", + "Feature:ReactionEnableDescription": "Enable reaction in the application.", + "Feature:TagEnable": "Enabled taging", + "Feature:TagEnableDescription": "Enable taging in the application." } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json index 19df2c45a2..8e8750e530 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "¿Está seguro de eliminar esta página?", "PageId": "Página", "Pages": "Paginas", - "PageSlugInformation": "Slug se usa en la URL. Su URL será '/pages/{{slug}}'.", + "PageSlugInformation": "Slug se usa en la URL. Su URL será '/{{slug}}'.", "Permission:BlogManagement": "Gestión de blogs", "Permission:BlogManagement.Create": "Crear", "Permission:BlogManagement.Delete": "Borrar", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json index 3ac961feef..855b6d091d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fa.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "آیا مطمئن هستید که این صفحه را حذف می کنید؟", "PageId": "صفحه", "Pages": "صفحات", - "PageSlugInformation": "Slug در url استفاده می شود. آدرس اینترنتی شما '/pages/{{slug}}' خواهد بود.", + "PageSlugInformation": "Slug در url استفاده می شود. آدرس اینترنتی شما '/{{slug}}' خواهد بود.", "Permission:BlogManagement": "مدیریت وبلاگ", "Permission:BlogManagement.Create": "ایجاد", "Permission:BlogManagement.Delete": "حذف", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json index 30a56fa9c0..438818cdfb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Haluatko varmasti poistaa tämän sivun?", "PageId": "Sivu", "Pages": "Sivut", - "PageSlugInformation": "Etanaa käytetään URL-osoitteessa. URL-osoitteesi on '/pages/{{slug}}'.", + "PageSlugInformation": "Etanaa käytetään URL-osoitteessa. URL-osoitteesi on '/{{slug}}'.", "Permission:BlogManagement": "Blogin hallinta", "Permission:BlogManagement.Create": "Luoda", "Permission:BlogManagement.Delete": "Poistaa", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json index 6d4e8f4cf5..5c789e996e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fr.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Êtes-vous sûr de vouloir supprimer cette page?", "PageId": "Page", "Pages": "Pages", - "PageSlugInformation": "Slug est utilisé sur l'url. Votre URL sera '/pages/{{slug}}'.", + "PageSlugInformation": "Slug est utilisé sur l'url. Votre URL sera '/{{slug}}'.", "Permission:BlogManagement": "Gestion de blog", "Permission:BlogManagement.Create": "Créer", "Permission:BlogManagement.Delete": "Effacer", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json index 732ca3d2de..8f69f2e25f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hi.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "क्या आप इस पृष्ठ को हटाना सुनिश्चित कर रहे हैं?", "PageId": "पृष्ठ", "Pages": "पृष्ठों", - "PageSlugInformation": "स्लग का उपयोग url पर किया जाता है। आपका url '/pages/{{slug}}' होगा।", + "PageSlugInformation": "स्लग का उपयोग url पर किया जाता है। आपका url '/{{slug}}' होगा।", "Permission:BlogManagement": "ब्लॉग प्रबंधन", "Permission:BlogManagement.Create": "सृजन करना", "Permission:BlogManagement.Delete": "हटाएं", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json index 49b7d5f828..ebeb5dad25 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hu.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Biztosan törlöd ezt az oldalt?", "PageId": "oldal", "Pages": "Oldalak", - "PageSlugInformation": "A Slug az url-en használatos. Az Ön URL-je a következő lesz: „/pages/{{slug}}”.", + "PageSlugInformation": "A Slug az url-en használatos. Az Ön URL-je a következő lesz: „/{{slug}}”.", "Permission:BlogManagement": "Blogkezelés", "Permission:BlogManagement.Create": "Teremt", "Permission:BlogManagement.Delete": "Töröl", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json index f5bb342dc6..60c8d13744 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/it.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Sei sicuro di cancellare questa pagina?", "PageId": "Pagina", "Pages": "Pagine", - "PageSlugInformation": "Lo slug viene utilizzato sull'URL. Il tuo URL sarà '/pages/{{slug}}'.", + "PageSlugInformation": "Lo slug viene utilizzato sull'URL. Il tuo URL sarà '/{{slug}}'.", "Permission:BlogManagement": "Gestione del blog", "Permission:BlogManagement.Create": "Crea", "Permission:BlogManagement.Delete": "Elimina", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json index b8adbbd5bb..39779d1d57 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/nl.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Weet u zeker dat u deze pagina wilt verwijderen?", "PageId": "Bladzijde", "Pages": "Pagina's", - "PageSlugInformation": "Slug wordt gebruikt voor de url. Uw url wordt '/pages/{{slug}}'.", + "PageSlugInformation": "Slug wordt gebruikt voor de url. Uw url wordt '/{{slug}}'.", "Permission:BlogManagement": "Blogbeheer", "Permission:BlogManagement.Create": "Toevoegen", "Permission:BlogManagement.Delete": "Verwijderen", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json index 6c5e77a7d3..5a2ed06a5d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pl-PL.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Czy na pewno chcesz usunąć tę stronę?", "PageId": "Strona", "Pages": "Strony", - "PageSlugInformation": "Slug jest używany na adresie URL. Twój adres URL to „/pages/{{slug}}”.", + "PageSlugInformation": "Slug jest używany na adresie URL. Twój adres URL to „/{{slug}}”.", "Permission:BlogManagement": "Zarządzanie blogiem", "Permission:BlogManagement.Create": "Tworzyć", "Permission:BlogManagement.Delete": "Kasować", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json index 5ec2a64799..fff05fefdd 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/pt-BR.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Tem certeza que deseja deletar esta página?", "PageId": "Página", "Pages": "Páginas", - "PageSlugInformation": "Slug é usado na url. Sua url será '/pages/{{slug}}'.", + "PageSlugInformation": "Slug é usado na url. Sua url será '/{{slug}}'.", "Permission:BlogManagement": "Gerenciamento de blogs", "Permission:BlogManagement.Create": "Criar", "Permission:BlogManagement.Delete": "Excluir", @@ -181,6 +181,31 @@ "HasBlogPostWaitingForReviewMessage": "Você tem uma postagem para revisão. Clique para listar.", "SelectAStatus": "Selecione um status", "Status": "Status", - "CmsKit.BlogPost.ScrollIndex": "Barra de navegação rápida em postagens" + "CmsKit.BlogPost.ScrollIndex": "Barra de navegação rápida em postagens", + "Add": "Adicionar", + "AddWidget": "Adicionar Widget", + "PleaseConfigureWidgets": "Por favor, configure os widgets", + "SelectAnAuthor": "Selecione um Autor", + "InThisDocument": "Neste Documento", + "GoToTop": "Ir para o Topo", + "Feature:CmsKitGroup": "Cms Kit", + "Feature:BlogEnable": "Habilitar página de blog", + "Feature:BlogEnableDescription": "Habilitar página de blog no aplicativo.", + "Feature:CommentEnable": "Habilitar comentários", + "Feature:CommentEnableDescription": "Habilitar comentários no aplicativo.", + "Feature:GlobalResourceEnable": "Recursos globais ativados", + "Feature:GlobalResourceEnableDescription": "Habilitar recurso global no aplicativo.", + "Feature:MediaEnable": "Mídia ativada", + "Feature:MediaEnableDescription": "Mídia ativada no aplicativo.", + "Feature:MenuEnable": "Menu habilitado", + "Feature:MenuEnableDescription": "Menu habilitado no aplicativo.", + "Feature:PageEnable": "Página de paginação ativada", + "Feature:PageEnableDescription": "Página de paginação ativada no aplicativo.", + "Feature:RatingEnable": "Classificação ativada", + "Feature:RatingEnableDescription": "Classificação ativada no aplicativo.", + "Feature:ReactionEnable": "Reações habilitadas", + "Feature:ReactionEnableDescription": "Reações habilitadas no aplicativo.", + "Feature:TagEnable": "Habilitar tag", + "Feature:TagEnableDescription": "Habilitar tag no aplicativo." } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json index 3e7e1caaa9..9cd519bb53 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Sunteţi sigur(ă) că vreţi să ştergeţi această pagină?", "PageId": "Pagina", "Pages": "Pagini", - "PageSlugInformation": "Slug este folosit pe url. Url-ul dumneavoastră va fi '/pages/{{slug}}'.", + "PageSlugInformation": "Slug este folosit pe url. Url-ul dumneavoastră va fi '/{{slug}}'.", "Permission:BlogManagement": "Administrare Blog", "Permission:BlogManagement.Create": "Creează", "Permission:BlogManagement.Delete": "Şterge", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json index 289b952e1b..f95ee910e4 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ru.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Вы уверены, что хотите удалить эту страницу?", "PageId": "Страница", "Pages": "Страницы", - "PageSlugInformation": "Слаг используется для URL. Ваш URL-адрес будет '/pages/{{slug}}'.", + "PageSlugInformation": "Слаг используется для URL. Ваш URL-адрес будет '/{{slug}}'.", "Permission:BlogManagement": "Управление блогом", "Permission:BlogManagement.Create": "Создавать", "Permission:BlogManagement.Delete": "Удалить", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json index d5873f42e1..2cf9410ca9 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sk.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Určite chcete túto stránku vymazať?", "PageId": "Stránka", "Pages": "Stránky", - "PageSlugInformation": "Slug sa používa v URL. Vaša URL bude '/pages/{{slug}}'.", + "PageSlugInformation": "Slug sa používa v URL. Vaša URL bude '/{{slug}}'.", "Permission:BlogManagement": "Správa blogov", "Permission:BlogManagement.Create": "Vytvoriť", "Permission:BlogManagement.Delete": "Zmazať", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json index 0a79428aac..22f252ea51 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sl.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Ali ste prepričani, da želite izbrisati to stran?", "PageId": "stran", "Pages": "strani", - "PageSlugInformation": "Slug se uporablja na url-ju. Vaš url bo '/pages/{{slug}}'.", + "PageSlugInformation": "Slug se uporablja na url-ju. Vaš url bo '/{{slug}}'.", "Permission:BlogManagement": "Upravljanje blogov", "Permission:BlogManagement.Create": "Ustvari", "Permission:BlogManagement.Delete": "Izbriši", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json index 431c50596c..78fb34087b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/tr.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Bu sayfayı silmek istediğinize emin misiniz?", "PageId": "Sayfa", "Pages": "Sayfalar", - "PageSlugInformation": "Etiket URL'de kullanılır. Url şöyle görünür: '/pages/{{slug}}'.", + "PageSlugInformation": "Etiket URL'de kullanılır. Url şöyle görünür: '/{{slug}}'.", "Permission:BlogManagement": "Blog Yönetimi", "Permission:BlogManagement.Create": "Oluşturma", "Permission:BlogManagement.Delete": "Silme", @@ -190,6 +190,25 @@ "CmsKit.BlogPost.ScrollIndex": "Blog yazılarında hızlı gezinme çubuğu", "Add": "Ekle", "AddWidget": "Widget Ekle", - "PleaseConfigureWidgets": "Lütfen widget'leri yapılandırın" + "PleaseConfigureWidgets": "Lütfen widget'leri yapılandırın", + "Feature:CmsKitGroup": "Cms Kit", + "Feature:BlogEnable": "Blog sayfasını etkinleştirin", + "Feature:BlogEnableDescription": "Uygulamınızdaki blog sayfasını etkinleştirir.", + "Feature:CommentEnable": "Yorum özelliğini etkinleştirin", + "Feature:CommentEnableDescription": "Uygulamınızdaki yorum özelliğini etkinleştirir.", + "Feature:GlobalResourceEnable": "Blog global kaynakları etkinleştirin", + "Feature:GlobalResourceEnableDescription": "Uygulamınızdaki global kaynakları etkinleştirir.", + "Feature:MediaEnable": "Medyayı etkinleştirin", + "Feature:MediaEnableDescription": "Uygulamınızdaki medyayı etkinleştirir.", + "Feature:MenuEnable": "Menüyü etkinleştirin", + "Feature:MenuEnableDescription": "Uygulamınızdaki menüyü etkinleştirir.", + "Feature:PageEnable": "Sayfa özelliğini etkinleştirin", + "Feature:PageEnableDescription": "Uygulamınızdaki sayfa özelliğini etkinleştirir.", + "Feature:RatingEnable": "Oylamayı etkinleştirin", + "Feature:RatingEnableDescription": "Uygulamınızdaki oylamayı etkinleştirir.", + "Feature:ReactionEnable": "Reaksiyonları etkinleştirin", + "Feature:ReactionEnableDescription": "Uygulamınızdaki reaksiyonları etkinleştirir.", + "Feature:TagEnable": "Etkiketleri etkinleştirin", + "Feature:TagEnableDescription": "Uygulamınızdaki etiketleri etkinleştirir." } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json index b0ed51a5d6..a581da6362 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/vi.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "Bạn có chắc chắn xóa trang này không?", "PageId": "Trang", "Pages": "Các trang", - "PageSlugInformation": "Slug được sử dụng trên url. Url của bạn sẽ là '/pages/{{slug}}'.", + "PageSlugInformation": "Slug được sử dụng trên url. Url của bạn sẽ là '/{{slug}}'.", "Permission:BlogManagement": "Quản lý blog", "Permission:BlogManagement.Create": "Tạo ra", "Permission:BlogManagement.Delete": "Xóa bỏ", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json index b312349ef4..bba6fff938 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hans.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "你确定删除这个页面吗?", "PageId": "页", "Pages": "页面", - "PageSlugInformation": "Slug用于url. 你的url将是 '/pages/{{slug}}'.", + "PageSlugInformation": "Slug用于url. 你的url将是 '/{{slug}}'.", "Permission:BlogManagement": "博客管理", "Permission:BlogManagement.Create": "创建", "Permission:BlogManagement.Delete": "删除", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json index 49584e5af0..91a742deba 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/zh-Hant.json @@ -75,7 +75,7 @@ "PageDeletionConfirmationMessage": "你確定刪除這個頁面嗎?", "PageId": "頁", "Pages": "頁面", - "PageSlugInformation": "Slug用於網址. 你的網址將是 '/pages/{{slug}}'.", + "PageSlugInformation": "Slug用於網址. 你的網址將是 '/{{slug}}'.", "Permission:BlogManagement": "部落格管理", "Permission:BlogManagement.Create": "創建", "Permission:BlogManagement.Delete": "刪除", diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs index 9f03dc809f..ff07df87a1 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Pages/PageConsts.cs @@ -2,7 +2,7 @@ namespace Volo.CmsKit.Pages; -public class PageConsts +public static class PageConsts { public const string EntityType = "Page"; @@ -16,7 +16,7 @@ public class PageConsts public static int MaxStyleLength { get; set; } = int.MaxValue; - private static string _urlPrefix = "/pages/"; + private static string _urlPrefix = "/"; public static string UrlPrefix { get => _urlPrefix; set => _urlPrefix = value.EnsureEndsWith('/').EnsureStartsWith('/'); diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs index 2707b8854c..98a401af17 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/EntityTagManager.cs @@ -1,9 +1,9 @@ -using JetBrains.Annotations; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Volo.Abp.Domain.Services; namespace Volo.CmsKit.Tags; @@ -62,7 +62,7 @@ public class EntityTagManager : DomainService var deletedTags = existingTags.Where(x => !tags.Contains(x.Name)).ToList(); var addedTags = tags.Where(x => !existingTags.Any(a => a.Name == x)); - await EntityTagRepository.DeleteManyAsync(deletedTags.Select(s => s.Id).ToArray()); + await EntityTagRepository.DeleteManyAsync(deletedTags.Select(s => s.Id).ToArray(), entityId); foreach (var addedTag in addedTags) { @@ -85,6 +85,6 @@ public class EntityTagManager : DomainService [CanBeNull] Guid? tenantId, CancellationToken cancellationToken = default) { - return await EntityTagRepository.GetEntityIdsFilteredByTagNameAsync(tagName, entityType,tenantId, cancellationToken); + return await EntityTagRepository.GetEntityIdsFilteredByTagNameAsync(tagName, entityType, tenantId, cancellationToken); } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs index 5105635c82..098ac8e46c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Tags/IEntityTagRepository.cs @@ -1,8 +1,8 @@ -using JetBrains.Annotations; -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Volo.Abp.Domain.Repositories; namespace Volo.CmsKit.Tags; @@ -15,7 +15,7 @@ public interface IEntityTagRepository : IBasicRepository [CanBeNull] Guid? tenantId, CancellationToken cancellationToken = default); - Task DeleteManyAsync(Guid[] tagIds, CancellationToken cancellationToken = default); + Task DeleteManyAsync(Guid[] tagIds, string entityId, CancellationToken cancellationToken = default); Task> GetEntityIdsFilteredByTagAsync( [NotNull] Guid tagId, @@ -25,6 +25,6 @@ public interface IEntityTagRepository : IBasicRepository Task> GetEntityIdsFilteredByTagNameAsync( [NotNull] string tagName, [NotNull] string entityType, - [CanBeNull] Guid? tenantId=null, - CancellationToken cancellationToken=default); + [CanBeNull] Guid? tenantId = null, + CancellationToken cancellationToken = default); } diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs index c9e501edc0..8dfeacfc36 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Tags/EfCoreEntityTagRepository.cs @@ -1,9 +1,9 @@ -using JetBrains.Annotations; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Volo.Abp; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; @@ -19,11 +19,11 @@ public class EfCoreEntityTagRepository : EfCoreRepository(); - dbSet.RemoveRange(dbSet.Where(x => tagIds.Contains(x.TagId))); + dbSet.RemoveRange(dbSet.Where(x => tagIds.Contains(x.TagId) && x.EntityId == entityId)); await dbContext.SaveChangesAsync(GetCancellationToken(cancellationToken)); } @@ -56,18 +56,18 @@ public class EfCoreEntityTagRepository : EfCoreRepository> GetEntityIdsFilteredByTagNameAsync( [NotNull] string tagName, [NotNull] string entityType, - [CanBeNull] Guid? tenantId=null, - CancellationToken cancellationToken=default) + [CanBeNull] Guid? tenantId = null, + CancellationToken cancellationToken = default) { var dbContext = await GetDbContextAsync(); var result = from et in dbContext.Set() join t in dbContext.Set() on et.TagId equals t.Id - where t.Name == tagName - && t.EntityType == entityType - && et.TenantId == tenantId + where t.Name == tagName + && t.EntityType == entityType + && et.TenantId == tenantId && t.TenantId == tenantId && !t.IsDeleted - select et.EntityId; - return await result.ToListAsync(cancellationToken:GetCancellationToken(cancellationToken)); + select et.EntityId; + return await result.ToListAsync(cancellationToken: GetCancellationToken(cancellationToken)); } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs index e3835bfe42..b270255900 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Tags/MongoEntityTagRepository.cs @@ -1,15 +1,14 @@ -using JetBrains.Annotations; -using MongoDB.Driver; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; +using MongoDB.Driver; using Volo.Abp; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.MongoDB; using Volo.CmsKit.Tags; -using Tag = Volo.CmsKit.Tags.Tag; namespace Volo.CmsKit.MongoDB.Tags; @@ -20,12 +19,19 @@ public class MongoEntityTagRepository : MongoDbRepository.Filter.In(x => x.TagId, tagIds), token); + + var builder = Builders.Filter; + var filter = builder.And( + builder.In(x => x.TagId, tagIds), + builder.Eq(x => x.EntityId, entityId) + ); + + await collection.DeleteManyAsync(filter, token); } public virtual Task FindAsync( @@ -57,7 +63,7 @@ public class MongoEntityTagRepository : MongoDbRepository> GetEntityIdsFilteredByTagNameAsync( [NotNull] string tagName, [NotNull] string entityType, - [CanBeNull] Guid? tenantId=null, + [CanBeNull] Guid? tenantId = null, CancellationToken cancellationToken = default) { var dbContext = await GetDbContextAsync(); @@ -76,7 +82,7 @@ public class MongoEntityTagRepository : MongoDbRepository s.entityTag.EntityId); - + return await AsyncExecuter.ToListAsync(resultQueryable, GetCancellationToken(cancellationToken)); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/GlobalResources/GlobalResourceDto.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/GlobalResources/GlobalResourceDto.cs index 16e0575288..5d1ba87fe0 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/GlobalResources/GlobalResourceDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application.Contracts/Volo/CmsKit/Public/GlobalResources/GlobalResourceDto.cs @@ -1,8 +1,12 @@ -namespace Volo.CmsKit.Public.GlobalResources; +using System; +using Volo.Abp.Application.Dtos; -public class GlobalResourceDto +namespace Volo.CmsKit.Public.GlobalResources; + +[Serializable] +public class GlobalResourceDto : AuditedEntityDto { public string Name { get; set; } - + public string Value { get; set; } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs index 80185f7bea..87e851431d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Blogs/BlogPostPublicAppService.cs @@ -1,16 +1,19 @@ -using JetBrains.Annotations; -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using JetBrains.Annotations; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Blogs; using Volo.CmsKit.Contents; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Users; namespace Volo.CmsKit.Public.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPublicAppService { @@ -38,7 +41,7 @@ public class BlogPostPublicAppService : CmsKitPublicAppServiceBase, IBlogPostPub var blogPostDto = ObjectMapper.Map(blogPost); blogPostDto.ContentFragments = await ContentParser.ParseAsync(blogPost.Content); - + return blogPostDto; } diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs index b1fae564d2..ef7e6be9fd 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Comments/CommentPublicAppService.cs @@ -1,20 +1,23 @@ -using Microsoft.AspNetCore.Authorization; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; using Volo.Abp.Authorization; using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.Abp.Users; using Volo.CmsKit.Comments; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Users; namespace Volo.CmsKit.Public.Comments; +[RequiresFeature(CmsKitFeatures.CommentEnable)] [RequiresGlobalFeature(typeof(CommentsFeature))] public class CommentPublicAppService : CmsKitPublicAppServiceBase, ICommentPublicAppService { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicAppService.cs index 2debf10ed5..af0d1fbf39 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicAppService.cs @@ -1,11 +1,14 @@ using System.Threading.Tasks; using Volo.Abp.Application.Services; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.GlobalResources; namespace Volo.CmsKit.Public.GlobalResources; +[RequiresFeature(CmsKitFeatures.GlobalResourceEnable)] [RequiresGlobalFeature(typeof(GlobalResourcesFeature))] public class GlobalResourcePublicAppService : ApplicationService, IGlobalResourcePublicAppService { @@ -15,18 +18,18 @@ public class GlobalResourcePublicAppService : ApplicationService, IGlobalResourc { GlobalResourceManager = globalResourceManager; } - + public async Task GetGlobalScriptAsync() { var globalScript = await GlobalResourceManager.GetGlobalScriptAsync(); - + return ObjectMapper.Map(globalScript); } - + public async Task GetGlobalStyleAsync() { var globalStyle = await GlobalResourceManager.GetGlobalStyleAsync(); - + return ObjectMapper.Map(globalStyle); } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/Handlers/GlobalResourceEventHandler.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/Handlers/GlobalResourceEventHandler.cs index 1e9503006c..d16e271e4e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/Handlers/GlobalResourceEventHandler.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/GlobalResources/Handlers/GlobalResourceEventHandler.cs @@ -5,11 +5,10 @@ using Volo.Abp.Domain.Entities.Events; using Volo.Abp.EventBus; using Volo.Abp.ObjectMapping; using Volo.CmsKit.GlobalResources; -using Volo.CmsKit.Public.GlobalResources; namespace Volo.CmsKit.Public.GlobalResources.Handlers; -public class GlobalResourceEventHandler: +public class GlobalResourceEventHandler : ILocalEventHandler>, ITransientDependency { @@ -23,11 +22,11 @@ public class GlobalResourceEventHandler: ObjectMapper = objectMapper; _resourceCache = resourceCache; } - + public async Task HandleEventAsync(EntityUpdatedEventData eventData) { await _resourceCache.SetAsync( - eventData.Entity.Name, + eventData.Entity.Name, ObjectMapper.Map(eventData.Entity)); } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Menus/MenuItemPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Menus/MenuItemPublicAppService.cs index 11a58d5935..0e9062d9af 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Menus/MenuItemPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Menus/MenuItemPublicAppService.cs @@ -1,12 +1,15 @@ using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Caching; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Menus; namespace Volo.CmsKit.Public.Menus; +[RequiresFeature(CmsKitFeatures.MenuEnable)] [RequiresGlobalFeature(typeof(MenuFeature))] public class MenuItemPublicAppService : CmsKitPublicAppServiceBase, IMenuItemPublicAppService { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs index 2bae7c350f..f20a181e9b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Pages/PagePublicAppService.cs @@ -1,11 +1,14 @@ using System.Threading.Tasks; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Contents; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Pages; namespace Volo.CmsKit.Public.Pages; +[RequiresFeature(CmsKitFeatures.PageEnable)] [RequiresGlobalFeature(typeof(PagesFeature))] public class PagePublicAppService : CmsKitPublicAppServiceBase, IPagePublicAppService { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Ratings/RatingPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Ratings/RatingPublicAppService.cs index 87ea0531db..f3b46c518b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Ratings/RatingPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Ratings/RatingPublicAppService.cs @@ -1,15 +1,18 @@ -using Microsoft.AspNetCore.Authorization; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.Authorization; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.Abp.Users; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Ratings; using Volo.CmsKit.Users; namespace Volo.CmsKit.Public.Ratings; +[RequiresFeature(CmsKitFeatures.RatingEnable)] [RequiresGlobalFeature(typeof(RatingsFeature))] public class RatingPublicAppService : CmsKitPublicAppServiceBase, IRatingPublicAppService { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Reactions/ReactionPublicAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Reactions/ReactionPublicAppService.cs index b12f659d23..1151578d57 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Reactions/ReactionPublicAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Application/Volo/CmsKit/Public/Reactions/ReactionPublicAppService.cs @@ -1,17 +1,19 @@ -using Microsoft.AspNetCore.Authorization; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Linq.Dynamic.Core; -using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.Abp.Users; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Reactions; namespace Volo.CmsKit.Public.Reactions; +[RequiresFeature(CmsKitFeatures.ReactionEnable)] [RequiresGlobalFeature(typeof(ReactionsFeature))] public class ReactionPublicAppService : CmsKitPublicAppServiceBase, IReactionPublicAppService { diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs index be28afa6a4..e5d2570e21 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Blogs/BlogPostPublicController.cs @@ -3,13 +3,16 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Contents; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Users; namespace Volo.CmsKit.Public.Blogs; +[RequiresFeature(CmsKitFeatures.BlogEnable)] [RequiresGlobalFeature(typeof(BlogsFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Comments/CommentPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Comments/CommentPublicController.cs index afbf11e843..f77444431e 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Comments/CommentPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Comments/CommentPublicController.cs @@ -3,11 +3,14 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; namespace Volo.CmsKit.Public.Comments; +[RequiresFeature(CmsKitFeatures.CommentEnable)] [RequiresGlobalFeature(typeof(CommentsFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicController.cs index 8b58a00f9a..635e228e0b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/GlobalResources/GlobalResourcePublicController.cs @@ -1,16 +1,19 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; namespace Volo.CmsKit.Public.GlobalResources; +[RequiresFeature(CmsKitFeatures.GlobalResourceEnable)] [RequiresGlobalFeature(typeof(GlobalResourcesFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] [Route("api/cms-kit-public/global-resources")] -public class GlobalResourcePublicController: CmsKitPublicControllerBase, IGlobalResourcePublicAppService +public class GlobalResourcePublicController : CmsKitPublicControllerBase, IGlobalResourcePublicAppService { private readonly IGlobalResourcePublicAppService _globalResourcePublicAppService; @@ -18,14 +21,14 @@ public class GlobalResourcePublicController: CmsKitPublicControllerBase, IGlobal { _globalResourcePublicAppService = globalResourcePublicAppService; } - + [HttpGet] [Route("script")] public Task GetGlobalScriptAsync() { return _globalResourcePublicAppService.GetGlobalScriptAsync(); } - + [HttpGet] [Route("style")] public Task GetGlobalStyleAsync() diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Menus/MenuItemPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Menus/MenuItemPublicController.cs index fc8820c1b2..3eb00439fb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Menus/MenuItemPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Menus/MenuItemPublicController.cs @@ -2,13 +2,16 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Menus; namespace Volo.CmsKit.Public.Menus; -[RequiresGlobalFeature(typeof(BlogsFeature))] +[RequiresFeature(CmsKitFeatures.MenuEnable)] +[RequiresGlobalFeature(typeof(MenuFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] [Route("api/cms-kit-public/menu-items")] diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs index cd65f84c26..22f2bd75bd 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Pages/PagesPublicController.cs @@ -1,12 +1,15 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.Contents; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; namespace Volo.CmsKit.Public.Pages; +[RequiresFeature(CmsKitFeatures.PageEnable)] [RequiresGlobalFeature(typeof(PagesFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Ratings/RatingPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Ratings/RatingPublicController.cs index 11e8d22a69..f793aaefc4 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Ratings/RatingPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Ratings/RatingPublicController.cs @@ -2,11 +2,14 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; namespace Volo.CmsKit.Public.Ratings; +[RequiresFeature(CmsKitFeatures.RatingEnable)] [RequiresGlobalFeature(typeof(RatingsFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Reactions/ReactionPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Reactions/ReactionPublicController.cs index 4a9df74df7..6242e253a2 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Reactions/ReactionPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Reactions/ReactionPublicController.cs @@ -2,11 +2,14 @@ using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; namespace Volo.CmsKit.Public.Reactions; +[RequiresFeature(CmsKitFeatures.ReactionEnable)] [RequiresGlobalFeature(typeof(ReactionsFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagPublicController.cs b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagPublicController.cs index ec45901118..1620f136da 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagPublicController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.HttpApi/Volo/CmsKit/Public/Tags/TagPublicController.cs @@ -1,13 +1,16 @@ -using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; using Volo.Abp; +using Volo.Abp.Features; using Volo.Abp.GlobalFeatures; +using Volo.CmsKit.Features; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.Tags; namespace Volo.CmsKit.Public.Tags; +[RequiresFeature(CmsKitFeatures.TagEnable)] [RequiresGlobalFeature(typeof(TagsFeature))] [RemoteService(Name = CmsKitPublicRemoteServiceConsts.RemoteServiceName)] [Area(CmsKitPublicRemoteServiceConsts.ModuleName)] diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/Default.cshtml b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/Default.cshtml index 11929dec03..fdcfb382bb 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/Default.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/Default.cshtml @@ -1 +1,3 @@ - +@model Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.GlobalResources.Style.GlobalStyleModel + + \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/GlobalStyleModel.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/GlobalStyleModel.cs new file mode 100644 index 0000000000..869f768987 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/GlobalStyleModel.cs @@ -0,0 +1,6 @@ +namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.GlobalResources.Style; + +public class GlobalStyleModel +{ + public long LastModificationTimeTimestamp { get; set; } +} diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/GlobalStyleViewComponent.cs b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/GlobalStyleViewComponent.cs index 3d9bc010c4..49062bdb06 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/GlobalStyleViewComponent.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Pages/CmsKit/Shared/Components/GlobalResources/Style/GlobalStyleViewComponent.cs @@ -1,13 +1,33 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc; +using Volo.CmsKit.Public.GlobalResources; namespace Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.GlobalResources.Style; public class GlobalStyleViewComponent : AbpViewComponent { + protected IGlobalResourcePublicAppService GlobalResourcePublicAppService { get; } + + public GlobalStyleViewComponent(IGlobalResourcePublicAppService globalResourcePublicAppService) + { + GlobalResourcePublicAppService = globalResourcePublicAppService; + } + + [BindProperty(SupportsGet = true)] + public DateTime? LastModificationTime { get; set; } + public async Task InvokeAsync() { - return View("~/Pages/CmsKit/Shared/Components/GlobalResources/Style/Default.cshtml"); + var lastModificationTime = (await GlobalResourcePublicAppService.GetGlobalStyleAsync())?.LastModificationTime; + var lastModificationTimeTimestamp = (long)(lastModificationTime.HasValue ? lastModificationTime.Value.Subtract(DateTime.UnixEpoch).TotalSeconds : 0); + + return View("~/Pages/CmsKit/Shared/Components/GlobalResources/Style/Default.cshtml", + new GlobalStyleModel() + { + LastModificationTimeTimestamp = lastModificationTimeTimestamp + }); } + } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj index e126b222b0..da794f2eac 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Public.Web/Volo.CmsKit.Public.Web.csproj @@ -15,7 +15,7 @@ - + diff --git a/modules/cms-kit/src/Volo.CmsKit.Web/Volo.CmsKit.Web.csproj b/modules/cms-kit/src/Volo.CmsKit.Web/Volo.CmsKit.Web.csproj index e8aa365b66..ea7e47859b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Web/Volo.CmsKit.Web.csproj +++ b/modules/cms-kit/src/Volo.CmsKit.Web/Volo.CmsKit.Web.csproj @@ -19,7 +19,7 @@ - + diff --git a/modules/cms-kit/test/Volo.CmsKit.TestBase/Tags/EntityTagRepository_Test.cs b/modules/cms-kit/test/Volo.CmsKit.TestBase/Tags/EntityTagRepository_Test.cs index c200fd01f3..a895f4a949 100644 --- a/modules/cms-kit/test/Volo.CmsKit.TestBase/Tags/EntityTagRepository_Test.cs +++ b/modules/cms-kit/test/Volo.CmsKit.TestBase/Tags/EntityTagRepository_Test.cs @@ -9,11 +9,11 @@ namespace Volo.CmsKit.Tags; public abstract class EntityTagRepository_Test : CmsKitTestBase where TStartupModule : IAbpModule { - private CmsKitTestData _cmsKitTestData; - private IEntityTagRepository _entityTagRepository; - private ITagRepository _tagRepository; + private readonly CmsKitTestData _cmsKitTestData; + private readonly IEntityTagRepository _entityTagRepository; + private readonly ITagRepository _tagRepository; - public EntityTagRepository_Test() + protected EntityTagRepository_Test() { _cmsKitTestData = GetRequiredService(); _entityTagRepository = GetRequiredService(); @@ -25,7 +25,7 @@ public abstract class EntityTagRepository_Test : CmsKitTestBase< { var relatedTags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId); - await _entityTagRepository.DeleteManyAsync(relatedTags.Select(s => s.Id).ToArray()); + await _entityTagRepository.DeleteManyAsync(relatedTags.Select(s => s.Id).ToArray(), _cmsKitTestData.Content_1_EntityId); relatedTags = await _tagRepository.GetAllRelatedTagsAsync(_cmsKitTestData.Content_1_EntityType, _cmsKitTestData.Content_1_EntityId); @@ -35,7 +35,7 @@ public abstract class EntityTagRepository_Test : CmsKitTestBase< [Fact] public async Task GetEntityIdsFilteredByTagNameAsync_ShouldWorkProperly() { - var entityIds = await _entityTagRepository.GetEntityIdsFilteredByTagNameAsync(_cmsKitTestData.TagName_1, _cmsKitTestData.EntityType1); + var entityIds = await _entityTagRepository.GetEntityIdsFilteredByTagNameAsync(_cmsKitTestData.TagName_1, _cmsKitTestData.EntityType1); entityIds.ShouldNotBeNull(); entityIds.ShouldNotBeEmpty(); diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj index 781dc024c5..e7f372dfc6 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj @@ -23,7 +23,7 @@ - + diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json index 06ee0a6dfc..d926dfada9 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json @@ -32,7 +32,7 @@ "DisplayName:GitHubAccessToken": "Token de acesso do GitHub", "DisplayName:GitHubUserAgent": "Usuário agente do GitHub", "DisplayName:GithubVersionProviderSource": "Fonte do provedor de versão do GitHub", - "DisplayName:VersionBranchPrefix": "Prefixo da ramificação da versão", + "DisplayName:VersionBranchPrefix": "Prefixo da Branch da versão", "DisplayName:All": "Puxe tudo", "DisplayName:LanguageCode": "Código de idioma", "DisplayName:Version": "Versão", @@ -55,6 +55,7 @@ "LanguageCode": "Código de idioma", "FileName": "Nome do arquivo", "LastCachedTime": "Tempo de cache", - "Project": "Projeto" + "Project": "Projeto", + "AdvancedFilters": "Filtros Avançados" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Volo.Docs.Admin.Web.csproj b/modules/docs/src/Volo.Docs.Admin.Web/Volo.Docs.Admin.Web.csproj index 7ca9847f71..0e184f85ce 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Volo.Docs.Admin.Web.csproj +++ b/modules/docs/src/Volo.Docs.Admin.Web/Volo.Docs.Admin.Web.csproj @@ -27,7 +27,7 @@ - + diff --git a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj index d8548c9bbc..29020e50bc 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj +++ b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj @@ -20,7 +20,7 @@ - + diff --git a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj index afb85eee10..24085924a7 100644 --- a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj +++ b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj @@ -23,7 +23,7 @@ - + diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo.Abp.FeatureManagement.Domain.Shared.csproj b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo.Abp.FeatureManagement.Domain.Shared.csproj index 20e31fe161..8b1796e8fb 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo.Abp.FeatureManagement.Domain.Shared.csproj +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo.Abp.FeatureManagement.Domain.Shared.csproj @@ -15,7 +15,7 @@ - + diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj index b460935d48..4c72508f43 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Volo.Abp.FeatureManagement.Web.csproj @@ -28,7 +28,7 @@ - + diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo.Abp.Identity.Domain.Shared.csproj b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo.Abp.Identity.Domain.Shared.csproj index fd461ebe66..ddd23ab870 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo.Abp.Identity.Domain.Shared.csproj +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo.Abp.Identity.Domain.Shared.csproj @@ -27,7 +27,7 @@ - + diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs index ce6c7d7049..0e86e4e526 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityRole.cs @@ -62,7 +62,7 @@ public class IdentityRole : AggregateRoot, IMultiTenant Name = name; TenantId = tenantId; NormalizedName = name.ToUpperInvariant(); - ConcurrencyStamp = Guid.NewGuid().ToString(); + ConcurrencyStamp = Guid.NewGuid().ToString("N"); Claims = new Collection(); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index 834f0d8d7a..eec620395c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -158,7 +158,7 @@ public class IdentityUser : FullAuditedAggregateRoot, IUser NormalizedUserName = userName.ToUpperInvariant(); Email = email; NormalizedEmail = email.ToUpperInvariant(); - ConcurrencyStamp = Guid.NewGuid().ToString(); + ConcurrencyStamp = Guid.NewGuid().ToString("N"); SecurityStamp = Guid.NewGuid().ToString(); IsActive = true; diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj b/modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj index 8ffd329591..e9b57c9b01 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj +++ b/modules/identity/src/Volo.Abp.Identity.Web/Volo.Abp.Identity.Web.csproj @@ -45,7 +45,7 @@ - + diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo.Abp.Identity.Domain.Tests.csproj b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo.Abp.Identity.Domain.Tests.csproj index 0f1ec0b5f7..efec94a7ea 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo.Abp.Identity.Domain.Tests.csproj +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo.Abp.Identity.Domain.Tests.csproj @@ -19,7 +19,7 @@ - + diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs index 8b08732378..65c3ff5a39 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs @@ -112,7 +112,7 @@ public class IdentityUserStore_Tests : AbpIdentityDomainTestBase (await _identityUserStore.UpdateAsync(user)).Succeeded.ShouldBeTrue(); - user.ConcurrencyStamp = Guid.NewGuid().ToString(); + user.ConcurrencyStamp = Guid.NewGuid().ToString("N"); var identityResult = await _identityUserStore.UpdateAsync(user); identityResult.Succeeded.ShouldBeFalse(); diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderOptions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderOptions.cs index 1927c21746..66a15fd051 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderOptions.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderOptions.cs @@ -27,4 +27,10 @@ public class AbpIdentityServerBuilderOptions /// Set false to suppress AddDeveloperSigningCredential() call on the IIdentityServerBuilder. /// public bool AddDeveloperSigningCredential { get; set; } = true; + + /// + /// Adds the default cookie handlers and corresponding configuration + /// Default: true, Set false to suppress AddCookieAuthentication() call on the IIdentityServerBuilder. + /// + public bool AddIdentityServerCookieAuthentication { get; set; } = true; } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs index 96ab4abd89..9b9dde5c96 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using IdentityServer4.Configuration; using IdentityServer4.Services; using IdentityServer4.Stores; using Microsoft.Extensions.DependencyInjection; @@ -71,13 +72,7 @@ public class AbpIdentityServerDomainModule : AbpModule var configuration = services.GetConfiguration(); var builderOptions = services.ExecutePreConfiguredActions(); - var identityServerBuilder = services.AddIdentityServer(options => - { - options.Events.RaiseErrorEvents = true; - options.Events.RaiseInformationEvents = true; - options.Events.RaiseFailureEvents = true; - options.Events.RaiseSuccessEvents = true; - }); + var identityServerBuilder = AddIdentityServer(services, builderOptions); if (builderOptions.AddDeveloperSigningCredential) { @@ -110,6 +105,37 @@ public class AbpIdentityServerDomainModule : AbpModule } } + private static IIdentityServerBuilder AddIdentityServer(IServiceCollection services, AbpIdentityServerBuilderOptions abpIdentityServerBuilderOptions) + { + services.Configure(options => + { + options.Events.RaiseErrorEvents = true; + options.Events.RaiseInformationEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseSuccessEvents = true; + }); + + var identityServerBuilder = services.AddIdentityServerBuilder() + .AddRequiredPlatformServices() + .AddCoreServices() + .AddDefaultEndpoints() + .AddPluggableServices() + .AddValidators() + .AddResponseGenerators() + .AddDefaultSecretParsers() + .AddDefaultSecretValidators(); + + if (abpIdentityServerBuilderOptions.AddIdentityServerCookieAuthentication) + { + identityServerBuilder.AddCookieAuthentication(); + } + + // provide default in-memory implementation, not suitable for most production scenarios + identityServerBuilder.AddInMemoryPersistedGrants(); + + return identityServerBuilder; + } + public override void PostConfigureServices(ServiceConfigurationContext context) { OneTimeRunner.Run(() => diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj index 34a4d6c334..2644d555f4 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj @@ -15,7 +15,7 @@ - + diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Localization/OpenIddict/pt-BR.json b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Localization/OpenIddict/pt-BR.json index 2952a0352c..6962ebcc4c 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Localization/OpenIddict/pt-BR.json +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo/Abp/OpenIddict/Localization/OpenIddict/pt-BR.json @@ -4,10 +4,10 @@ "TheOpenIDConnectRequestCannotBeRetrieved": "Não foi possivel recuperar a requisição do OpenID Connect.", "TheUserDetailsCannotBbeRetrieved": "Não foi possivel recuperar os detalhes do usuário.", "TheApplicationDetailsCannotBeFound": "Os detalhes da aplicação não foram encontrados.", - "DetailsConcerningTheCallingClientApplicationCannotBeFound": "Os detalhes relativos ao aplicativo cliente requisitante não firam encontrados.", + "DetailsConcerningTheCallingClientApplicationCannotBeFound": "Os detalhes relativos ao aplicativo cliente requisitante não foram encontrados.", "TheSpecifiedGrantTypeIsNotImplemented.": "O tipo de permissão {0} não está implementando.", "Authorization": "Autorização", - "DoYouWantToGrantAccessToYourData": "Deseja permitir {0} acesse seus dados?", + "DoYouWantToGrantAccessToYourData": "Deseja permitir {0} acessar seus dados?", "ScopesRequested": "Escopo solicitado", "Accept": "Aceitar", "Deny": "Negar" diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs index af5999fcc5..267fb175e2 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo/Abp/OpenIddict/Scopes/AbpOpenIddictScopeCache.cs @@ -9,11 +9,11 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.OpenIddict.Scopes; -public class AbpOpenIddictScopeCacheAbpOpenIddictAuthorizationCache : AbpOpenIddictCacheBase>, +public class AbpOpenIddictScopeCache : AbpOpenIddictCacheBase>, IOpenIddictScopeCache, ITransientDependency { - public AbpOpenIddictScopeCacheAbpOpenIddictAuthorizationCache( + public AbpOpenIddictScopeCache( IDistributedCache cache, IDistributedCache arrayCache, IOpenIddictScopeStore store) diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo.Abp.PermissionManagement.Domain.Shared.csproj b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo.Abp.PermissionManagement.Domain.Shared.csproj index c44c0b326f..70c8b26f2d 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo.Abp.PermissionManagement.Domain.Shared.csproj +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo.Abp.PermissionManagement.Domain.Shared.csproj @@ -25,7 +25,7 @@ - + diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Volo.Abp.PermissionManagement.Web.csproj b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Volo.Abp.PermissionManagement.Web.csproj index d289598e8b..1fb94a5eae 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Volo.Abp.PermissionManagement.Web.csproj +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Volo.Abp.PermissionManagement.Web.csproj @@ -35,7 +35,7 @@ - + diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo.Abp.SettingManagement.Domain.Shared.csproj b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo.Abp.SettingManagement.Domain.Shared.csproj index f6c3e0a102..38991408d5 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo.Abp.SettingManagement.Domain.Shared.csproj +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo.Abp.SettingManagement.Domain.Shared.csproj @@ -21,7 +21,7 @@ - + diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj index 9307cfa02e..f4f03b3706 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Volo.Abp.SettingManagement.Web.csproj @@ -23,7 +23,7 @@ - + diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo.Abp.TenantManagement.Domain.Shared.csproj b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo.Abp.TenantManagement.Domain.Shared.csproj index 7aa53a7476..effe1e51f4 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo.Abp.TenantManagement.Domain.Shared.csproj +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo.Abp.TenantManagement.Domain.Shared.csproj @@ -25,7 +25,7 @@ - + diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/AbpTenantManagementDomainSharedModule.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/AbpTenantManagementDomainSharedModule.cs index e0ce655235..5b388d9078 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/AbpTenantManagementDomainSharedModule.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/AbpTenantManagementDomainSharedModule.cs @@ -1,6 +1,7 @@ using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.TenantManagement.Localization; +using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Validation; using Volo.Abp.Validation.Localization; using Volo.Abp.VirtualFileSystem; @@ -25,5 +26,10 @@ public class AbpTenantManagementDomainSharedModule : AbpModule typeof(AbpValidationResource) ).AddVirtualJson("/Volo/Abp/TenantManagement/Localization/Resources"); }); + + Configure(options => + { + options.MapCodeNamespace("Volo.Abp.TenantManagement", typeof(AbpTenantManagementResource)); + }); } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ar.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ar.json index 267165038c..8146974400 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ar.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ar.json @@ -1,6 +1,7 @@ { "culture": "ar", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "اسم المستأجر موجود بالفعل: {Name}", "Menu:TenantManagement": "إدارة الجهات", "Tenants": "الجهات", "NewTenant": "جهة جديدة", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/de-DE.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/de-DE.json index c744619234..58d71c9252 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/de-DE.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/de-DE.json @@ -1,6 +1,7 @@ { "culture": "de-DE", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Der Name des Mandanten ist bereits vorhanden: {Name}", "Menu:TenantManagement": "Mandantenverwaltung", "Tenants": "Mandanten", "NewTenant": "Neuer Mandant", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/en.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/en.json index da222e994d..e639feb5f3 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/en.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/en.json @@ -1,6 +1,7 @@ { "culture": "en", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Tenant name already exist: {Name}", "Menu:TenantManagement": "Tenant management", "Tenants": "Tenants", "NewTenant": "New tenant", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/es.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/es.json index a570c4a84e..bcbfc98852 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/es.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/es.json @@ -1,6 +1,7 @@ { "culture": "es", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "El nombre del inquilino ya existe: {Name}", "Menu:TenantManagement": "Gestión de tenants", "Tenants": "Inquilinos", "NewTenant": "Nuevo inquilino", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fi.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fi.json index 3bd039ffcf..179ec3c1d6 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fi.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fi.json @@ -1,6 +1,7 @@ { "culture": "fi", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Vuokralaisen nimi on jo olemassa: {Name}", "Menu:TenantManagement": "Vuokralaisten hallinta", "Tenants": "Vuokralaiset", "NewTenant": "Uusi vuokralainen", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fr.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fr.json index 771a1e1fd5..3537ca8ca6 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fr.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/fr.json @@ -1,6 +1,7 @@ { "culture": "fr", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Le nom du locataire existe déjà: {Name}", "Menu:TenantManagement": "Gestion des locataires", "Tenants": "Locataires", "NewTenant": "Nouveau locataire", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/hi.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/hi.json index 45e5de55c0..70367305a9 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/hi.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/hi.json @@ -1,6 +1,7 @@ { "culture": "hi", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "किरायेदार नाम पहले से मौजूद है: {Name}", "Menu:TenantManagement": "किरायेदार प्रबंधन", "Tenants": "किरायेदारों", "NewTenant": "नया किरायेदार", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/it.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/it.json index efc7cb2f6b..5d95e2039c 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/it.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/it.json @@ -1,6 +1,7 @@ { "culture": "it", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Il nome del tenant esiste già: {Name}", "Menu:TenantManagement": "Gestione tenants", "Tenants": "Tenants", "NewTenant": "Nuovo Tenant", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/pt-BR.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/pt-BR.json index 9d0771ed9e..d9f6b14a69 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/pt-BR.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/pt-BR.json @@ -1,6 +1,7 @@ { "culture": "pt-BR", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "O nome do ambiente já existe: {Name}", "Menu:TenantManagement": "Gerencimento de Inquilinos", "Tenants": "Inquilinos", "NewTenant": "Novo Inquilino", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ru.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ru.json index b737b7ee24..2204cf35cf 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ru.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ru.json @@ -1,6 +1,7 @@ { "culture": "ru", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Имя арендатора уже существует: {Name}", "Menu:TenantManagement": "Управление арендаторами", "Tenants": "Арендаторы", "NewTenant": "Новый арендатор", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sk.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sk.json index 0689dee0e2..1aff65e71c 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sk.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sk.json @@ -1,6 +1,7 @@ { "culture": "sk", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Názov tenanta už existuje: {Name}", "Menu:TenantManagement": "Správa tenantov", "Tenants": "Tentanti", "NewTenant": "Nový tenant", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sl.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sl.json index bc2d857331..a21cfa702a 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sl.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/sl.json @@ -1,6 +1,7 @@ { "culture": "sl", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Ime najemnika že obstaja: {Name}", "Menu:TenantManagement": "Upravljanje najemnikov", "Tenants": "Najemniki", "NewTenant": "Nov najemnik", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/tr.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/tr.json index 933f4a4650..409aa40795 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/tr.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/tr.json @@ -1,6 +1,7 @@ { "culture": "tr", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "Müşteri ismi zaten mevcut: {Name}", "Menu:TenantManagement": "Müşteri yönetimi", "Tenants": "Müşteriler", "NewTenant": "Yeni müşteri", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hans.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hans.json index 1e8e98412a..0367489a5a 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hans.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hans.json @@ -1,6 +1,7 @@ { "culture": "zh-Hans", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "租户名称已存在: {Name}", "Menu:TenantManagement": "租户管理", "Tenants": "租户", "NewTenant": "新租户", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hant.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hant.json index 200dde595f..59519aff67 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hant.json +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/zh-Hant.json @@ -1,6 +1,7 @@ { "culture": "zh-Hant", "texts": { + "Volo.Abp.TenantManagement:DuplicateTenantName": "租戶名稱已存在: {Name}", "Menu:TenantManagement": "租戶管理", "Tenants": "租戶", "NewTenant": "新租戶", diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 8fc75d2ecb..fa388426d9 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -36,7 +36,7 @@ public class TenantManager : DomainService, ITenantManager var tenant = await TenantRepository.FindByNameAsync(name); if (tenant != null && tenant.Id != expectedId) { - throw new UserFriendlyException("Duplicate tenancy name: " + name); //TODO: A domain exception would be better..? + throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", name); } } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Volo.Abp.TenantManagement.Web.csproj b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Volo.Abp.TenantManagement.Web.csproj index 7e211e504c..baa3cdb03c 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Volo.Abp.TenantManagement.Web.csproj +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Web/Volo.Abp.TenantManagement.Web.csproj @@ -39,7 +39,7 @@ - + diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs index 6b86c8503c..b797e05566 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Application.Tests/Volo/Abp/TenantManagement/TenantAppService_Tests.cs @@ -66,7 +66,7 @@ public class TenantAppService_Tests : AbpTenantManagementApplicationTestBase [Fact] public async Task CreateAsync_Should_Not_Allow_Duplicate_Names() { - await Assert.ThrowsAsync(async () => + await Assert.ThrowsAsync(async () => { await _tenantAppService.CreateAsync(new TenantCreateDto { Name = "acme", AdminEmailAddress = "admin@admin.com", AdminPassword = "123456" }); }); @@ -90,7 +90,7 @@ public class TenantAppService_Tests : AbpTenantManagementApplicationTestBase { var acme = UsingDbContext(dbContext => dbContext.Tenants.Single(t => t.Name == "acme")); - await Assert.ThrowsAsync(async () => + await Assert.ThrowsAsync(async () => { await _tenantAppService.UpdateAsync(acme.Id, new TenantUpdateDto { Name = "volosoft" }); }); diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs index fcacb22e37..161882e412 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantManager_Tests.cs @@ -26,7 +26,7 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase [Fact] public async Task Create_Tenant_Name_Can_Not_Duplicate() { - await Assert.ThrowsAsync(async () => await _tenantManager.CreateAsync("volosoft")); + await Assert.ThrowsAsync(async () => await _tenantManager.CreateAsync("volosoft")); } [Fact] @@ -46,6 +46,6 @@ public class TenantManager_Tests : AbpTenantManagementDomainTestBase var tenant = await _tenantRepository.FindByNameAsync("acme"); tenant.ShouldNotBeNull(); - await Assert.ThrowsAsync(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft")); + await Assert.ThrowsAsync(async () => await _tenantManager.ChangeNameAsync(tenant, "volosoft")); } } diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pt-BR.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pt-BR.json index d6fb96ed4e..f4b0675210 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pt-BR.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/pt-BR.json @@ -8,7 +8,7 @@ "VirtualFileName": "Nome do arquivo virtual", "FileContent": "Conteúdo do arquivo", "Size": "Tamanho", - "BackToRoot": "De volta à raiz", + "BackToRoot": "Voltar à raiz", "EmptyFileInfoList": "Não há arquivos virtuais" } } \ No newline at end of file diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj index 32ae96fa5b..4558a035fc 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.csproj @@ -34,7 +34,7 @@ - + diff --git a/npm/ng-packs/.gitignore b/npm/ng-packs/.gitignore index 326e29324e..b542c2b12d 100644 --- a/npm/ng-packs/.gitignore +++ b/npm/ng-packs/.gitignore @@ -54,3 +54,5 @@ Thumbs.db !**/[Pp]ackages/* *.internal.* + +.angular diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index 953d2d5f93..ae2b77443e 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -34,7 +34,9 @@ "dev:schematics": "tsc -p packages/schematics/tsconfig.json -w", "ci": "yarn affected:lint && yarn affected:build && yarn affected:test", "lerna": "lerna", - "migrate-nx": "yarn nx migrate --run-migrations" + "migrate-nx": "yarn nx migrate --run-migrations", + "mock:schematics": "cd scripts/mock-schematic && yarn && yarn start", + "debug:schematics": "./node_modules/.bin/ng g ./packages/schematics/src/collection.json:proxy-add --module __default --apiName __default --source __default --target __default --url http://localhost:4300" }, "private": true, "devDependencies": { diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html index 7873adf6ea..99d435c891 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html @@ -39,7 +39,7 @@ >
-
+