diff --git a/.github/workflows/auto-pr.yml b/.github/workflows/auto-pr.yml index 4f28b14a9c..a572653e48 100644 --- a/.github/workflows/auto-pr.yml +++ b/.github/workflows/auto-pr.yml @@ -27,10 +27,12 @@ jobs: title: Merge branch dev with rel-9.0 body: This PR generated automatically to merge dev with rel-9.0. Please review the changed files before merging to prevent any errors that may occur. reviewers: maliming + draft: true token: ${{ github.token }} - name: Merge Pull Request env: GH_TOKEN: ${{ secrets.BOT_SECRET }} run: | + gh pr ready gh pr review auto-merge/rel-9-0/${{github.run_number}} --approve - gh pr merge auto-merge/rel-9-0/${{github.run_number}} --merge --auto --delete-branch \ No newline at end of file + gh pr merge auto-merge/rel-9-0/${{github.run_number}} --merge --auto --delete-branch diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index b707786d73..88b94689d6 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -51,7 +51,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-dotnet@master with: - dotnet-version: 9.0.100-rc.2.24474.11 + dotnet-version: 9.0.100 - name: chown run: | diff --git a/Directory.Packages.props b/Directory.Packages.props index 6991b372b7..ddadecbc2b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,7 +6,7 @@ - + @@ -17,10 +17,10 @@ - - - - + + + + @@ -51,60 +51,60 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - + @@ -114,7 +114,7 @@ - + @@ -155,17 +155,17 @@ - + - + - - - + + + diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 9fb30d3fda..0e8546ae41 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -22,6 +22,7 @@ "Permission:Accounting": "Accounting", "Permission:Accounting:Quotation": "Quotation", "Permission:Accounting:Invoice": "Invoice", + "Permission:Export" : "Export", "Menu:Organizations": "Organizations", "Menu:Accounting": "Accounting", "Menu:Packages": "Packages", @@ -511,6 +512,7 @@ "QuotationTemplate.BankAccount": "Our bank account information can be found at {0}", "Permission:Raffles": "Raffle", "Permission:Draw": "Draw", + "Permission:ExportAttendeesAsExcel": "Export at attendees as Excel", "Menu:Raffles": "Raffles", "RaffleIsNotDrawable": "Raffle is not drawable", "WinnerCountMustBeGreaterThanZero": "Winner count must be greater than zero", @@ -649,6 +651,19 @@ "Permission:HeroSections": "Hero Sections", "RedirectLink": "Redirect link", "HeroSectionsDeletionConfirmationMessage": "Are you sure you want to delete the hero section?", - "AbpStudioName": "Abp Studio name" + "AbpStudioName": "ABP Studio name", + "Permission:EditAttendees": "Edit Attendees", + "AttendeesCount": "Attendees Count", + "CreateQRCode": "Create QR Code", + "DrawTV": "Public draw on the TV", + "DrawModal": "Private draw on the modal", + "SetAsDrawable": "Set as drawable", + "SetAsNoDrawable": "Set as non-drawable", + "SetAsCompleted": "Set as completed", + "RemoveAllWinners": "Remove all winners", + "EditWinners": "Edit winners", + "EditAttendees": "Edit attendees", + "ExportAttendeesAsExcel": "Export attendees as Excel", + "DuplicateRaffle": "Duplicate raffle" } -} \ No newline at end of file +} diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index ae040e7fd2..4856813fe1 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -1211,6 +1211,5 @@ "TrainingDescription": "We are offering the following training packages for who want to get expertise on the ABP Framework and the ABP.", "PurchaseDevelopers": "developers", "LinkExpiredMessage": "The payment link has expired! Contact us at sales@volosoft.com to update the link or click here to navigate to the contact page." - } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 581d9bf6fc..08e1687357 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -459,7 +459,7 @@ "FullName": "Full name", "CompanySize": "Company size", "TestimonialTitle": "Let's hear your testimonial", - "TestimonialInfo": "What our customers say matters! Tell us about your experience with our product and service. It is recommended to write the testimonial in English to reach a wider audience.", + "TestimonialInfo": "What you say matters! Tell us about your experience with ABP in a few sentences. Please write it in English to reach a wider audience.", "Country": "Country", "TestimonialTextPlaceholder": "Write a brief story about how ABP helped you build and deliver your project.", "PositionPlaceholder": "Your position at your company", @@ -1691,8 +1691,8 @@ "HurryUpLastDay": "Hurry Up! Last Day: {0}", "CreatingCRUDPagesWithABPSuite": "Creating CRUD pages with ABP Suite", "MultipleYearDiscount": "Multiple Year Discount", - "CampaignDiscountText": "New Platform Discount", - "CampaignDiscountName": "New Platform", + "CampaignDiscountText": "Black Friday Discount", + "CampaignDiscountName": "Black Friday", "CampaignName:BlackFriday": "Black Friday", "MultipleOrganizationInfo": "See All Your Organizations", "AbpStudioBetaAccessInfoTitle": "ABP Studio Beta Access", @@ -1867,6 +1867,7 @@ "NewsletterEmailFooterTemplateDeleteSubscription": "If you change your mind, you're always welcome to resubscribe!", "GenerateQuote" : "Generate Quote" , "GeneratePriceQuote": "Generate a Price Quote", - "Qa:QuestionPageTitle": "Support" + "Qa:QuestionPageTitle": "Support", + "SelectedTrainingName" : "Trainings" } } diff --git a/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/docs-image-larger.png b/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/docs-image-larger.png index 7e49b10aee..95b999560e 100644 Binary files a/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/docs-image-larger.png and b/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/docs-image-larger.png differ diff --git a/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/suite-navigation-properties.png b/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/suite-navigation-properties.png index 3669804a0c..4d329ccc7b 100644 Binary files a/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/suite-navigation-properties.png and b/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/suite-navigation-properties.png differ diff --git a/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/community-talks.png b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/community-talks.png new file mode 100644 index 0000000000..7263b68e10 Binary files /dev/null and b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/community-talks.png differ diff --git a/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/cover-image.png b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/cover-image.png new file mode 100644 index 0000000000..f272a8d463 Binary files /dev/null and b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/cover-image.png differ diff --git a/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/post.md b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/post.md new file mode 100644 index 0000000000..26850bc57f --- /dev/null +++ b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/post.md @@ -0,0 +1,93 @@ +# ABP.IO Platform 9.0 Has Been Released Based on .NET 9.0 + +![](cover-image.png) + +Today, [ABP](https://abp.io/) 9.0 stable version has been released based on [.NET 9.0](https://dotnet.microsoft.com/en-us/download/dotnet/9.0). You can create solutions with ABP 9.0 starting from ABP Studio v0.9.11 or by using the ABP CLI as explained in the following sections. + +## What's New With Version 9.0? + +All the new features were explained in detail in the [9.0 RC Announcement Post](https://abp.io/blog/announcing-abp-9-0-release-candidate), so there is no need to review them again. You can check it out for more details. + +## Getting Started with 9.0 + +### Creating New Solutions + +You can check the [Get Started page](https://abp.io/get-started) to see how to get started with ABP. You can either download [ABP Studio](https://abp.io/get-started#abp-studio-tab) (**recommended**, if you prefer a user-friendly GUI application - desktop application) or use the [ABP CLI](https://abp.io/docs/latest/cli) to create new solutions. + +By default, ABP Studio uses stable versions to create solutions. Therefore, it will be creating the solution with the latest stable version, which is v9.0 for now, so you don't need to specify the version. **You can create solutions with ABP 9.0 starting from v0.9.11.** + +### How to Upgrade an Existing Solution + +You can upgrade your existing solutions with either ABP Studio or ABP CLI. In the following sections, both approaches are explained: + +### Upgrading via ABP Studio + +If you are already using the ABP Studio, you can upgrade it to the latest version to align it with ABP v9.0. ABP Studio periodically checks for updates in the background, and when a new version of ABP Studio is available, you will be notified through a modal. Then, you can update it by confirming the opened modal. See [the documentation](https://abp.io/docs/latest/studio/installation#upgrading) for more info. + +After upgrading the ABP Studio, then you can open your solution in the application, and simply click the **Switch to stable** action button to instantly upgrade your solution: + +![](switch-to-stable.png) + +> Please note that ABP CLI & ABP Studio only upgrade the related ABP packages, so you need to upgrade the other packages for .NET 9.0 manually. + +### Upgrading via ABP CLI + +Alternatively, you can upgrade your existing solution via ABP CLI. First, you need to install the ABP CLI or upgrade it to the latest version. + +If you haven't installed it yet, you can run the following command: + +```bash +dotnet tool install -g Volo.Abp.Studio.Cli +``` + +Or to update the existing CLI, you can run the following command: + +```bash +dotnet tool update -g Volo.Abp.Studio.Cli +``` + +After installing/updating the ABP CLI, you can use the [`update` command](https://abp.io/docs/latest/CLI#update) to update all the ABP related NuGet and NPM packages in your solution as follows: + +```bash +abp update +``` + +You can run this command in the root folder of your solution to update all ABP related packages. + +> Please note that ABP CLI & ABP Studio only upgrade the related ABP packages, so you need to upgrade the other packages for .NET 9.0 manually. + +## Migration Guides + +There are a few breaking changes in this version that may affect your application. Please read the migration guide carefully, if you are upgrading from v8.x: [ABP Version 9.0 Migration Guide](https://abp.io/docs/9.0/release-info/migration-guides/abp-9-0) + +## Community News + +### Highlights from .NET 9.0 + +Our team has closely followed the ASP.NET Core and Entity Framework Core 9.0 releases, read Microsoft's guides and documentation, and adapted the changes to our ABP.IO Platform. We are proud to say that we've shipped the ABP 9.0 based on .NET 9.0 just after Microsoft's .NET 9.0 release. + +In addition to the ABP's .NET 9.0 upgrade, our team has created many great articles to highlight the important features coming with ASP.NET Core 9.0 and Entity Framework Core 9.0. + +> You can read [this post](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-9-0) to see the list of all articles. + +### New ABP Community Articles + +In addition to [the articles to highlight .NET 9.0 features written by our team](https://volosoft.com/blog/Highlights-for-ASP-NET-Entity-Framework-Core-NET-9-0), here are some of the recent posts added to the [ABP Community](https://abp.io/community): + +* [Video: Building Modular Monolith Applications with ASP.NET Core & ABP Studio](https://abp.io/community/videos/building-modular-monolith-applications-with-asp.net-core-abp-studio-66znukvf) by [Halil İbrahim Kalkan](https://x.com/hibrahimkalkan) +* [How to create your Own AI Bot on WhatsApp Using an ABP.io Template](https://abp.io/community/articles/how-to-create-your-own-ai-bot-on-whatsapp-using-the-abp-framework-c6jgvt9c) by [Michael Kokula](https://abp.io/community/members/Michal_Kokula) +* [ABP Now Supports .NET 9](https://abp.io/community/articles/abp-now-supports-.net-9-zpkznc4f) by [Alper Ebiçoğlu](https://x.com/alperebicoglu) + +Thanks to the ABP Community for all the content they have published. You can also [post your ABP related (text or video) content](https://abp.io/community/posts/submit) to the ABP Community. + +### ABP Community Talks 2024.7: What’s New with .NET 9 & ABP 9? + +![](community-talks.png) + +In this episode of ABP Community Talks, 2024.7; we will dive into the features that came with .NET 9.0 with [Alper Ebicoglu](https://github.com/ebicoglu), [Engincan Veske](https://github.com/EngincanV), [Berkan Sasmaz](https://github.com/berkansasmaz) and [Ahmet Faruk Ulu](https://github.com/ahmetfarukulu). + +## Conclusion + +This version comes with some new features and a lot of enhancements to the existing features. You can see the [Road Map](https://docs.abp.io/en/abp/9.0/Road-Map) documentation to learn about the release schedule and planned features for the next releases. Please try ABP v9.0 and provide feedback to help us release more stable versions. + +Thanks for being a part of this community! diff --git a/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/switch-to-stable.png b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/switch-to-stable.png new file mode 100644 index 0000000000..30883ebf92 Binary files /dev/null and b/docs/en/Blog-Posts/2024-11-19 v9_0_Release_Stable/switch-to-stable.png differ diff --git a/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/cover.png b/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/cover.png index 68a18b85fe..5c7f576575 100644 Binary files a/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/cover.png and b/docs/en/Community-Articles/2024-10-09-Cookies-vs-Local-Storage/cover.png differ diff --git a/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cited-from-microsoft-blog-post.png b/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cited-from-microsoft-blog-post.png index c35771b071..5deb5c12fb 100644 Binary files a/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cited-from-microsoft-blog-post.png and b/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cited-from-microsoft-blog-post.png differ diff --git a/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cover.png b/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cover.png index 91ed380f6d..bec5aa6579 100644 Binary files a/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cover.png and b/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cover.png differ diff --git a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-existing-package.png b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-existing-package.png index 27b445c6d4..a5940a931f 100644 Binary files a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-existing-package.png and b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-existing-package.png differ diff --git a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-new-microservice.png b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-new-microservice.png index 5acbb8e582..7af8143949 100644 Binary files a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-new-microservice.png and b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-add-new-microservice.png differ diff --git a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-solution-runner.png b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-solution-runner.png index d761a60374..27047da5c6 100644 Binary files a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-solution-runner.png and b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-solution-runner.png differ diff --git a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-vs-dotnet-aspire-comparison-table.png b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-vs-dotnet-aspire-comparison-table.png index 170220507e..8b27070d5c 100644 Binary files a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-vs-dotnet-aspire-comparison-table.png and b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/abp-studio-vs-dotnet-aspire-comparison-table.png differ diff --git a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/dotnet-aspire-dashboard.png b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/dotnet-aspire-dashboard.png index e42f39d948..a0401a3fd0 100644 Binary files a/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/dotnet-aspire-dashboard.png and b/docs/en/Community-Articles/2024-10-11-NET-Aspire-vs-ABP-Studio/dotnet-aspire-dashboard.png differ diff --git a/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/dog-food.png b/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/dog-food.png index ac1d243444..67294f7596 100644 Binary files a/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/dog-food.png and b/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/dog-food.png differ diff --git a/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/net-support-policy.png b/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/net-support-policy.png index 0f9ac3f4e9..ae7afa5d8b 100644 Binary files a/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/net-support-policy.png and b/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/net-support-policy.png differ diff --git a/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/POST.md b/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/POST.md new file mode 100644 index 0000000000..3cd4bdc706 --- /dev/null +++ b/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/POST.md @@ -0,0 +1,125 @@ +# Hybrid Cache in .NET 9 + +.NET 9 introduces an exciting feature: **HybridCache**, an advanced caching mechanism that seamlessly combines multiple caching strategies to maximize performance and scalability. + +It offers a flexible caching solution that combines the best aspects of local and distributed caching. **HybridCache** is particularly useful in scenarios where quick, in-memory access is desirable but data consistency across multiple application instances is also a requirement. + +In this article, we’ll explore **HybridCache** in .NET 9 and how it integrates with ABP Framework using `AbpHybridCache`. This new feature offers a robust solution for applications that need to scale while maintaining efficient caching strategies. + +## What is HybridCache? + +**HybridCache** is designed to merge different caching layers, commonly including an in-memory cache (for high-speed access) and a distributed cache (for scalability across multiple instances). This hybrid approach allows for: + +* **Improved Performance**: Frequently accessed data is stored in-memory, reducing latency. +* **Increased Scalability**: Cached data can still be shared across distributed environments, essential for load-balanced applications. +* **Automatic Synchronization**: Changes in distributed cache automatically update the in-memory cache, ensuring data consistency. + +## Using HybridCache with ABP + +> For more information about the implementation in the ABP side, you can refer to the pull request [here](https://github.com/abpframework/abp/pull/20859). + +ABP's support for **HybridCache** is available starting from version 9.0 through the [`AbpHybridCache`](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/Hybrid/AbpHybridCache.cs) implementation. By leveraging this feature, developers using ABP can implement hybrid caching in a way that aligns with ABP’s modular and extensible architecture. + +To demonstrate how to use **HybridCache** in ABP, let's start with a simple example. + +> You can create an ABP-based application with v9.0+, and then follow the next steps for using hybrid caching in your application. + +### Configuring the `AbpHybridCacheOptions` (Optional) + +First, you can configure the hybrid cache options in your module class as below (it's optional): + +```csharp +using Microsoft.Extensions.Caching.Hybrid; +using Volo.Abp.Caching.Hybrid; + +public class YourModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + //... + + Configure(options => + { + //configuring the global hybrid cache options + options.GlobalHybridCacheEntryOptions = new HybridCacheEntryOptions() + { + Expiration = TimeSpan.FromMinutes(20), + LocalCacheExpiration = TimeSpan.FromMinutes(10) + }; + }); + } +} +``` + +* You can configure the `AbpHybridCacheOptions` to set *keyPrefix* for your cache keys, throw or hide exceptions for the distributed cache (by default *it hides errors*), or configure cache for specific cache item keys and more... +* By setting the `GlobalHybridCacheEntryOptions`, you specify the caching options globally in your application. Thanks to that, you don't need to manually pass the related options whenever you use the `IHybridCache` service. + +### Using the `IHybridCache` Service + +After the configuration, now you can inject the `IHybridCache` and use it to set and retrieve cache values: + +```csharp +using Volo.Abp.Caching.Hybrid; + +public class BookAppService : ApplicationService, IBookAppService +{ + private readonly IHybridCache _hybridCache; + + public BookAppService(IHybridCache hybridCache) + { + _hybridCache = hybridCache; + } + + public async Task GetBookWithPageCountAsync(string name) + { + var cacheKey = "cacheKey:book-" + name; + + // Retrieve data from hybrid cache + return await _hybridCache.GetOrCreateAsync(cacheKey, async () => + { + // Simulating getting and returning the data if not exist in the cache + return new BookCacheItem + { + Name = name, + PageCount = 100 + }; + }); + } +} + +public class BookCacheItem +{ + public string Name { get; set; } + + public int PageCount { get; set; } +} +``` + +* You can use the `IHybridCache` or `IHybridCache` service to leverage the hybrid caching. If you use `IHybridCache`as the service, then you should pass the cache key as *string* like in the example above. +* In this example, you used the `GetOrCreateAsync` method, which first tries to get the cache item with the provided cache key, if there is no cache with the specified key, then it runs the factory method and add the returned data to the cache. +* Alternatively, you can use the `SetAsync` method to set the cache item. + +### Debugging the `IHybridCache` Service (deep-dive) + +When you debug the `IHybridCache` service, you'll notice the L1 and L2 cache stores. (L1 is in-memory cache store and L2 is the distributed cache store): + +![](debug-hybrid-cache.png) + +As you can see from the figure, it only set the cache item to the **LocalCache** (`MemoryCache`) and did not set the **BackendCache** (`DistributedCache`) because I did not configure the distributed cache and not running my application in multiple instances. But as you can notice, even without an `IDistributedCache` configuration, the `HybridCache` service will still provide in-process caching. + +**Note:** If you configure distributed caching options, `HybridCache` service uses the distributed cache and sets the **BackendCache**. + +## Conclusion + +The **HybridCache** library in .NET 9 provides a powerful tool for applications needing both high-speed caching and consistency in distributed environments. + +With ABP Framework’s `AbpHybridCache` support, integrating this feature into an ABP-based application becomes straightforward. This setup helps ensure that cached data remains synchronized across instances, bringing a new level of flexibility to caching in .NET 9 applications. + +> For more information, you can refer to the [Microsoft's official document](https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-9.0#new-hybridcache-library). + +## References + +- https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-9.0#new-hybridcache-library +- https://www.youtube.com/watch?v=TDyZc11cJfA +- https://github.com/abpframework/abp/pull/20803 +- https://github.com/abpframework/abp/pull/20859 diff --git a/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/cover-image.png b/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/cover-image.png new file mode 100644 index 0000000000..3494a01265 Binary files /dev/null and b/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/cover-image.png differ diff --git a/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/debug-hybrid-cache.png b/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/debug-hybrid-cache.png new file mode 100644 index 0000000000..3f8c8e0b1c Binary files /dev/null and b/docs/en/Community-Articles/2024-11-01-Hybrid-Cache-Net-9/debug-hybrid-cache.png differ diff --git a/docs/en/Community-Articles/2024-11-04-EF Core 9 Read-only-Primitive-Collections/POST.md b/docs/en/Community-Articles/2024-11-04-EF Core 9 Read-only-Primitive-Collections/POST.md new file mode 100644 index 0000000000..94d2e7fa4a --- /dev/null +++ b/docs/en/Community-Articles/2024-11-04-EF Core 9 Read-only-Primitive-Collections/POST.md @@ -0,0 +1,86 @@ +# EF Core 9 Read-only Primitive Collections + +In this article, we will explore the new features introduced in EF Core 9, specifically focusing on Read-only Primitive Collections. EF Core 8 introduced support for mapping arrays and mutable lists of primitive types, and you can read more about it [here](https://abp.io/community/articles/ef-core-8-primitive-collections-ttn5b6xp). This has been expanded in EF Core 9 to include read-only collections/lists. Specifically, EF Core 9 supports collections typed as `IReadOnlyList`, `IReadOnlyCollection`, or `ReadOnlyCollection`. + +## Introduction to EF Core 9 Read-only Primitive Collections + +Entity Framework Core 9 introduces several enhancements, one of which is the support for Read-only Primitive Collections. This feature aims to provide better support for scenarios where collections of primitive types, such as `int`, `string`, or `bool`, need to be used in a read-only manner in your entity classes. Previously, developers had to use complex workarounds to ensure collections couldn't be modified, but EF Core 9 now provides a simpler, built-in solution to handle this more effectively. + +### Why Read-only Primitive Collections Matter + +Read-only Primitive Collections are particularly useful when you need to guarantee the integrity of certain data within your entities. For example, imagine you have a `Car` entity that has a collection of `Colors`, represented as a set of enums. You might not want these colors to be modified after they're initially set, ensuring that any business logic reliant on these values remains consistent. + +EF Core 9 introduces a convenient way to define these collections as read-only, helping developers maintain stricter control over their data. + +### How It Works + +Defining a read-only primitive collection is quite straightforward in EF Core 9. You can use the `IReadOnlyList`, `IReadOnlyCollection`, or `ReadOnlyCollection` types to declare your properties, ensuring a consistent read-only behavior. This helps maintain data integrity by preventing modifications after the collection is set. Below is an example that includes a `Car` class and a `Color` enum. The `Car` class has a `Colors` property that holds a read-only list of available colors, ensuring that these values cannot be modified after being initially set: + +```csharp +public enum Color +{ + Black, + White, + Red, + Blue +} + +public class Car +{ + public int Id { get; set; } + public string Brand { get; set; } + public string Model { get; set; } + public IReadOnlyList Colors { get; private set; } = new List { Color.Black, Color.White }.AsReadOnly(); + + protected Car() + { + /* This constructor is for deserialization / ORM purpose */ + } + + public Car(string brand, string model, IEnumerable colors) + { + Brand = brand; + Model = model; + Colors = colors.ToList().AsReadOnly(); + } +} +``` + +In the example above, `Colors` is defined as a read-only list, preventing any accidental modifications once it is set. This ensures that data integrity is maintained without the need for manual validation. + +To query cars with specific colors, you can use the following example: + +```csharp +var colors = new List { Color.Black, Color.White }; +var cars = await context.Cars + .Where(c => c.Colors.Intersect(colors).Any()) + .ToListAsync(); +``` + +The query selects all cars that have any of the specified colors in their `Colors` collection. + +The SQL result looks like this; as you can see, it sends colors as parameters instead of adding them inline. It also uses the `json_each` function to deserialize on the database side: + +```sql +SELECT "c"."id", + "c"."brand", + "c"."colors", + "c"."model" +FROM "cars" AS "c" +WHERE EXISTS (SELECT 1 + FROM (SELECT "c0"."value" + FROM Json_each("c"."colors") AS "c0" + INTERSECT + SELECT "c1"."value" + FROM Json_each(@__colors_0) AS "c1") AS "i") +``` + +### Conclusion + +Read-only primitive collections make it easier to enforce data integrity by preventing changes to your collection data. This feature helps simplify your code while ensuring that critical parts of your data remain consistent. + +## References + +- https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/whatsnew#read-only-primitive-collections +- https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/whatsnew#primitive-collections +- https://abp.io/community/articles/ef-core-8-primitive-collections-ttn5b6xp diff --git a/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/Post.md b/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/Post.md new file mode 100644 index 0000000000..174aca756d --- /dev/null +++ b/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/Post.md @@ -0,0 +1,54 @@ +# .NET Aspire 9.0 Features + +.NET Aspire 9.0 is the next major release, supporting both .NET 8 and .NET 9. This version includes new features and improvements. + +## Upgrade to .NET Aspire + +Now, you don't need workloads to develop .NET Aspire applications. In your project, you can add an SDK reference to `Aspire.AppHost.Sdk`. +For more information, you can check out [https://learn.microsoft.com/en-us/dotnet/aspire/whats-new/dotnet-aspire-9?tabs=windows#upgrade-to-net-aspire-9](https://learn.microsoft.com/en-us/dotnet/aspire/whats-new/dotnet-aspire-9?tabs=windows#upgrade-to-net-aspire-9) which explains upgrading an existing project in details. + +## Dashboard + +.NET Aspire offers a nice dashboard for developers to observe the performance and behavior of their applications. In this version, there are some enhancements; + +* **Manage resource lifecycle**: You can stop, start, and restart resources. +* **Mobile and responsive support**: The .NET Aspire dashboard is now mobile-friendly. +* **Sensitive properties**: Properties can be marked as sensitive, automatically masking them in the dashboard UI. +* **Volumes**: Configured container volumes are listed in resource details. +* **Health checks**: .NET Aspire 9 adds support for health checks. + +![Resource Lifecycle](./aspire_resource_lifecycle.jpg) + +## Telemetry + +.NET Aspire 9 comes with many new features to the Telemetry service. + +* **Improve telemetry filtering**: Telemetry data can now be filtered by attribute values. +* **Combine telemetry from multiple resources**: If a resource has multiple replicas, you can now filter telemetry data to view from all instances. +* **Browser telemetry support**: The dashboard now supports OpenTelemetry Protocol (OTLP) over HTTP and cross-origin resource sharing (CORS). + +![Telemetry Filtering](./aspire_trace_filter.jpg) + +## Orchestration + +The .NET App Host is a core component of the .NET runtime that helps launch and execute .NET applications. +.NET Aspire 9 introduces many new features to the app host. Let's take a look; + +* **Waiting for dependencies**: You can configure a resource to wait for another resource to start before starting. +* **Resource health checks**: The `Waiting for dependencies` feature uses health checks to determine if a resource is ready. + +## Integrations + +.NET Aspire has integrations with some services and tools that make it easy to get started. New integrations are coming with .NET Aspire 9. + +* Redis Insight +* OpenAI (Preview) +* MongoDB +* Azure + +For Azure part, it is better to check the official documentation here [https://learn.microsoft.com/en-us/dotnet/aspire/whats-new/dotnet-aspire-9-release-candidate-1?tabs=windows&pivots=visual-studio#azure](https://learn.microsoft.com/en-us/dotnet/aspire/whats-new/dotnet-aspire-9-release-candidate-1?tabs=windows&pivots=visual-studio#azure) because it has a very detailed explanation. + +## ABP Studio + +.NET Aspire and [ABP Studio](https://abp.io/studio) are tools for different purposes with different scopes, and they have different approaches to solving problems; many developers may still be confused since they also have some similar functionalities and solve some common problems. You can check the comparison of .NET Aspire and ABP Studio in this [article](https://abp.io/community/articles/.net-aspire-vs-abp-studio-side-by-side-t1c73d1l). + diff --git a/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/aspire_resource_lifecycle.jpg b/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/aspire_resource_lifecycle.jpg new file mode 100644 index 0000000000..011a705beb Binary files /dev/null and b/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/aspire_resource_lifecycle.jpg differ diff --git a/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/aspire_trace_filter.jpg b/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/aspire_trace_filter.jpg new file mode 100644 index 0000000000..f7563e632b Binary files /dev/null and b/docs/en/Community-Articles/2024-11-05-.NET Aspire 9.0 Features/aspire_trace_filter.jpg differ diff --git a/docs/en/Community-Articles/2024-11-05-SignalR-supports-trimming-and-Native-AOT/POST.md b/docs/en/Community-Articles/2024-11-05-SignalR-supports-trimming-and-Native-AOT/POST.md new file mode 100644 index 0000000000..c43c30d268 --- /dev/null +++ b/docs/en/Community-Articles/2024-11-05-SignalR-supports-trimming-and-Native-AOT/POST.md @@ -0,0 +1,113 @@ +# SignalR supports trimming and Native AOT + +## What is SignalR? + +SignalR is a library that allows you to add real-time web functionality to your applications. It provides a simple API for creating server-to-client remote procedure calls (RPC) that can be called from the server and client. Now SignalR supports trimming and Native AOT in .NET 8.0 and .NET 9.0. You can learn more about [SignalR new features](https://abp.io/community/articles/asp.net-core-signalr-new-features-summary-kcydtdgq) in this article. + +## What is trimming and Native AOT? + +AOT (Ahead-of-Time) compilation is a feature that allows you to compile your application into native code before running it. This can help improve performance and reduce startup times. Trimming is a feature that allows you to remove unused code from your application, reducing its size and improving performance. You can learn more about [Native AOT Compilation](https://abp.io/community/articles/native-aot-compilation-in-.net-8-oq7qtwov) in this article. + +## How to use SignalR with trimming and Native AOT? + +You can create ASP.NET Core AOT application with using the following command: + +```bash +dotnet new webapiaot -n Acme.Sample +``` + +The created application uses `CreateSlimBuilder` method to create minimal builder for the application. You can use `CreateBuilder` method to create a builder with all the services registered. However, deploying an application with `CreateSlimBuilder` method is more convenient because it reduces the size of the application. You can learn more about [CreateSlimBuilder vs CreateBuilder](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/native-aot#createslimbuilder-vs-createbuilder). + +Replace the `Program.cs` file with the following code: + +```csharp +using Microsoft.AspNetCore.SignalR; +using System.Text.Json.Serialization; + +var builder = WebApplication.CreateSlimBuilder(args); + +builder.Services.AddSignalR(); +builder.Services.Configure(o => +{ + o.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default); +}); + +var app = builder.Build(); + +app.MapHub("/chatHub"); +app.MapGet("/", () => Results.Content(""" + + + + SignalR Chat + + + + + +
    + + + + + +""", "text/html")); + +app.Run(); + +[JsonSerializable(typeof(string))] +internal partial class AppJsonSerializerContext : JsonSerializerContext { } + +public class ChatHub : Hub +{ + public async Task SendMessage(string user, string message) + { + await Clients.All.SendAsync("ReceiveMessage", user, message); + } +} +``` + +It is a simple chat application that uses SignalR to send and receive messages. + +![chat](chat.png) + +Before deploying the application, ensure that **Desktop development with C++** is installed on your machine if you're using Windows OS. For more details, you can check the [pre-requisites](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot#prerequisites). + +You can deploy the application with the following command: + +```bash +dotnet publish -c Release +``` + +### Limitations + +Since we are using Native AOT, there are some limitations that you should be aware of: + +- **Only the JSON protocol is supported**: For the payload serialization in SignalR, only the JSON protocol is supported. You need to configure the `JsonHubProtocolOptions` to use the `AppJsonSerializerContext` for serialization/deserialization. +- **Reflection**: Native AOT does not support reflection. You need to use the `JsonSerializable` attribute to specify the types that should be serialized/deserialized. In this example, we have used the `JsonSerializable` attribute for the `string` type in the `AppJsonSerializerContext` class. + +For more details, you can check the [limitations](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot#limitations-of-native-aot-deployment) of Native AOT. + +## Conclusion + +In this article, we learned how to use SignalR with trimming and Native AOT in .NET 8.0 and .NET 9.0. We created a simple chat application that uses SignalR to send and receive messages. We also discussed the limitations of using Native AOT and how to overcome them. + +For more information, you can refer to the [Microsoft's official document](https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-9.0#signalr-supports-trimming-and-native-aot). \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-11-05-SignalR-supports-trimming-and-Native-AOT/chat.png b/docs/en/Community-Articles/2024-11-05-SignalR-supports-trimming-and-Native-AOT/chat.png new file mode 100644 index 0000000000..d6dff70d6d Binary files /dev/null and b/docs/en/Community-Articles/2024-11-05-SignalR-supports-trimming-and-Native-AOT/chat.png differ diff --git a/docs/en/Community-Articles/2024-11-06-Keyed-DI-in-Middlewares-Net-9/post.md b/docs/en/Community-Articles/2024-11-06-Keyed-DI-in-Middlewares-Net-9/post.md new file mode 100644 index 0000000000..4cb6992d0d --- /dev/null +++ b/docs/en/Community-Articles/2024-11-06-Keyed-DI-in-Middlewares-Net-9/post.md @@ -0,0 +1,58 @@ +# Middleware Now Supports Keyed Dependency Injection in .NET 9 + +This article explores a new feature in .NET 9 that enables keyed dependency injection in middleware. Previously, .NET 8 introduced keyed services, which allowed developers to register multiple instances of the same service type with distinct keys. Now, .NET 9 extends this feature to middleware, making it easier to inject specific services within the middleware based on defined keys. For more details, see this [overview on the .NET blog](https://github.com/dotnet/core/blob/main/release-notes/9.0/preview/rc1/aspnetcore.md#keyed-di-in-middleware). + +## What is Keyed Dependency Injection? + +Keyed dependency injection is a technique for registering multiple service versions with unique identifiers, or “keys.” This approach is especially helpful when multiple implementations of the same service are required in different contexts. For example, you may have various logging services but want to inject a specific logger based on the application’s current needs. By using keys, developers can ensure that the appropriate service version is injected precisely where it’s needed. + +## Using Keyed Dependency Injection in Middleware + +In .NET 9, developers can now use keyed dependency injection directly in middleware. Keyed services can be injected through the middleware constructor or via the `Invoke`/`InvokeAsync` methods, allowing for straightforward and flexible control of service instances in middleware components. Here’s an example of how to configure and use keyed dependency injection in middleware: + +```csharp +var builder = WebApplication.CreateBuilder(args); + +// Register services with unique keys +builder.Services.AddKeyedSingleton("test"); +builder.Services.AddKeyedScoped("test2"); + +var app = builder.Build(); +app.UseMiddleware(); +app.Run(); + +internal class MyMiddleware +{ + private readonly RequestDelegate _next; + private readonly MySingletonClass _singletonService; + + // Constructor injection with key + public MyMiddleware(RequestDelegate next, [FromKeyedServices("test")] MySingletonClass singletonService) + { + _next = next; + _singletonService = singletonService; + } + + // Invoke method with additional scoped service injection using key + public Task Invoke(HttpContext context, [FromKeyedServices("test2")] MyScopedClass scopedService) + { + // Middleware logic here + return _next(context); + } +} +``` + +In this example: +- `MySingletonClass` and `MyScopedClass` are registered with unique keys (`"test"` and `"test2"`). +- These services are injected into the middleware through both the constructor and `Invoke` method, based on their respective keys. + +This approach allows developers to manage which service instances are available within middleware precisely. + +## Conclusion + +Keyed dependency injection in middleware is a significant addition in .NET 9. It provides developers with more control over which services are injected based on specific keys. This enhancement enables selective service injection in middleware scenarios, allowing for more modular and maintainable applications. + +## References + +- [.NET 9 Release Notes](https://github.com/dotnet/core/blob/main/release-notes/9.0/preview/rc1/aspnetcore.md#keyed-di-in-middleware) +- [Dependency Injection and Keyed Services](https://learn.microsoft.com/aspnet/core/fundamentals/dependency-injection#keyed-services) \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-11-06-Optimize-static-web-asset-delivery/POST.md b/docs/en/Community-Articles/2024-11-06-Optimize-static-web-asset-delivery/POST.md new file mode 100644 index 0000000000..67c4762952 --- /dev/null +++ b/docs/en/Community-Articles/2024-11-06-Optimize-static-web-asset-delivery/POST.md @@ -0,0 +1,108 @@ +# Optimizing Static Asset Delivery feature in ASP.NET Core 9.0 + +Delivering static assets efficiently is a key factor in building performant web applications. By optimizing how assets like CSS, JavaScript, and images are served to the browser, you can reduce load times, decrease network traffic, and improve the overall user experience. + +One powerful tool to help achieve this is **MapStaticAssets**, a feature in ASP.NET Core that significantly optimizes the delivery of static resources. Whether you're working with Blazor, Razor Pages, MVC, or other UI frameworks, **MapStaticAssets** streamlines asset management and ensures that your web app delivers resources in the most efficient way possible. + +## Why Optimizing Static Assets Matters + +Serving static assets without optimization can lead to several performance bottlenecks: + +- **Excessive network requests**: The browser may need to request the same resources multiple times, even if they haven’t changed. +- **Unnecessary data transfer**: Larger files are sent over the network, consuming bandwidth and slowing down page loads. +- **Outdated assets**: Without proper cache management, users may receive stale versions of files after an app update. + +Optimizing static assets involves compressing files, managing caching headers, and ensuring that only the necessary resources are sent to the client. **MapStaticAssets** takes care of all these issues in a seamless, automated way. + +## What is MapStaticAssets? + +**MapStaticAssets** is designed to enhance the default static asset serving mechanism in ASP.NET Core. It can replace `UseStaticFiles` in most scenarios and comes with several built-in optimizations. These optimizations are executed at both build and publish time, ensuring that static resources are served in the most efficient way possible when your app is running. + +Here's how you can implement **MapStaticAssets** in your app: + +```csharp +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddRazorPages(); + +var app = builder.Build(); + +if (!app.Environment.IsDevelopment()) +{ + app.UseExceptionHandler("/Error"); + app.UseHsts(); +} + +app.UseHttpsRedirection(); + +app.UseRouting(); + +app.UseAuthorization(); + +// Replacing UseStaticFiles with MapStaticAssets +app.MapStaticAssets(); +app.MapRazorPages(); + +app.Run(); +``` + +## Key Features of MapStaticAssets + +1. **Build-time Compression**: + **MapStaticAssets** automatically compresses all static assets during the build process. It uses **gzip** compression during development and **gzip + brotli** compression when publishing. This reduces the file size significantly, ensuring faster download times. + + For example, in a default Razor Pages template, assets like `bootstrap.min.css` and `jquery.js` are compressed by over 80%, resulting in significantly reduced file sizes: + + | File | Original Size | Compressed Size | Compression Reduction | + |----------------------|---------------|-----------------|-----------------------| + | `bootstrap.min.css` | 163 KB | 17.5 KB | 89.26% | + | `jquery.js` | 89.6 KB | 28 KB | 68.75% | + | `bootstrap.min.js` | 78.5 KB | 20 KB | 74.52% | + | **Total** | 331.1 KB | 65.5 KB | 80.20% | + +2. **Content-based ETags**: + **MapStaticAssets** generates **ETags** based on the SHA-256 hash of the file content, encoded in Base64. This ensures that the browser only re-downloads a resource if its content has changed. This eliminates unnecessary network requests, improving page load speeds. + +3. **Smaller File Sizes for Libraries**: + Popular component libraries, such as **Fluent UI Blazor** and **MudBlazor**, benefit from similar compression optimizations. For example, the size of the **MudBlazor** library is reduced by over 90%, from 588 KB to just 46.7 KB after compression. + + | File | Original Size | Compressed Size | Compression Reduction | + |----------------------|---------------|-----------------|-----------------------| + | `MudBlazor.min.css` | 541 KB | 37.5 KB | 93.07% | + | `MudBlazor.min.js` | 47.4 KB | 9.2 KB | 80.59% | + | **Total** | 588.4 KB | 46.7 KB | 92.07% | + +4. **Automatic Optimization**: + As libraries or components are added or updated, **MapStaticAssets** automatically optimizes the assets as part of the build process. This includes minimizing the size of JavaScript and CSS files, reducing the impact of mobile or low-bandwidth environments. + +5. **Serving Assets with a CDN**: + Although **MapStaticAssets** is focused on server-side optimizations, integrating a **CDN (Content Delivery Network)** can further boost performance by serving static assets from servers geographically closer to the user, reducing latency. + +## Comparing MapStaticAssets to IIS Dynamic Compression + +**MapStaticAssets** provides several advantages over traditional dynamic compression techniques, such as IIS **gzip** compression: + +- **Simplicity**: There is no need for server-specific configuration, making **MapStaticAssets** easy to implement. +- **Performance**: By compressing assets at build time, the app doesn't need to perform compression during every request, which improves server performance. +- **Optimization**: Developers can focus on ensuring that assets are compressed to the smallest possible size during the build process. + +For example, using **MapStaticAssets**, a file like `MudBlazor.min.css` is compressed down to 37.5 KB, whereas IIS dynamic compression might result in a size of 90 KB. This represents a **59%** reduction in size. + +## About MapAbpStaticAssets + +The ABP framework is 100% compatible with this new feature. + +However, some JavaScript, CSS, and image files exist in the [Virtual File System](https://abp.io/docs/latest/framework/infrastructure/virtual-file-system), which ASP.NET Core's **MapStaticAssets** can't handle. For these files, additional **StaticFileMiddleware** is needed to serve them, which is where **MapAbpStaticAssets** comes in. + +**MapAbpStaticAssets** adds the necessary **StaticFileMiddleware** to ensure that virtual files are correctly served. This middleware setup ensures seamless delivery of virtual resources alongside static assets. + +You can view the source code of **MapAbpStaticAssets** on [GitHub](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs#L129-L198). + +## Conclusion + +Optimizing static asset delivery is essential for building fast, efficient web applications. **MapStaticAssets** simplifies and automates the optimization of static files by providing build-time compression, caching headers, and content-based ETags. This ensures that your app's static assets are always delivered in the most efficient way, whether users are on fast broadband or slower mobile connections. By using **MapStaticAssets**, you can deliver a faster, more reliable experience for your users with minimal effort. + +## References + +* [Static files in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-9.0) +* [What's new in ASP.NET Core 9.0](https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0#optimize-static-web-asset-delivery) diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/cover.png b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/cover.png new file mode 100644 index 0000000000..4ac79513c3 Binary files /dev/null and b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/cover.png differ diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img1.png b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img1.png new file mode 100644 index 0000000000..e47683afd8 Binary files /dev/null and b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img1.png differ diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img2.png b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img2.png new file mode 100644 index 0000000000..a89415db1d Binary files /dev/null and b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img2.png differ diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img3.png b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img3.png new file mode 100644 index 0000000000..8698b153ab Binary files /dev/null and b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img3.png differ diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img4.png b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img4.png new file mode 100644 index 0000000000..30e539ffb2 Binary files /dev/null and b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img4.png differ diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img5.png b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img5.png new file mode 100644 index 0000000000..5b5c1a9b7d Binary files /dev/null and b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img5.png differ diff --git a/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/post.md b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/post.md new file mode 100644 index 0000000000..3e950c38c0 --- /dev/null +++ b/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/post.md @@ -0,0 +1,164 @@ +Built-in OpenAPI Document Generation with .NET 9 — No more SwaggerUI! 👋 +======================================================================== + +![Cover](cover.png) + +What’s Swagger UI? +------------------ + +[Swagger UI](https://swagger.io/) is an open-source tool that automatically generates an interactive, web-based documentation interface for WebAPIs. +It supports OpenAPI standards. It was very popular tool among the ASP.NET Core developers from 2020 to 2024. +Because it was a built-in tool comes with ASP.NET Core default templates. +We liked this tool because it was the first tool that allows us to make WebAPI calls for testing. +Now it provides paid services as well as free ones. + +> Previously, Swagger was included by default from **.NET 5** to **.NET 8** in .NET web templates. + +--- + + + +What’s OpenAPI? +--------------- + +OpenAPI is a standard specification for defining REST APIs. +The official website is [https://www.openapis.org/](https://www.openapis.org/). +Microsoft is now using OpenAPI and here is the official documentation 👉 [https://aka.ms/aspnet/openapi](https://aka.ms/aspnet/openapi) + +--- + + + + + +Replacement of Swagger UI with OpenAPI +---------------------------------------------------------------------------- + +Swagger UI is no longer integrated into NET 9, as Microsoft wants a solution with first-class support, better control, and enhanced security. As you see in the below screenshot, Microsoft declares that it's already removed. + +![Docs](img2.png) + +--- + + + + + +## Why is Swagger Removed from .NET 9? + +In March 2024, the ASP.NET Core team announced that they are removing the `Swashbuckle.AspNetCore` dependency from web templates from .NET 9 release. + + + +> This decision was influenced by the project's lack of active maintenance and the absence of an official release for .NET 8. + + + +Microsoft team created a new package `Microsoft.AspNetCore.OpenApi`. It provides built-in OpenAPI document generation just like Swagger. So Microsoft doesn't depend on external tools. Because in every .NET release, they need to ask the owners of the external tool libraries to align with their new version. And sometimes these library owners cannot update their code-base according to the recent .NET changes. And it is becoming harder for Microsoft to support the 3rd party libraries under these circumstances. Basically reducing 3rd party dependencies will help Microsoft fast release cycles. + +I read Reddit, GitHub discussions and YouTube reviews about this topic. As I see community members expressed concerns about the inactivity of Swashbuckle and they are discussing alternatives like contributing to or forking the project. The Microsoft team also contacted the owners of Swashbuckle and NSwag to explore potential collaborations and ensure a smooth transition for developers. + +In the below GitHub issue, you can see the details of this decision: + +* [github.com/dotnet/aspnetcore/issues/54599](https://github.com/dotnet/aspnetcore/issues/54599) + + + +**Jeremy** -Product Manager- at Microsoft, answers why they took this decision in [this post](https://github.com/dotnet/aspnetcore/issues/54599#issuecomment-2004975574). + +![Jeremy Comments](img3.png) + +As a summary; + +**The change is due to a lack of maintenance of the Swagger library**, although it has seen some recent updates. This aims to reduce dependency on external tools and provide a streamlined, out-of-the-box experience for generating OpenAPI documentation for ASP.NET Core Web APIs. + +--- + + + + + +What are the Benefits of the New OpenAI Package? +--------------------------------------------------------------- + +### Native Support and Reduced Dependency + +The new `Microsoft.AspNetCore.OpenApi` package provides first-class citizen support for OpenAPI. It reduces reliance on external tools like Swashbuckle or NSwag for basic documentation needs. The native implementation leverages source generators to reduce runtime overhead. + +### Simplified Configuration + +No need extra setup or 3rd party integrations. Just by defining controllers and endpoints, ASP.NET Core automatically generates OpenAPI specifications. + +### Well Integration with Minimal APIs + +[Minimal APIs](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis) introduced in .NET 6. There's an optimized built-in support for Minimal APIs. It automatically adds metadata for routes, request parameters, and responses. + +### Compatibility with Existing Tools + +You can still use the output of OpenAPI with Swagger or NSwag... So it doesn't mean that in this case you have only one option when you use OpenAPI. + +--- + + + +How to Use the New OpenAPI in .NET9? +------------------------------------ + +When you create a new ASP.NET Core project, you can see the below checkbox to add OpenAPI. + +![New .NET 9 Project Screen](img5.png) + +I created a new .NET 9 web project, I saw that OpenAPI had already been added. + +![Package Reference](img4.png) + +## Add OpenAPI Support For Your Existing Project + +Upgrade your project to .NET 9 and add the required NuGet package [Microsoft.AspNetCore.OpenApi](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) + +``` +dotnet add package Microsoft.AspNetCore.OpenApi +``` + +### + +Add the following services and middleware in `Program.cs` + +``` +var builder = WebApplication.CreateBuilder(); +builder.Services.AddOpenApi(); //<<----- +var app = builder.Build(); +app.MapOpenApi(); //<<----- +app.MapGet("/", () => "Test"); +app.Run(); +``` + +Your OpenAPI document URL is [_https://localhost:7077/openapi/v1.json_](https://localhost:7077/openapi/v1.json) + +Change the port to your active port. This is how it looks like: + +![Web UI of the Documentation](img1.png) + +--- + + + +Alternative 3rd Party Tool: Scalar +================================== + +**Scalar** is an open-source API platform for RestAPI documentation. Also, it provides an interface for interacting with RESTful API. Generates interactive and user-friendly API documentation. Supports OpenAPI and Swagger specifications. It’s open-source with **7K stars** on GitHub. + +See the repo 👉 [https://github.com/scalar/scalar](https://github.com/scalar/scalar). + + + +That's all from the replacement of Swagger in .NET 9. +Happy coding 👨‍💻 + + + +**References** + +* [https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0#openapi](https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0#openapi) + + diff --git a/docs/en/Community-Articles/2024-11-14-Csharp-13-Features/Post.md b/docs/en/Community-Articles/2024-11-14-Csharp-13-Features/Post.md new file mode 100644 index 0000000000..12a1dea431 --- /dev/null +++ b/docs/en/Community-Articles/2024-11-14-Csharp-13-Features/Post.md @@ -0,0 +1,202 @@ +# C# 13 Features + +C# 13 is the latest version of C# and it comes with a lot of new features. In this article, we will discuss some of the new features of C# 13. + +## `params` collections + +With the C# 13, method parameter with `params` keyword isn't limited to be an array. You can now use any collection type that implements `IEnumerable` interface. + +Let's see how it can help us in our code. + +```csharp +public IEnumerable GetOdds(params IEnumerable numbers) +{ + foreach (var number in numbers) + { + if (number % 2 != 0) + { + Console.WriteLine(number); + } + } +} +``` + +## New lock object + +I'm sure you have used `lock` statement in your code to synchronize access to a shared resource. With C# 13, you can now use a new lock object that is more efficient than the traditional lock object. +The new `Lock` type provides better thread synchronization through its API. When `Lock.EnterScope()` method is called, it returns a struct named `Scope` that contains a `Dispose` method. The `Dispose` method is called when the `Scope` object goes out of scope, which releases the lock. C# `using` statement recognizes the `Dispose` method and calls it automatically like it does with other `IDisposable` objects. + +It was something similar before: +```csharp +private object _lock = new(); + +public void DoSomething() +{ + lock (_lock) + { + // Do something + } +} +``` + +Now, you can use the new lock object like this: +```csharp +System.Threading.Lock x = new System.Threading.Lock(); +public void DoSomething() +{ + using (x.EnterScope()) + { + // Do something + } +} +``` + +## New escape sequence +In C# 13, a new escape sequence `\e` has been introduced to represent the `ESCAPE` character, Unicode `U+001B`. Previously, you had to use `\u001b` or `\x1b` to represent this character. The new `\e` escape sequence simplifies this process and avoids potential issues with hexadecimal digits following `\x1b`. + +> You can check [here](https://en.wikipedia.org/wiki/ANSI_escape_code#C0_control_codes) for ANSI escape codes. + +## Implicit index access + +The implicit "from the end" index operator, `^`, is now allowed in an object initializer expression. + +It was not possible before, but now you can do this: + +```csharp +var countdown = new TimerRemaining() +{ + buffer = + { + [^1] = 0, + [^2] = 1, + [^3] = 2, + [^4] = 3, + [^5] = 4, + [^6] = 5, + [^7] = 6, + [^8] = 7, + [^9] = 8, + [^10] = 9 + } +}; +``` + +It's a great feature that makes the code more readable and maintainable. Still not a big deal, but it's nice to have it. + +## `ref` and `unsafe` in iterators and async methods + +In C# 13, the restrictions on using `ref` and `unsafe` constructs in iterators and async methods have been relaxed. Previously, you couldn't declare local `ref` variables or use unsafe contexts in these methods. Now, you can declare ref local variables and use unsafe contexts in async methods and iterators, provided they are not accessed across `await` or `yield` boundaries + + +This change allows for more expressive and efficient code, especially when working with types like `System.Span` and `System.ReadOnlySpan`. The compiler ensures that these constructs are used safely, and it will notify you if any safety rules are violated. + +You can read more about this feature on the [Microsoft Learn page](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-13.0/ref-unsafe-in-iterators-async). + + + +## More partial members + +In C# 13, the concept of partial members has been expanded to include partial properties and partial indexers. Previously, only methods could be defined as partial members. This means you can now split the definition of properties and indexers across multiple files, just like you could with methods. + +For example, you can declare a partial property in one part of your class and implement it in another part. Here's a simple illustration: + +```csharp +public partial class MyClass +{ + // Declaring declaration + public partial string MyProperty { get; set; } +} + +public partial class MyClass +{ + // Implementing declaration + private string _myProperty; + public partial string MyProperty + { + get => _myProperty; + set => _myProperty = value; + } +} +``` + +This feature allows for better organization and modularization of your code, especially in large projects where different parts of a class might be implemented by different team members. + +## Overload resolution priority + +What does "Overload resolution priority" section mean in this page? +In C# 13, the OverloadResolutionPriority attribute allows library authors to specify which method overload should be preferred by the compiler when multiple overloads are available. This attribute helps avoid ambiguity and ensures that the most appropriate overload is chosen, even if it might not be the most obvious choice based on traditional overload resolution rules. + +This may be useful in scenarios where you have multiple overloads that are equally valid, but you want to prioritize one over the others. The attribute can be applied to a method or constructor to indicate its priority in the overload resolution process. It can prevent unexpected behavior and make your code more predictable and maintainable. + + +Let me show with an example: +```csharp +public class Example +{ + // Existing method + public void Display(string message = "Hello!") + { + Console.WriteLine("Message: " + message); + } + + // New, more efficient method with higher priority + [OverloadResolutionPriority(1)] + public void Display(string message = "Hello!", int repeatCount = 3) + { + for (int i = 0; i < repeatCount; i++) + { + Console.WriteLine("Message: " + message); + } + } +} + +class Program +{ + static void Main() + { + Example example = new Example(); + + // Normally, you can't compile this code because of ambiguity: + example.Display(); + } +} +``` + +Output: +``` +Message: Hello! +Message: Hello! +Message: Hello! +``` + +## The `field` keyword + +n C# 13, the `field` keyword is introduced as a preview feature to simplify property accessors. This keyword allows you to reference the compiler-generated backing `field` directly within a property accessor, eliminating the need to declare an explicit backing `field` in your type declaration. + +For example, instead of writing: + +```csharp +private int _value; +public int Value +{ + get => _value; + set => _value = value; +} +``` + +You can now write: + +```csharp +public int Value +{ + get => field; + set => field = value; +} +``` + +This makes your code cleaner and more concise. However, be cautious if you have a `field` named `field` in your class, as it could cause confusion. You can disambiguate by using `@field` or `this.field`. + +Make sure you're using the latest `LangVersion` in your `.csproj` project file to enable this feature. +```xml +preview +``` \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-11-14-EF-Core-9-Linq-SQL-Translation/POST.md b/docs/en/Community-Articles/2024-11-14-EF-Core-9-Linq-SQL-Translation/POST.md new file mode 100644 index 0000000000..2e91d30e7f --- /dev/null +++ b/docs/en/Community-Articles/2024-11-14-EF-Core-9-Linq-SQL-Translation/POST.md @@ -0,0 +1,165 @@ +# EF Core 9 LINQ & SQL translation + +EF Core improves the translation of LINQ queries to SQL with every release. EF Core 9 is no exception. This article will show you some of the improvements in EF Core 9. + +EF Core 9 includes a lot of improvements in LINQ to SQL translation. we don't cover all of them in this article. You can find more information in the [official release notes](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/whatsnew#linq-and-sql-translation). + +## Support for complex types + +### GroupBy + +EF Core now supports grouping by complex type instance. For example: + +```csharp +var groupedAddress = await context.Customers + .GroupBy(c => new { c.Address }) + .Select(g => new { g.Key, Count = g.Count() }) + .ToListAsync(); +``` + +Address is a complex type as a value object here. + +### ExecuteUpdate + +EF Core now supports updating a complex type. For example: + +```csharp +var newAddress = new Address("New Street", "New City", "New Country"); + +await context.Customers + .Where(e => e.Region == "Turkey") + .ExecuteUpdateAsync(s => s.SetProperty(b => b.Address, newAddress)); +``` + +EF Core updates each column of the complex type. + +## Prune unneeded elements from SQL + +Ef Core now translates LINQ queries to SQL more efficiently. It will remove unneeded elements from the SQL query and bring better performance. + +### Table pruning + +When you use table-per-hierarchy (TPH) inheritance, previously EF Core generated SQL queries that included JIONs to tables that were not needed. + +For example: + +```csharp +public class Order +{ + public int Id { get; set; } + ... + + public Customer Customer { get; set; } +} + +public class DiscountedOrder : Order +{ + public double Discount { get; set; } +} + +public class Customer +{ + public int Id { get; set; } + ... + + public List Orders { get; set; } +} + +public class AppContext : DbContext +{ + ... + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().UseTptMappingStrategy(); + } +} +``` + +Consider the following query to get all customers with at least one order: + +```csharp +var customers = await context.Customers.Where(o => o.Orders.Any()).ToListAsync(); +``` + +Previously, EF Core generated the following SQL query: + +```sql +SELECT [c].[Id], [c].[Name] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + LEFT JOIN [DiscountedOrders] AS [d] ON [o].[Id] = [d].[Id] + WHERE [c].[Id] = [o].[CustomerId]) +``` + +It included a JOIN to the `DiscountedOrders` table, which was not needed. In EF Core 9, the generated SQL query is: + +```sql +SELECT [c].[Id], [c].[Name] +FROM [Customers] AS [c] +WHERE EXISTS ( + SELECT 1 + FROM [Orders] AS [o] + WHERE [c].[Id] = [o].[CustomerId]) +``` + +## EF Core in ABP + +ABP Framework is built on top of the latest technologies. It will support EF Core 9 as soon as it is released. You can use the latest features of EF Core in your ABP applications. + +For example, you can use the `ExecuteUpdateAsync` method in your ABP application: + +```csharp +public class Book : FullAuditedAggregateRoot +{ + public string Name { get; set; } + + public float Price { get; set; } + + public string Author { get; set; } +} + +public class AppContext : AbpDbContext +{ + public DbSet Books { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(builder); + + builder.Entity(b => + { + b.ToTable("Books"); + b.ConfigureByConvention(); + b.Property(x => x.Name).IsRequired().HasMaxLength(128); + b.Property(x => x.Author).IsRequired().HasMaxLength(64); + }); + } +} + +public class BookRepository : EfCoreRepository, IBookRepository +{ + public BookRepository(IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task UpdatePriceByAuthorAsync(string author, float price) + { + await (await GetDbSetAsync()) + .Where(b => b.Author == author) + .ExecuteUpdateAsync(b => b.SetProperty(x => x.Price, price)); + } +} +``` + +* `FullAuditedAggregateRoot` is an aggregate root base class with auditing properties provided by ABP Framework. +* `IRepository` is a generic repository interface provided by ABP Framework that provides CRUD operations and you can use EF Core's API in your entity repository implementation. + +## References + +* [LINQ and SQL translation](https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/whatsnew#linq-and-sql-translation) +* [ABP Entity Framework Core Integration](https://abp.io/docs/latest/framework/data/entity-framework-core) +* [ABP Entities](https://abp.io/docs/latest/framework/architecture/domain-driven-design/entities) diff --git a/docs/en/cli/index.md b/docs/en/cli/index.md index 2c8a4d894e..9297965bb4 100644 --- a/docs/en/cli/index.md +++ b/docs/en/cli/index.md @@ -913,7 +913,7 @@ abp logout ### bundle -This command generates script and style references for ABP Blazor WebAssembly and MAUI Blazor project and updates the **index.html** file. It helps developers to manage dependencies required by ABP modules easily. In order ```bundle``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain a Blazor or MAUI Blazor project file(*.csproj). +This command generates script and style references for ABP Blazor WebAssembly and MAUI Blazor project and updates the **index.html** file. It helps developers to manage dependencies required by ABP modules easily. In order for ```bundle``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain a Blazor or MAUI Blazor project file(*.csproj). Usage: diff --git a/docs/en/cli/new-command-samples.md b/docs/en/cli/new-command-samples.md index 6b168b538c..a8d469b10b 100644 --- a/docs/en/cli/new-command-samples.md +++ b/docs/en/cli/new-command-samples.md @@ -221,6 +221,79 @@ As seen below, ABP libraries are local project references. ``` +## Using Existing Configuration + +If you want to programmaticaly create solutions, you can use an existing configuration instead of passing parameters to CLI one by one. ABP Studio keeps the solution creation history locally in `(UserProfile)\.abp\studio\solution-creation-history.json` file, there you can find the configurations of the solutions created in your machine. + +### Using a Solution Id + +In `*.abpsln` file of the solutions, there is an ID field that you can use to recreate a solution. To do this, pass the id to cli using `-shi or --solution-history-id` parameters. + +```bash +abp new -shi dbb1afa9-190e-419a-842d-2780bb1bad1f +abp new -shi dbb1afa9-190e-419a-842d-2780bb1bad1f -o D:\test\Acme.BookStore +``` + +### Using a JSON Configuration File + +You can also use a configuration file to create solutions. You need to use `-rcp or ready-config-path` parameters to do that. + +```bash +abp new -rcp MyTests\config.json +abp new -rcp D:\MyTests\config.json +abp new -rcp D:\MyTests\config.json -o D:\test\Acme.BookStore +``` + +To prepare a config file, you can check the records in `solution-creation-history.json` file mentioned above. An example config file would look like that: + +```json +{ + "solutionName": { + "fullName": "Acme.BookStore", + "companyName": "Acme", + "projectName": "BookStore" + }, + "pro": true, + "useOpenSourceTemplate": false, + "booksSample": false, + "databaseProvider": "ef", + "createInitialMigration": true, + "runDbMigrator": true, + "uiFramework": "angular", + "theme": "leptonx", + "themeStyle": "system", + "mobileFramework": "none", + "databaseManagementSystem": "sqlserver", + "databaseManagementSystemBuilderExtensionMethod": "UseSqlServer", + "connectionString": "Server=(LocalDb)\\\\MSSQLLocalDB;Database=BookStore;Trusted_Connection=True;TrustServerCertificate=true", + "mauiBlazorApplicationIdGuid": "d3499a09-f3d4-4bb7-9d58-4c7b1caee331", + "tiered": false, + "publicWebsite": false, + "cmskit": false, + "openIddictAdmin": true, + "languageManagement": true, + "textTemplateManagement": true, + "multiTenancy": true, + "auditLogging": false, + "gdpr": true, + "chat": false, + "fileManagement": false, + "socialLogins": true, + "includeTests": true, + "distributedEventBus": "none", + "publicRedis": false, + "separateTenantSchema": false, + "progressiveWebApp": false, + "runProgressiveWebAppSupport": false, + "runInstallLibs": false, + "runBundling": false, + "kubernetesConfiguration": true, + "templateName": "app" + } +``` + + + ## See Also * [ABP CLI documentation](../cli/index.md) diff --git a/docs/en/deployment/configuring-openIddict.md b/docs/en/deployment/configuring-openIddict.md index 80fa74d898..30b8078098 100644 --- a/docs/en/deployment/configuring-openIddict.md +++ b/docs/en/deployment/configuring-openIddict.md @@ -36,7 +36,7 @@ To avoid that, consider creating self-signed certificates and storing them in th `AddDevelopmentEncryptionAndSigningCertificate` is disabled in production environment. Signing and encryption of certificates is done using `openiddict.pfx` file in production environment. -You can use the `dotnet dev-certs https -v -ep openiddict.pfx -p 00000000-0000-0000-0000-000000000000` command to generate the `authserver.pfx` certificate. +You can use the `dotnet dev-certs https -v -ep openiddict.pfx -p 00000000-0000-0000-0000-000000000000` command to generate the `openiddict.pfx` certificate. > `00000000-0000-0000-0000-000000000000` is the password of the certificate, you can change it to any password you want. diff --git a/docs/en/deployment/forwarded-headers.md b/docs/en/deployment/forwarded-headers.md new file mode 100644 index 0000000000..b6b74205c3 --- /dev/null +++ b/docs/en/deployment/forwarded-headers.md @@ -0,0 +1,84 @@ +# Forwarded Headers + +Reverse proxies and load balancers play a crucial role in modern web application architectures. When an application is deployed behind these proxies and load balancers, several specific issues can arise. This document will discuss these issues in detail, explain how ASP.NET Core's forwarded headers middleware can address them, and provide a code example for configuring forwarded headers in an ABP application. + +## Possible problem in a Reverse Proxy Environment + +When requests pass through a reverse proxy or load balancer, the following common issues can occur: + +### 1. Loss of Original Request Information + +A reverse proxy or load balancer typically modifies the original HTTP request headers. For example, the proxy may replace the client's `X-Forwarded-For` header, or the `Host` header might be set to the proxy's address. This can result in the backend application being unable to directly access the client's IP address, the true hostname, and the protocol used. + +### 2. HTTPS vs HTTP Protocol Confusion + +When a request is forwarded by a proxy server, it is often upgraded to HTTPS to ensure secure transmission. The proxy server will send a header like `X-Forwarded-Proto` to indicate whether the original request was HTTP or HTTPS. If the backend application does not correctly handle this header, it may generate URLs with the wrong protocol. + +### 3. Path Handling Issues + +Since load balancers and proxies might modify or map the request URL paths differently, the backend application could encounter path inconsistencies. For example, a reverse proxy might forward a request from `/api` to `/myapp/api`. If the backend application is not correctly configured, path parsing errors may occur. + +### 4. IP Address and Security + +Reverse proxies might replace the original client IP address with their own, which can affect logging, authentication, and access control mechanisms. To retrieve the actual client IP address, the `X-Forwarded-For` header must be correctly parsed and trusted. + +### 5. Load Balancer Impact + +Load balancers might distribute requests to different backend servers using different algorithms. This can create session affinity problems. If session data is stored on a single server and the load balancer directs subsequent requests to different servers, session loss or inconsistency may occur. + +## Forwarded Headers Middleware in ABP web application + +To resolve the above issues, ASP.NET Core provides a built-in middleware, `ForwardedHeadersMiddleware`, which processes the headers forwarded by reverse proxies. This middleware helps the application recover the correct original request information, such as the client’s IP address, protocol, and host. + +### Configuring `ForwardedHeadersMiddleware` + +ASP.NET Core’s `ForwardedHeadersMiddleware` supports several HTTP headers: + +- **X-Forwarded-For**: Contains the original client’s IP address. +- **X-Forwarded-Proto**: Indicates whether the original request was HTTP or HTTPS. +- **X-Forwarded-Host**: Contains the original host requested by the client. +- **X-Forwarded-Port**: Indicates the original port of the request. + +To configure this middleware: + +1. In the `ConfigureServices` method of your module, configure the `ForwardedHeadersOptions`: + +```csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + context.Services.Configure(options => + { + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + }); +} +``` + +2. In the `OnApplicationInitialization` method of your module, add the middleware: + +> Forwarded Headers Middleware should run before other middleware. This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing. Forwarded Headers Middleware can run after diagnostics and error handling, but it must be run before calling UseHsts: + +```csharp +public override void OnApplicationInitialization(ApplicationInitializationContext context) +{ + var app = context.GetApplicationBuilder(); + var env = context.GetEnvironment(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseForwardedHeaders(); + } + else + { + app.UseErrorPage(); + app.UseForwardedHeaders(); + app.UseHsts(); + } + + // Other middleware configurations... +} +``` + +## References + +- [ASP.NET Core Proxy and Load Balancer Configuration](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-9.0) diff --git a/docs/en/deployment/index.md b/docs/en/deployment/index.md index 3537e4593e..245c8bdaf0 100644 --- a/docs/en/deployment/index.md +++ b/docs/en/deployment/index.md @@ -12,3 +12,4 @@ However, there are some topics that you should care about when you are deploying * [Optimization for Production](./optimizing-production.md): Tips and suggestions for optimizing your application in production environments. * [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. * [Deploying Distributed / Microservice Solutions](./distributed-microservice.md): Deployment notes for solutions consisting of multiple applications and/or services. +* [Forwarded Headers](./forwarded-headers): Explains how to configure the application to trust headers forwarded by reverse proxies and recover the original request information from the `X-Forwarded-For` and `X-Forwarded-Proto` headers. \ No newline at end of file diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index 6992cbc78a..53f1159629 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -156,6 +156,43 @@ } ] }, + { + "text": "Microservice Solution", + "items": [ + { + "text": "Overview", + "path": "tutorials/microservice/index.md" + }, + { + "text": "1: Creating the initial solution", + "path": "tutorials/microservice/part-01.md" + }, + { + "text": "2: Creating the initial Catalog service", + "path": "tutorials/microservice/part-02.md" + }, + { + "text": "3: Building the Catalog service", + "path": "tutorials/microservice/part-03.md" + }, + { + "text": "4: Creating the initial Ordering service", + "path": "tutorials/microservice/part-04.md" + }, + { + "text": "5: Building the Ordering service", + "path": "tutorials/microservice/part-05.md" + }, + { + "text": "6: Integrating the services: HTTP API Calls", + "path": "tutorials/microservice/part-06.md" + }, + { + "text": "7: Integrating the services: Using Distributed Events", + "path": "tutorials/microservice/part-07.md" + } + ] + }, { "text": "Community Articles", "path": "https://abp.io/community" @@ -227,8 +264,8 @@ "path": "studio/concepts.md" }, { - "text": "Version Compatibility", - "path": "studio/version-compatibility.md" + "text": "Version Mapping", + "path": "studio/version-mapping.md" }, { "text": "Release Notes", @@ -893,7 +930,7 @@ "items": [ { "text": "Overview", - "path": "framework/ui/mvc-razor-pages/overall" + "path": "framework/ui/mvc-razor-pages/overall.md" }, { "text": "Navigation / Menus", @@ -1642,6 +1679,10 @@ "text": "Overview", "path": "solution-templates" }, + { + "text": "Template Guide", + "path": "solution-templates/guide.md" + }, { "text": "Single-Layer Solution", "path": "solution-templates/single-layer-web-application" @@ -1718,7 +1759,16 @@ }, { "text": "Account (Pro)", - "path": "modules/account-pro.md" + "items": [ + { + "text": "Overview", + "path": "modules/account-pro.md" + }, + { + "text": "Tenant impersonation & User impersonation", + "path": "modules/account/impersonation.md" + } + ] }, { "text": "Audit Logging", diff --git a/docs/en/docs-params.json b/docs/en/docs-params.json index 46e496f248..e108f1b554 100644 --- a/docs/en/docs-params.json +++ b/docs/en/docs-params.json @@ -7,6 +7,7 @@ "MVC": "MVC / Razor Pages", "Blazor": "Blazor WebAssembly", "BlazorServer": "Blazor Server", + "BlazorWebApp": "Blazor WebApp", "NG": "Angular" } }, diff --git a/docs/en/framework/infrastructure/event-bus/index.md b/docs/en/framework/infrastructure/event-bus/index.md index 982268780a..1c3f59bc4e 100644 --- a/docs/en/framework/infrastructure/event-bus/index.md +++ b/docs/en/framework/infrastructure/event-bus/index.md @@ -6,5 +6,26 @@ An event bus is a mediator that transfers a message from a sender to a receiver. ABP provides two type of event buses; -* **[Local Event Bus](local)** is suitable for in-process messaging. -* **[Distributed Event Bus](distributed)** is suitable for inter-process messaging, like microservices publishing and subscribing to distributed events. \ No newline at end of file +* **[Local Event Bus](local/index.md)** is suitable for in-process messaging. +* **[Distributed Event Bus](distributed/index.md)** is suitable for inter-process messaging, like publishing and subscribing to distributed events in a distributed/microservice system. + +## Event Bus Guiding + +You may confuse which event bus to use in your application. Here, a few example scenarios: + +* If you are building a microservice system, use the distributed event bus for **inter-microservice communication**. If you are publishing an event and always handling it in the same microservice, you can use the local event bus for that event. +* If you are building a modular monolith application, use the distributed event bus for **inter-module communication**. Since the distributed event bus works in-process by default (unless you configure a real distributed event bus provider). In that way, if you migrate to a microservice system later, these inter-module communication can become a inter-microservice communication without any code change (with just installing a distributed event bus provide package). If you are publishing an event and always handling it in the same module, you can use the local event bus for that event. +* If you are building a monolith (non-modular) application, you can always use the local event bus. + +The distributed event bus works in-process by default. Unless you don't configure a real distributed event bus provider, it works just like the local event bus. Once you configure a real distributed event bus provider, all your events become distributed. + +So, you use the local event bus only if you an event should always remain in-process in any scenario. For other type of events, use the distributed event bus. + +### Technical Differences + +There are some technical differences between the local and distributed event bus: + +* You can send entities or other non-serializable objects using the local event bus since these objects are not serialized/deserialized on event publishing. On the other hand, distributed event bus serializes/deserializes objects once you use a real distributed event bus provider. +* The local event bus is always transactional in the database level. For distributed event bus, you should enable inbox/outbox pattern to ensure data consistency once you use a real distributed event bus provider. + +These differences are because of the distributed event bus supports distributed scenarios while the local event bus is only used for in-process messaging. When you don't set up a real distributed event bus provider, these differences are not valid. \ No newline at end of file diff --git a/docs/en/framework/ui/angular/http-error-handling.md b/docs/en/framework/ui/angular/http-error-handling.md index e165ac7125..14d4589c97 100644 --- a/docs/en/framework/ui/angular/http-error-handling.md +++ b/docs/en/framework/ui/angular/http-error-handling.md @@ -27,7 +27,7 @@ export class AppModule {} ``` - `ErrorScreenErrorCodes` the error codes that you can pass to `skipHandledErrorCodes` and `forWhichErrors`. -- `skipHandledErrorCodes` the error codes those you don't want to handle it. +- `skipHandledErrorCodes` the error codes those you don't want to handle. - `errorScreen` the screen that you want to show when a route error occurs. - `component` component that you want to show. - `forWhichErrors` same as `ErrorScreenErrorCodes` diff --git a/docs/en/get-started/images/abp-studio-microservice-solution-runner-docker-dependencies.png b/docs/en/get-started/images/abp-studio-microservice-solution-runner-docker-dependencies.png deleted file mode 100644 index 99c09045f8..0000000000 Binary files a/docs/en/get-started/images/abp-studio-microservice-solution-runner-docker-dependencies.png and /dev/null differ diff --git a/docs/en/get-started/index.md b/docs/en/get-started/index.md index 1f8d864450..59f9812563 100644 --- a/docs/en/get-started/index.md +++ b/docs/en/get-started/index.md @@ -5,10 +5,14 @@ Great that you've decided to create a new application with ABP. ABP provides mul Please select one of the following documents best fits for your application: - **[Single-Layer Solution](single-layer-web-application.md)**: Creates a single-project solution. Recommended for building an application with a **simpler and easy to understand** architecture. -- **[Layered Solution](layered-web-application.md)**: A fully layered (multiple projects) solution based on [Domain Driven Design](../framework/architecture/domain-driven-design) practices. Recommended for long-term projects that need a **maintainable and extensible** codebase. +- **[Application (Layered)](layered-web-application.md)**: A fully layered (multiple projects) solution based on [Domain Driven Design](../framework/architecture/domain-driven-design) practices. Recommended for long-term projects that need a **maintainable and extensible** codebase. - **[Microservice Solution](microservice.md)**: A **distributed solution** to build **microservice systems**. It includes pre-built services, API gateways, web and mobile applications, Kubernetes and Helm configuration, and everything you need to start your large-scale microservice solution. - **Others** - [Empty ASP.NET Core Application](empty-aspnet-core-application.md) - [MAUI Application](maui.md) - [WPF Application](wpf.md) - [Console Application](console.md) + +## Which Startup Template is Suitable for Me? + +You can see the *[Solution Template Selection Guide](../solution-templates/guide.md)* if you are not sure which solution template is suitable for you. diff --git a/docs/en/get-started/layered-web-application.md b/docs/en/get-started/layered-web-application.md index 188e0cfd15..e8896b8666 100644 --- a/docs/en/get-started/layered-web-application.md +++ b/docs/en/get-started/layered-web-application.md @@ -3,7 +3,7 @@ ````json //[doc-params] { - "UI": ["MVC", "Blazor", "BlazorServer", "NG"], + "UI": ["MVC", "Blazor", "BlazorServer", "BlazorWebApp", "NG"], "DB": ["EF", "Mongo"], "Tiered": ["Yes", "No"] } @@ -162,7 +162,7 @@ You can start the following application(s): {{ else if UI == "Blazor" }} {{ if Tiered == "No" }}- `Acme.BookStore.HttpApi.Host`{{ end }} - `Acme.BookStore.Blazor` -{{ else if UI == "BlazorServer" }} +{{ else if UI == "BlazorServer" || UI == "BlazorWebApp" }} - `Acme.BookStore.Blazor` {{ else }} - `Acme.BookStore.Web` @@ -174,7 +174,7 @@ You can start the following application(s): > Notice that the services running in docker-compose are exposed to your localhost. If any service in your localhost is already using the same port(s), you will get an error. In that case, stop your local services first. {{ end }} -Once the `Acme.BookStore.{{ if UI == "NG" }}Angular{{ else if UI == "BlazorServer" || UI == "Blazor" }}Blazor{{ else }}Web{{ end }}` application started, you can right-click it and select the *Browse* command: +Once the `Acme.BookStore.{{ if UI == "NG" }}Angular{{ else if UI == "BlazorServer" || UI == "Blazor" || UI == "BlazorWebApp" }}Blazor{{ else }}Web{{ end }}` application started, you can right-click it and select the *Browse* command: ![abp-studio-quick-start-browse-command](images/abp-studio-quick-start-browse-command.png) @@ -206,7 +206,7 @@ Once the solution is opened in Visual Studio, you should see a screen like shown ![visual-studio-bookstore-application](images/visual-studio-bookstore-application.png) -Right-click the `Acme.BookStore.{{ if UI == "NG" || UI == "Blazor" }}HttpApi.Host{{ else if UI == "BlazorServer" }}Blazor{{ else }}Web{{ end }}` project and select the *Set as Startup Project* command. You can then hit *F5* or *Ctrl + F5* to run the web application. It will run and open the application UI in your default browser: +Right-click the `Acme.BookStore.{{ if UI == "NG" || UI == "Blazor" }}HttpApi.Host{{ else if UI == "BlazorServer" || UI == "BlazorWebApp" }}Blazor{{ else }}Web{{ end }}` project and select the *Set as Startup Project* command. You can then hit *F5* or *Ctrl + F5* to run the web application. It will run and open the application UI in your default browser: ![bookstore-browser-users-page](images/bookstore-browser-users-page.png) @@ -242,4 +242,4 @@ Before starting the mobile application, ensure that you configure it for [react- > For example in non-tiered MVC with public website application: -![solution-runner-public-website](images/solution-runner-public-website.png) \ No newline at end of file +![solution-runner-public-website](images/solution-runner-public-website.png) diff --git a/docs/en/get-started/microservice.md b/docs/en/get-started/microservice.md index 5be705e215..7a94ae3bdf 100644 --- a/docs/en/get-started/microservice.md +++ b/docs/en/get-started/microservice.md @@ -73,11 +73,11 @@ Click the Next button to see *Additional Options* selection: If you unchecked the *Kubernetes Configuration* option, the solution will not include the Kubernetes configuration files which include the Helm charts and other Kubernetes related files. You can also specify *Social Logins*; if you uncheck this option, the solution will not be configured for social login. Lastly, you can specify the *Include Tests* option to include the test projects in the solution. -Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. After clicking the Create button, the dialog is closed and your solution is loaded into ABP Studio: +Now, we are ready to allow ABP Studio to create our solution. Just click the *Create* button and let the ABP Studio do the rest for you. After clicking the *Create* button, the dialog is closed and your solution is loaded into ABP Studio: ![abp-studio-created-new-microservice-solution](images/abp-studio-created-new-microservice-solution.png) -You can explore the solution, but you need to wait for background tasks to be completed before running any application in the solution (it can take up to a few minutes to set up all). +You can explore the solution, but you need to **wait for background tasks to be completed** before running any application in the solution (it can take up to a few minutes to set up all). > The solution structure can be different in your case based on the options you've selected. @@ -123,9 +123,7 @@ In the *Solution Runner* section (on the left side) you can see all the runnable ![abp-studio-microservice-solution-runner-applications](images/abp-studio-microservice-solution-runner-applications.png) -> All the leaf items in the *Solution Runner* is called as an *Application* as they are executable applications. - -> For a faster start process, first start the *Docker-Dependencies*, then you can start all applications. +> A leaf item in the *Solution Runner* is called as an *Application* as it is an executable application. As shown in the figure above, the executable applications are grouped into folders like `apps`, `gateways`, `infrastructure`, and `services`. You can start/stop them all, a group (folder) of them, or one by one. @@ -135,16 +133,14 @@ Before running the applications, it is good to be sure that all applications are > *Solution Runner* doesn't build an application before running it. That provides a great performance gain because most of the time you will work on one or a few services and you don't need to build all of the other applications in every run. However, if you want to build before running, you can right-click an item in the *Solution Runner* tree and select *Run* -> *Build & Start* command. -It will take some time to build all. Once all is done, you can start the system. - -You can click the *Play* button on the root item in Solution Runner to start all the applications. Or you can start `Docker-Dependencies` first, so the database and other infrastructure services get ready before the other applications: - -![abp-studio-microservice-solution-runner-docker-dependencies](images/abp-studio-microservice-solution-runner-docker-dependencies.png) +It will take some time to build all. Once all is done, you can start the system. You can click the *Play* button on the root item in Solution Runner to start all the applications. +> **About the Docker Containers** +> > Docker will fetch the docker images before starting the containers in your first run (if they were not fetched before) and that process may take a few minutes depending on your internet connection speed. So, please wait for it to completely start. If the process takes more time than you expect, you can right-click on `Docker-Dependencies` and select the *Logs* command to see what's happening. -Once `Docker-Dependencies` is ready, you can click the *Play* button on the root item in Solution Runner to start all the applications. - +> **About Failing Services on Startup** +> > Some applications/services may fail on the first run. That may be because of service and database dependencies were not satisfied and an error occurs on the application startup. ABP Studio automatically restarts failing services until it is successfully started. Being completely ready for such a distributed solution may take a while, but it will be eventually started. Once all the applications are ready, you can right-click the `Web` application and select the *Browse* command: @@ -222,6 +218,8 @@ Once the solution is ready in Kubernetes, you can open a browser and visit the f ![abp-studio-microservice-web-application-home-page](images/abp-studio-microservice-web-application-home-page.png) +> We could use `cloudcrm-local-web` as the host name since ABP Studio has added an entry to the host file for us. + Click the *Login* link in the application UI, it will redirect you to the *Authentication Server* application, enter `admin` as username and `1q2w3E*` as password to login to the application. > The services run independently from each other and perform some initial data seed logic on their startups. So, they may fail in their first run. In that case, Kubernetes will re-start them. So, it may initially get some time to make the solution fully ready and working. @@ -248,11 +246,11 @@ Clicking the *Connect* button will start a process that establishes the VPN conn ![abp-studio-microservice-kubernetes-services](images/abp-studio-microservice-kubernetes-services.png) -Now, you can access all the services inside the Kubernetes cluster, including the services those are not exposes out of the cluster. You can use the service name as DNS. For example, you can directly visit `http://cloudcrm-local-identity` in your Browser. You can also right-click to a service or application and select the Browse command to open it's UI in the built-in browser of ABP Studio: +Now, you can access all the services inside the Kubernetes cluster, including the services those are not exposed out of the cluster. You can use the service name as DNS. For example, you can directly visit `http://cloudcrm-local-identity` in your Browser. You can also right-click to a service or application and select the Browse command to open it's UI in the built-in browser of ABP Studio: ![abp-studio-microservice-kubernetes-services-browse](images/abp-studio-microservice-kubernetes-services-browse.png) -You can even use the other services (e.g. SQL Server or RabbitMQ) from your local computer (even if they were not exposed out of cluster) with their service names. `sa` password for the SQL server is `myPassw@rd` by default, you can use your SQL Server management studio to connect to it and see the databases: +You can even use the other services (e.g. SQL Server or RabbitMQ) from your local computer (even if they were not exposed out of cluster) with their service names. `sa` password for the SQL server is `myPassw@rd` by default, you can use your SQL Server management studio to connect to it and see the databases (*Server name* is `cloudcrm-local-sqlserver`): ![abp-studio-microservice-sql-server-connection](images/abp-studio-microservice-sql-server-connection.png) @@ -266,6 +264,8 @@ When you connect to Kubernetes, ABP Studio automatically connects to the applica In this way, you can easily track HTTP requests, distributed events, exceptions, logs and other details of your applications. +> If you want to browse a web application in the integrated browser of ABP Studio, right-click to a service in the *Kubernetes* tab of the *Kubernetes* panel and select the *Browse* command. + ## Kubernetes Integration: Intercepting Services The next step is to intercept a service to forward the traffic (coming to that service) to your local computer, so you can run the same service in your local computer to test, debug and develop it. This is the way of connecting two environments (your local machine and the Kubernetes cluster) to develop your services integrated to Kubernetes. @@ -306,3 +306,7 @@ To re-deploy a service to Kubernetes, right-click the service and select *Comman ![abp-studio-microservice-kubernetes-redeploy](images/abp-studio-microservice-kubernetes-redeploy.png) ABP Studio will re-build the Docker image and re-install it using the related Helm chart. + +## See Also + +* [Microservice Development Tutorial](../tutorials/microservice/index.md) diff --git a/docs/en/modules/account/impersonation.md b/docs/en/modules/account/impersonation.md index ed008c6418..e814a414b2 100644 --- a/docs/en/modules/account/impersonation.md +++ b/docs/en/modules/account/impersonation.md @@ -71,7 +71,7 @@ No need to do anything here. #### Web 1. Depends `AbpAccountPublicWebImpersonationModule(Volo.Abp.Account.Pro.Public.Web.Impersonation)` on your `WebModule` -2. Chnage the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` +2. Change the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` ```cs public class AccountController : AbpAccountImpersonationChallengeAccountController @@ -197,7 +197,7 @@ No need to do anything here. 1. Depends `AbpAccountPublicWebImpersonationModule(Volo.Abp.Account.Pro.Public.Web.Impersonation)` and `AbpAccountPublicBlazorServerModule(Volo.Abp.Account.Pro.Public.Blazor.Server)` on your `BlazorModule` -2. Chnage the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` +2. Change the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` ```cs public class AccountController : AbpAccountImpersonationChallengeAccountController { @@ -301,7 +301,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) #### Web 1. Depends `AbpAccountPublicWebImpersonationModule(Volo.Abp.Account.Pro.Public.Web.Impersonation)` on your `WebModule` -2. Chnage the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` +2. Change the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` ```cs public class AccountController : AbpAccountImpersonationChallengeAccountController @@ -367,7 +367,7 @@ public override void ConfigureServices(ServiceConfigurationContext context) 1. Depends `AbpAccountPublicWebImpersonationModule(Volo.Abp.Account.Pro.Public.Web.Impersonation)` and `AbpAccountPublicBlazorServerModule(Volo.Abp.Account.Pro.Public.Blazor.Server)` on your `BlazorModule` -2. Chnage the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` +2. Change the base class of `AccountController` to `AbpAccountImpersonationChallengeAccountController` ```cs public class AccountController : AbpAccountImpersonationChallengeAccountController { diff --git a/docs/en/modules/openiddict.md b/docs/en/modules/openiddict.md index 5f421d9001..35c5220096 100644 --- a/docs/en/modules/openiddict.md +++ b/docs/en/modules/openiddict.md @@ -279,7 +279,7 @@ UserInfoController -> connect/userinfo > **Device flow** implementation will be done in the commercial module. -#### AbpOpenIddictAspNetCoreOptions +### AbpOpenIddictAspNetCoreOptions `AbpOpenIddictAspNetCoreOptions` can be configured in the `PreConfigureServices` method of your OpenIddict [module](../framework/architecture/modularity/basics.md). diff --git a/docs/en/release-info/migration-guides/abp-8-3.md b/docs/en/release-info/migration-guides/abp-8-3.md index 85d67e5f1e..b68805a3ab 100644 --- a/docs/en/release-info/migration-guides/abp-8-3.md +++ b/docs/en/release-info/migration-guides/abp-8-3.md @@ -57,6 +57,24 @@ In this version, we have started updating entities' `EntityVersion`, `Modificati We wish to formally inform you that ABP version 8.3 has been upgraded to incorporate Angular version 18. Consequently, we recommend migrating your application to [Angular v18](https://angular.dev/update-guide) to ensure compatibility. +#### Tenant impersonation & User impersonation + +Add the `impersonation: { userImpersonation: true, tenantImpersonation: true}` object to the `oAuthConfig` of the environment if it does not exit. + +``` +export const environment = { + //Other props.. + oAuthConfig: { + //Other props.. + impersonation: { + userImpersonation: true, + tenantImpersonation: true, + }, + }, +``` + +See https://abp.io/docs/latest/modules/account/impersonation#angular + ## PRO > Please check the **Open-Source (Framework)** section before reading this section. The listed topics might affect your application and you might need to take care of them. diff --git a/docs/en/release-info/release-notes.md b/docs/en/release-info/release-notes.md index e94086e14f..b86da2c079 100644 --- a/docs/en/release-info/release-notes.md +++ b/docs/en/release-info/release-notes.md @@ -4,11 +4,9 @@ This document contains **brief release notes** for each release. Release notes o > If you want to read the release notes for each ABP Studio release, check it out from [here](../studio/release-notes.md). -## 9.0 (2024-10-22) +## 9.0 (2024-11-19) -> This version is currently in preview. The final release date is planned for November, 2024. - -See the detailed **[blog post / announcement](https://abp.io/blog/announcing-abp-9-0-release-candidate)** for the v9.0 release. +See the detailed **[blog post / announcement](https://abp.io/blog/abp-9-0-stable-release-with-dotnet-9-0)** for the v9.0 release. * Upgraded to .NET 9.0 * Introducing the `Extension Property Policy` diff --git a/docs/en/release-info/upgrading.md b/docs/en/release-info/upgrading.md index 496b3b2961..28404c20b4 100644 --- a/docs/en/release-info/upgrading.md +++ b/docs/en/release-info/upgrading.md @@ -20,7 +20,7 @@ Run this command in the terminal while you are in the root folder of your soluti When you upgrade to a new version, it is good to check if there is a database schema change and upgrade your database schema if your database provider is **Entity Framework Core**; -* Use `Add-Migration "Upgraded_To_Abp_8_2"` or a similar command in the Package Manager Console (PMC) to create a new migration (Set the `EntityFrameworkCore` as the Default project in the PMC and `.DbMigrator` as the Startup Project in the Solution Explorer, in the Visual Studio). +* Use `Add-Migration "Upgraded_To_Abp_8_3"` or a similar command in the Package Manager Console (PMC) to create a new migration (Set the `EntityFrameworkCore` as the Default project in the PMC and `.DbMigrator` as the Startup Project in the Solution Explorer, in the Visual Studio). * Apply the database migrations to your database. If available, you can run the `.DbMigrator` application to upgrade the database and seed the initial data. > If `Add-Migration` generates an empty migration (that means no schema change), you can use `Remove-Migration` to delete it before executing the `.DbMigrator`. @@ -57,4 +57,4 @@ Preview releases and nightly builds can help you to try new features and adapt y ## See Also -* [Migration Guides](migration-guides) \ No newline at end of file +* [Migration Guides](migration-guides) diff --git a/docs/en/solution-templates/guide.md b/docs/en/solution-templates/guide.md new file mode 100644 index 0000000000..cb14f57ef3 --- /dev/null +++ b/docs/en/solution-templates/guide.md @@ -0,0 +1,184 @@ +# Solution Templates: A Guide to Select the Right One For You + +ABP provides several [startup templates](index.md) to you. It is important to start with the right startup template that is suitable for your **project** and **team**. This guide aims to lead you to select the most proper startup template for your requirements. + +The following **architectures** will be discussed based on ABP startup templates: + +* **Single-Layer** (non-layered) application +* **N-Layered** application +* **Modular** application +* **Microservice** solution + +## What is a Startup Template? + +In the following section, you will understand what a startup template is and what it provides. + +### Pre-Architected Solution Structure + +A startup solution template is a **pre-architected** structure. For example, the [layered startup template](layered-web-application/index.md) is a great starting point if you want to build a layered application code-base based on [Domain-Driven Design](../framework/architecture/domain-driven-design/index.md) principles and patterns. + +However, starting with any startup template **doesn't limit you** on adding or removing projects, layers, integration packages, and creating other applications/services. You can even start with a [single-layer application template]() and convert it to a microservice solution. However, if you want to build a microservice solution, starting with the [microservice startup template](microservice/index.md) is the best. + +So, it is **best to start with the most suitable startup template** for your purpose and then modify the solution to fit your custom requirements. + +### Well-Structured Code Organization + +Besides the overall solution structure, the internals of each project in a solution template are well-structured. It is clear where will you place your [entities](../framework/architecture/domain-driven-design/entities.md), [repositories](../framework/architecture/domain-driven-design/repositories.md), [data access code](../framework/data/index.md), [application services](../framework/architecture/domain-driven-design/application-services.md), [API controllers](../framework/api-development/index.md), [UI elements](../framework/ui/index.md), etc. You don't spend time thinking about how to **organize your codebase** in every new project. If you prefer to build automated tests for your application, the test projects are also included and pre-configured. + +### Library Integrations & Configurations + +When you use ABP startup solution templates to create a new solution, some **fundamental library installations** ([Serilog](https://serilog.net/), [Autofac](https://autofac.org/), [AutoMapper](https://automapper.org/), [Swagger](https://swagger.io/), [HealthCheck](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks) and others..) and their fine-tuned configurations are already prepared for you. Also, required **[ABP packages](https://abp.io/packages)** are just installed based on your preferences and configured for **development and production environments**. + +### Development Ready + +When you create a new solution, or when a new teammate starts to work on your existing solution, it is pretty **easy to understand** the solution structure, design decisions and the development flow by the help of [solution structure documents](index.md) and [development tutorials](../tutorials/index.md). + +### Production Ready + +ABP's startup templates are ready for production out of the box. You can just create a new solution and **deploy it** to your production environment. It is not only about **technical readiness**, but also about **functional readiness**. + +When you create a new ABP solution, **fundamental modules are already installed**. Your application has a robust [account module](../modules/account.md) (user registration, login, social logins, 2-factor authentication, user lockout, password complexity control...), an advanced [identity module](../modules/identity.md) (user, role and permission management), and many other production-ready [pre-built application modules](../modules/index.md) are just working as a part your application in the first day. + +## The Startup Solution Templates + +Up to this point, it is explained what a startup template is and the features it offers. In the following section, you will see the types of startup solution templates and **which one is best for you**. + +### Single-Layer Application Solution Template + +The [single-layer solution template](single-layer-web-application/index.md) is the simplest. It provides a **minimal solution architecture** while starting a new project. Your .NET solution typically contains a **single, or a few .NET projects** depending on your UI and other preferences while creating your solution. + +The following figure shows a single-project web application that has [MVC (Razor Pages) UI](../framework/ui/mvc-razor-pages/overall.md) and [Entity Framework Core](../framework/data/entity-framework-core/index.md) database provider with the default configuration: + +![single-layer-abp-solution](images/single-layer-abp-solution.png) + +As you see in the preceding figure, all the application code (entities, data access, services, UI pages, etc.) are located in a **single .NET project**. + +#### When Should You Start a Single-Layer Solution Template? + +In the following conditions, you may consider to use the single-layer solution template: + +* If **your project is small** and you don't expect that it will grow by the time. But remember that many projects are thought of as small in the beginning. +* If your project is a **temporary project** and it will be trash in a short time. It can be a POC project or a temporary application for a demo or advertisement campaign. +* If you are a **single developer** or there are only 2-3 developers working on your solution, and these developers are not experienced and are not willing to understand the structure and benefits of a layered application. + +If the preceding conditions are met with your case, you can consider starting with this solution template. +However, keep in mind that your solution can quickly become a **[big ball of mud](https://thedomaindrivendesign.io/big-ball-of-mud/)**. +We think that only a **very small portion of applications** are suitable for that kind of solution structure. + +Note that the single-layer solution template doesn't provide the following options/features: + +* Mobile application integration +* Public website (a second web application for landing page of your product) +* Tiered architecture (for MVC applications, separates UI and service layers) +* Separate tenant schema (for multi-tenant applications) +* Kubernetes / Helm configuration +* Automated (unit/integration) test projects + +These options are not implemented to keep the solution structure as simple as possible. If you need some of these, please feel free to use the layered solution template. + +### Layered Solution Template + +The [layered application startup template](layered-web-application/index.md) is a .NET solution that consists of several projects. +Each project represents a layer of the application or has a specific functionality for the solution. + +The exact project count in your solution depends on the options you have selected. +The following figure shows a solution with [MVC (Razor Pages) UI](../framework/ui/mvc-razor-pages/overall.md) and [Entity Framework Core](../framework/data/entity-framework-core/index.md) database provider with the default configuration: + +![layered-abp-application](images/layered-abp-application.png) + +The solution is layered based on Domain-Driven Design principles and extended based on real-world business application requirements. It includes test projects for each layer. Layering the solution has great benefits: + +* It makes your business code (domain & application layers) independent from infrastructure (UI and database) that makes it more **maintainable and long-living**. +* Different developers can **focus on different layers**. It is valuable when multiple developers (with different roles) touching to the same solution. +* It **separate concerns**, so you can focus on a single concern at a time. You can optimize your data access code without touching other layers, you can change your UI code without breaking your business logic. +* It provides **maximum code reusability**. If you have multiple applications (e.g. one back office application, one end-user application, and a mobile application), it is easy to separate these application's codebases (simply create new application & UI layers for each application type) while they can share the same domain and data access layers. +* Separating **UI layer** gives an opportunity to **replace/modify** it in the future without affecting other parts of your solution. You know, UI is the fastest changing technology in software industry. + +While it may seem a little complicated at the beginning, once you **complete the [Book Store tutorial](../tutorials/book-store/index.md)**, you will easily understand the purpose and usage of each project. + +#### When Should You Start a Layered Solution Template? + +In the following conditions, you may consider to use the layered solution template: + +* If your project **code-base** is relatively **larger**. +* If your project is **relatively complex** and involves multiple business domains or complex workflows. +* If your project is a **long-term** project and you want to design it as **maintainable** for long years. +* If you are **a team of developers** working on your solution. When multiple teams or developers work on different parts of the system. +* If your solution will have **multiple** web, mobile or other type of **applications** that need to **share** the same business logic. +* If your project needs **scalability**, solutions that may need to scale in functionality or user load over time. +* If your project needs **extensibility**, which requires the addition of new features or integration with third-party services. + +### Modular Monolith Applications + +ABP does not provide a specific modular monolith application startup template. However, it is not needed. Let us explain why. + +The ABP Framework and [ABP Studio](../studio/index.md) are already designed to support modular application development from their beginning. ABP framework provides all the **necessary infrastructure** for [modularity](../framework/architecture/modularity/basics.md) and all other framework features are **compatible with modular solutions**. + +On the other hand, the main purpose of ABP Studio's [Solution Explorer panel](../studio/solution-explorer.md) is to **architect and build modular and complex software solutions**. You can easily create new modules, arrange dependencies between the modules and import/install these modules into a monolith application. While you can do all these manually yourself, ABP Studio makes it extremely easy to do and understand it. + +#### How to Build a Modular Monolith Application? + +A **modular monolith** application consists of a **single host** application and **multiple sub-modules**. Typically, each module has its own .NET solution that contains the code related to that module. So, the general structure is shown in the following figure: + +![example-modular-solution](images/example-modular-solution.png) + +In this example, `MyCrm.Host` is an almost-empty host application that has package references to other modules. Every module consists of two packages: implementation and contract packages. + +You can follow the steps below to create such a modular solution with ABP Studio: + +* **Create a new application** using either [single-layer](single-layer-web-application/index.md) or [layered](layered-web-application/index.md) application startup template. That application will be the **host application** of your solution. +* **Create new modules** (right-click to the solution root, select the *Add* -> *New Module* -> ... command). +* **Import & Install** these **modules** to the host application. + +> You can follow the **[Modular Monolith Application Development Tutorial](../tutorials/modular-crm/index.md)** to learn how to build a modular application step by step. + +#### Which Startup Template should be used for a Modular Application? + +So, both [single-layer](single-layer-web-application/index.md) and [layered](layered-web-application/index.md) application startup templates are inherently modular. Just use one of them and start your modular solution. You may wonder which one to start: + +* Use the **[single-layer startup template](single-layer-web-application/index.md)** for the host application of your modular monolith if you will leave the host application as empty. It will contain some configuration code of course, but it won't contain any actual application code. **This is the suggested approach.** +* Use the **[layered application startup template](layered-web-application/index.md)** if you will write some application code into the hosting application. You may want to write some code that makes multiple module operations that are not easy to implement in a particular module. In that case, a layered hosting application will be a better way to organize your codebase. However, this approach can quickly move your solution away from a modular system. So, take your own risk. + +#### When Should You Start a Modular Monolith Application? + +In the following conditions, you may consider to build a modular software solution: + +* If your **domain is too complex** to develop and maintain in a single monolith codebase. +* If your business domain has clear functional boundaries and is possible to **split into sub-domains**. +* If you have **multiple teams** that will work on the solution. +* When you need to **reduce complexity** early on. And if you are considering migrating your application to a **microservice system**. + +While all these are also suitable for microservice solutions (which will be discussed in the next section), a modular solution is more suitable than microservices for most of the projects. +Especially if you don't need to have technology diversity, deploy and scale services independently and serve too many users concurrently with a fault-tolerant system, a modular monolith application would be a better choice to not deal with the complexity of a microservice system. Also, it is better to start with a thin architecture when you have a small team that can focus on building features without spending time managing distributed architecture complexities. Another advantage is that the modular monoliths avoid the network latency and communication overhead inherent in microservices, so debugging and monitoring are easier as all modules run within a single application. In summary, if you anticipate that your application may grow to require a microservices architecture in the future, a modular monolith is a great starting point. + +> Build for Now, Scale for Tomorrow + +Even if you are considering building a microservice architecture, it is usually advised to [start with a monolith modular first](https://martinfowler.com/bliki/MonolithFirst.html), then migrate to microservices later once your business and module boundaries are more stable. + +### Microservice Solution Template + +ABP's [microservice startup template](microservice/index.md) includes multiple services, API gateways and applications that are well integrated into each other and ready to be a great **base solution for your microservice system**. +In the following picture, you can see an overall diagram that shows the main components of the solution (they vary based on the options while you are creating your solution): + +![ms-overall-architecture](microservice/images/overall-architecture.png) + +#### When Should You Start a Microservice Solution Template? + +In the following conditions, you may consider to build a microservice system: + +* If your **domain is too complex** to develop and maintain in a single monolith codebase. +* If your business domain is possible to **split into sub-domains**. +* If you have **multiple teams** that will work on the solution in parallel. +* If you need to **develop**, **test**, **deploy** and **scale services** independently. +* If you need to use **multiple technology stacks** so, some services can be built with .NET, and others can be built with Java, Python, etc... +* If you need to serve **too many users** concurrently with a **high available** and **fault tolerant** system. +* If you have **DevOps** knowledge and culture in your company. If you can deal with **complex** development, build, test, deployment and production environments. + +**Use Case Examples** +* **E-Commerce Platforms**: Separate services for cart, checkout, inventory, and shipping. +* **Streaming Services**: Modules for content delivery, user preferences, and recommendations. +* **SaaS Platforms**: Independent services for billing, user accounts, and analytics. + +## Conclusion + +In summary, the ABP Platform offers a variety of solution templates tailored to different architectural needs, including layered applications, microservices, and modular development. These templates provide a great foundation for building robust applications by implementing best practices and providing essential features. By selecting the right template, you can streamline the development process, ensuring scalability and maintainability in your project. diff --git a/docs/en/solution-templates/images/example-modular-solution.png b/docs/en/solution-templates/images/example-modular-solution.png new file mode 100644 index 0000000000..49e7b72c08 Binary files /dev/null and b/docs/en/solution-templates/images/example-modular-solution.png differ diff --git a/docs/en/solution-templates/images/layered-abp-application.png b/docs/en/solution-templates/images/layered-abp-application.png new file mode 100644 index 0000000000..02c8fa49a0 Binary files /dev/null and b/docs/en/solution-templates/images/layered-abp-application.png differ diff --git a/docs/en/solution-templates/images/single-layer-abp-solution.png b/docs/en/solution-templates/images/single-layer-abp-solution.png new file mode 100644 index 0000000000..fab2a85ecd Binary files /dev/null and b/docs/en/solution-templates/images/single-layer-abp-solution.png differ diff --git a/docs/en/solution-templates/index.md b/docs/en/solution-templates/index.md index 76a5348bec..b5bf59688d 100644 --- a/docs/en/solution-templates/index.md +++ b/docs/en/solution-templates/index.md @@ -1,12 +1,21 @@ # Solution Templates -ABP provides pre-architected and production-ready templates to jump start a new solution. The following solution templates are provided out of the box: +ABP provides pre-architected and production-ready templates to jump start a new solution. -* **[Single-Layer Solution](single-layer-web-application)**: A single-project solution. Recommended for building an application with a **simpler and easy to understand** architecture. -* **[Layered Solution](layered-web-application)**: A fully layered (multiple projects) solution based on [Domain Driven Design](../framework/architecture/domain-driven-design) practices. Recommended for long-term projects that need a **maintainable and extensible** codebase. -* **[Microservice Solution](microservice)**: A **distributed solution** to build **microservice systems**. It includes pre-built services, API gateways, web and mobile applications, Kubernetes and Helm configuration, and everything you need to start your large-scale microservice solution. -* **[Application Module](application-module)**: A template that can be used to create a **reusable [application module](../modules)** based on the [module development best practices & conventions](../framework/architecture/best-practices). It is also suitable for creating **services** (with or without UI). +> **You can see the [Solution Template Selection Guide](guide.md) if you are not sure which solution template is suitable for you.** + +The following solution templates are provided out of the box: + +* **[Single-Layer Solution](single-layer-web-application/index.md)**: A single-project solution. Recommended for building an application with a **simpler and easy to understand** architecture. +* **[Layered Solution](layered-web-application/index.md)**: A fully layered (multiple projects) solution based on [Domain Driven Design](../framework/architecture/domain-driven-design) practices. Recommended for long-term projects that need a **maintainable and extensible** codebase. +* **[Microservice Solution](microservice/index.md)**: A **distributed solution** to build **microservice systems**. It includes pre-built services, API gateways, web and mobile applications, Kubernetes and Helm configuration, and everything you need to start your large-scale microservice solution. +* **[Application Module](application-module/index.md)**: A template that can be used to create a **reusable [application module](../modules/index.md)** based on the [module development best practices & conventions](../framework/architecture/best-practices/index.md). It is also suitable for creating **services** (with or without UI). * **Others** - [MAUI Application](../get-started/maui.md) - [WPF Application](../get-started/wpf.md) - - [Console Application](../get-started/console.md) \ No newline at end of file + - [Console Application](../get-started/console.md) + +## See Also + +* [Solution Template Selection Guide](guide.md) +* [Get Started with ABP Platform](../get-started/index.md) \ No newline at end of file diff --git a/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md b/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md index ee6f6667c2..79382f1b0a 100644 --- a/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md +++ b/docs/en/solution-templates/layered-web-application/deployment/deployment-iis.md @@ -254,6 +254,37 @@ We can visit the websites from a browser. ![Tiered IIS deployment](../../../images/iis-sample-tiered-deployment.gif) +## How to get stdout-log + +If your application is running on IIS and getting errors like `502.5, 500.3x`, you can enable stdout logs to see the error details. + +To enable and view stdout logs: + +1. Navigate to the site's deployment folder on the hosting system. +2. If the logs folder isn't present, create the folder. For instructions on how to enable MSBuild to create the logs folder in the deployment automatically, see the [Directory structure topic](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/directory-structure?view=aspnetcore-8.0). +3. Edit the `web.config` file. Set `stdoutLogEnabled` to `true` and change the `stdoutLogFile` path to point to the logs folder (for example, `.\logs\stdout`). stdout in the path is the log file name prefix. A timestamp, process id, and file extension are added automatically when the log is created. Using stdout as the file name prefix, a typical log file is named `stdout_20180205184032_5412.log`. +4. Ensure your application pool's identity has write permissions to the logs folder. +5. Save the updated `web.config` file. +6. Make a request to the app. +7. Navigate to the logs folder. Find and open the most recent stdout log. + +> The following sample aspNetCore element configures stdout logging at the relative path `.\log\.` Confirm that the AppPool user identity has permission to write to the path provided. + +```xml + + +``` + +Reference: + +[IIS log creation and redirection](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/logging-and-diagnostics) + +[Troubleshoot ASP.NET Core on Azure App Service and IIS](https://learn.microsoft.com/en-us/aspnet/core/test/troubleshoot-azure-iis) + ## What's next? - [Docker Deployment using Docker Compose](deployment-docker-compose.md) diff --git a/docs/en/solution-templates/layered-web-application/index.md b/docs/en/solution-templates/layered-web-application/index.md index ef8e707249..5e0d64b2d8 100644 --- a/docs/en/solution-templates/layered-web-application/index.md +++ b/docs/en/solution-templates/layered-web-application/index.md @@ -1,9 +1,9 @@ # Layered Application Solution Template -## Introduction - This template provides a layered application structure based on the [Domain Driven Design](../../framework/architecture/domain-driven-design) (DDD) practices. +## Getting Started + This document explains **the solution structure** and projects in details. If you want to start quickly, follow the guides below: * [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application in a few minutes. @@ -68,7 +68,8 @@ Use the `-m` (or `--mobile`) option to specify the mobile application framework: abp new Acme.BookStore -m react-native ```` -If not specified, no mobile application will be created. +* [The getting started document](../../get-started/layered-web-application.md) explains how to create a new application with this startup template. +* [The application development tutorial](../../tutorials/book-store/part-01.md) explains step by step application development with this startup template. ## Solution Structure diff --git a/docs/en/solution-templates/microservice/images/enable-dynamic-localization.png b/docs/en/solution-templates/microservice/images/enable-dynamic-localization.png new file mode 100644 index 0000000000..8e562bf20f Binary files /dev/null and b/docs/en/solution-templates/microservice/images/enable-dynamic-localization.png differ diff --git a/docs/en/solution-templates/microservice/images/ui-localization-mvc.png b/docs/en/solution-templates/microservice/images/ui-localization-mvc.png new file mode 100644 index 0000000000..e1d715f7e5 Binary files /dev/null and b/docs/en/solution-templates/microservice/images/ui-localization-mvc.png differ diff --git a/docs/en/solution-templates/microservice/localization-system.md b/docs/en/solution-templates/microservice/localization-system.md index fd0dddf093..a350de6848 100644 --- a/docs/en/solution-templates/microservice/localization-system.md +++ b/docs/en/solution-templates/microservice/localization-system.md @@ -18,12 +18,124 @@ Like the other fundamental feature modules ([Permission Management](permission-m ## Language Management +> If the dynamic localization option is enabled, then the *Language Management Module** will be removed from the optional modules and a new microservice named `LanguageService` will be created. The `LanguageService` uses *Language Management Module* behind the scene. + The *Administration* microservice provides a set of APIs to manage localization. The localization resources are defined in each microservice, and when a microservice starts, it registers its localization resources to the related localization tables automatically. After that, you can see the localization resources from the [language texts](../../modules/language-management.md#language-texts) and manage them. ![language-texts](images/language-management-language-texts-page.png) > The *Language Management* module is optional. If you don't need to manage localization resources from the UI, you can uncheck the *Language Management* module while creating the solution. However, each microservice's localization resources are still registered to the database and can be used by the applications. +## Dynamic Localization + +When you create a new microservice solution, you can **enable dynamic localization** option, which allows you to add/remove languages and change localization texts on the application UI: + +![](./images/enable-dynamic-localization.png) + +When you enable this option, a new microservice named **LanguageService** will be added (with the language management module integrated) and you can use its `LanguageServiceResource` class to use the localization entries in your UI application. It's already configured in your final host application, so you don't need to make any configuration related to that. To define a new localization entry you can either use the language files in the `LanguageService` or update the already defined localization entries in the UI (on the *Language Texts* page). + +After defining localization entries or updating them, you can inject the `IStringLocalizer<>` or `IHtmlLocalizer<>` services and use the localized values in your pages for MVC/Razor Pages UI, for instance: + +```html +@page +@using Microsoft.Extensions.Localization +@inject IStringLocalizer L + +
    +

    @L["LongWelcomeMessage"]

    +
    +``` + +## UI Localizations + +In the microservice architecture, localizations also can be defined in the final host application, if they only need to be defined in the UI. When you create a new microservice solution template, independent from the UI, all configurations are made and you can directly define localization entries and use them in your final UI application. + +> **Note:** When you define localization entries in the host application, then you can't make dynamic localization with the language management module! (Because the language management module, would be unaware of the defined localization entries on the UI side) + +### MVC/Razor Pages & Blazor UIs + +For MVC & Blazor UIs, you can see the **Localization** directory in your final application, like in the following figure: + +![](./images/ui-localization-mvc.png) + +In this directory, you can see the language files, those are pre-defined for you to directly add localization entries. The related configurations are already made for you, in the module class (inside the `ConfigureLocalization` method) as below: + +```csharp + private void ConfigureLocalization(IWebHostEnvironment hostingEnvironment) + { + //code abbreviated for brevity... + + Configure(options => + { + options.Resources + .Add("en") + .AddVirtualJson("/Localization/CloudCrmWeb"); + + options.DefaultResourceType = typeof(CloudCrmWebResource); + }); + } +``` + +You can define new localization entries in the language files under the **Localization** folder and directly use them in your application by using the `IStringLocalizer<>` or `IHtmlLocalizer<>` services: + +```html +@page +@using Microsoft.Extensions.Localization +@inject IStringLocalizer L + +
    +

    @L["LongWelcomeMessage"]

    +
    +``` + +### Angular UI + +Angular UI gets the localization resources from the [`application-localization`](../../framework/api-development/standard-apis/localization.md) API's response and merges these resources in the `ConfigStateService` for the localization entries/resources coming from the backend side. + +In addition, you may need to define some localization entries and only use them on the UI side. ABP already provides the related configuration for you, so you don't need to make any configurations related to that and instead you can directly define localization entries in the `app.-module.ts` file of your angular application as follows: + +```ts +import { provideAbpCore, withOptions } from '@abp/ng.core'; + +@NgModule({ + providers: [ + // ... + provideAbpCore( + withOptions({ + environment, + registerLocaleFn: registerLocale(), + localizations: [ + { + culture: 'en', + resources: [ + { + resourceName: 'MyProjectName', + texts: { + "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information visit" + } + } + ] + } + ] + }), + ), + ... + ], +}) +export class AppModule {} + +``` + +After defining the localization entries, it can be used as below: + +{%{ +```html +
    {{ 'MyProjectName::LongWelcomePage' | abpLocalization }}
    +``` +}%} + +> For more information, please refer to [UI Localization section of the Angular Localization document](../../framework/ui/angular/localization.md). + ## Creating a New Localization Resource To create a new localization resource, you can create a class named *MicroservicenameResource* in the *Contracts* project for the related microservice, which is already created by the solution template. For example, the *Identity* microservice has an *IdentityServiceResource* class and localization JSON files. @@ -61,4 +173,4 @@ public override void ConfigureServices(ServiceConfigurationContext context) } ``` -> Existing microservices in the solution don't contain the localization text. These localization resources are defined in their own modules. You can add new localization resources to the existing microservices by following the steps above. \ No newline at end of file +> Existing microservices in the solution don't contain the localization text. These localization resources are defined in their own modules. You can add new localization resources to the existing microservices by following the steps above. diff --git a/docs/en/solution-templates/single-layer-web-application/index.md b/docs/en/solution-templates/single-layer-web-application/index.md index 5984ffa70a..d5720f5602 100644 --- a/docs/en/solution-templates/single-layer-web-application/index.md +++ b/docs/en/solution-templates/single-layer-web-application/index.md @@ -1,66 +1,15 @@ # Single Layer Application Solution Template -## Introduction - This template provides a simple solution structure with a single project. This document explains that solution structure in details. -### The Difference Between the Application Solution Templates - -ABP's [Layered Application Solution Template](../layered-web-application) provides a well-organized and layered solution to create maintainable business applications based on the [Domain Driven Design](../../framework/architecture/domain-driven-design) (DDD) practices. However, some developers find this template a little bit complex for simple and short-term applications. The single-layer application template has been created to provide a simpler development model for such applications. This template has the same functionality, features and modules on runtime with the [Layered Application Solution Template](../layered-web-application) but the development model is minimal and everything is in a single project (`.csproj`). - -## How to Start with It? - -You can use the [ABP CLI](../../cli) to create a new project using this startup template. Alternatively, you can generate a CLI command for this startup template from the [Get Started](https://abp.io/get-started) page. In this section, we will use the ABP CLI. - -Firstly, install the ABP CLI if you haven't installed it before: - -```bash -dotnet tool install -g Volo.Abp.Studio.Cli -``` - -Then, use the `abp new` command in an empty folder to create a new solution: - -```bash -abp new Acme.BookStore -t app-nolayers -``` - -* `Acme.BookStore` is the solution name, like *YourCompany.YourProduct*. You can use single-level, two-level or three-level naming. -* In this example, the `-t` (or `--template`) option specifies the template name. - -### Specify the UI Framework +## Getting Started -This template provides multiple UI frameworks: - -* `mvc`: ASP.NET Core MVC UI with Razor Pages (default) -* `blazor`: Blazor UI -* `blazor-server`: Blazor Server UI -* `angular`: Angular UI -* `none`: Without UI (for HTTP API development) - -Use the `-u` (or `--ui`) option to specify the UI framework while creating the solution: - -```bash -abp new Acme.BookStore -t app-nolayers -u angular -``` - -This example specifies the UI type (the `-u` option) as `angular`. You can also specify `mvc`, `blazor`, `blazor-server` or `none` for the UI type. - -### Specify the Database Provider - -This template supports the following database providers: - -- `ef`: Entity Framework Core (default) -- `mongodb`: MongoDB - -Use the `-d` (or `--database-provider`) option to specify the database provider while creating the solution: - -```bash -abp new Acme.BookStore -t app-nolayers -d mongodb -``` +* Follow the [Getting Started guide](../../get-started/single-layer-web-application.md) to create a new solution using this startup solution template. +* Follow the [TODO application tutorial](../../tutorials/todo/single-layer/index.md) to learn how to create a simple application with this startup solution template. -## Solution Structure +## The Solution Structure -If you don't specify any additional options while creating an `app-nolayers` template, you will have a solution as shown below: +If you created your solution with the default options, you will have a .NET solution as shown below: ![](../../images/bookstore-single-layer-solution-structure.png) diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md index 7d5575786b..31e5bbdfcf 100644 --- a/docs/en/studio/release-notes.md +++ b/docs/en/studio/release-notes.md @@ -2,13 +2,81 @@ This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version. +## 0.9.13 (2024-11-25) + +* Angular - Theme-based Fixes for the Home Page. + +## 0.9.12 (2024-11-25) + +* Handled the `DynamicPermissionDefinitionsChangedEto` event to automatically add permissions for the admin role. +* Enhanced the Solution Configuration window with a more intuitive design and updated content. +* Improved MAUI application support by displaying all target frameworks in the Solution Runner and automatically setting the appropriate targetFramework based on the operating system. + +## 0.9.11 (2024-11-21) + +* Fixed the extension loading problem occured in v0.9.9 & v0.9.10. + +## 0.9.10 (2024-11-21) + +> Recommended to use v0.9.11+ for .NET 9. + +* Added shortcut for Build & Start operation (CTRL + Click) +* Fixed extension loading loop problem in v0.9.9 +* Fixed MAUI template for android + +## 0.9.9 (2024-11-21) + +> Recommended to use v0.9.11+ for .NET 9. + +* Upgraded templates to .NET 9 +* Fixed blazor wasm bundle problem in microservice template + +## 0.9.8 (2024-11-20) + +* Upgraded templates to version `8.3.4` + +## 0.9.7 (2024-11-19) + +* Added `AppearanceStyles` component to blazor server templates +* Fixed module import window +* Made several enhancements to the existing features + +## 0.9.6 (2024-11-15) + +* Added missing imports to templates +* Fixed bugs during EF Core package installation +* Show errors to the user when adding a database migration +* Changed empty solution description on create new solution wizard +* Fixed problems with templates created with Basic Theme +* Ensure the correct version is used when adding a new module/package to an existing solution + +## 0.9.5 (2024-11-06) + +* Added dynamic localization option to microservice template +* Added new template creation options for the Application (No Layers) +* Fixed the environment variable setting for .NET global tool and verification of tool installation +* Fixed log view auto-scrolling issue, ensuring smooth scrolling experience +* Upgraded templates to version `8.3.3` + +## 0.9.4 (2024-10-31) + +* Made the `TopMenuLayout` as the default layout type for microservice public website +* Fixed application crashing problem when the ABP Suite is opened + +## 0.9.3 (2024-10-30) + +* Added the **standard module template** +* Made enhancements on the pre-integrated browser +* Fixed Blazor WebAssembly UI being not run on kubernetes problem +* Added a database migration after a module added to the solution + ## 0.9.2 (2024-10-22) -* Added "Sample CRUD Page" option for pro templates -* Generated *Signing-Certificate* for appnolayers template +* Added a status bar to the pre-integrated browser for showing errors +* Added **Sample CRUD Page** option to pro templates * Added test projects optionally for all templates -* Added automapper configuration to apps/web project for ms template -* Disabled *transaction* for `MongoDB` and `SQLite` by default +* Added **AutoMapper** configurations to microservice host projects +* Disabled **transaction** for *MongoDB* & *SQLite* by default. ## 0.9.1 (2024-10-10) diff --git a/docs/en/studio/running-applications.md b/docs/en/studio/running-applications.md index a41f15207d..a4dc4f8388 100644 --- a/docs/en/studio/running-applications.md +++ b/docs/en/studio/running-applications.md @@ -187,6 +187,8 @@ We have several options in C# applications. Those options are `Start`(If the app > When *Watch* is enable you should see an *eye* icon next to the application name. +> Hint: Performing CTRL+Click on the start icon left to a stopped C# application equals to `Build & Start` command. Same applies for folders. + ![csharp-application-context-menu-run-connection](images/solution-runner/csharp-application-context-menu-run-connection.png) ### Build diff --git a/docs/en/studio/version-compatibility.md b/docs/en/studio/version-compatibility.md deleted file mode 100644 index 8cfc373bcb..0000000000 --- a/docs/en/studio/version-compatibility.md +++ /dev/null @@ -1,19 +0,0 @@ -# ABP Studio and ABP Solution Templates Version Compatibility - -This document provides an overview of the compatibility between various versions of ABP Studio and [ABP Solution Templates](../solution-templates/index.md). Use this reference to ensure that you are using the correct versions of ABP Studio and ABP for your projects. - -| **ABP Studio Version** | **ABP Version** | -|------------------------|---------------------------| -| 0.9.2 | 8.3.2 | -| 0.8.4 - 0.9.1 | 8.3.1 | -| 0.8.1 to 0.8.3 | 8.3.0 | -| 0.8.0 | 8.2.3 | -| 0.7.8 - 0.7.9 | 8.2.2 | -| 0.7.4 to 0.7.7 | 8.2.1 | -| 0.7.0 to 0.7.3 | 8.2.0 | -| 0.6.8 - 0.6.9 | 8.1.3 | -| 0.6.7 | 8.1.1 | - -By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: - -![](images/abp-studio-switch-to-preview.png) \ No newline at end of file diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md new file mode 100644 index 0000000000..64ba3c1fb2 --- /dev/null +++ b/docs/en/studio/version-mapping.md @@ -0,0 +1,24 @@ +# ABP Studio and ABP Startup Template Version Mappings + +This document provides a general overview of the relationship between various versions of ABP Studio and the ABP version of the [ABP Solution Templates](../solution-templates/index.md) used when generating a new solution. Each version of ABP Studio is configured to create solutions with a specific ABP version. However, once a solution is created, you can easily update it to the latest version of ABP via ABP Studio or [ABP CLI](../cli/index.md#update). + +| **ABP Studio Version** | **ABP Version of Startup Template** | +|------------------------|---------------------------| +| 0.9.9 to 0.9.13 | 9.0.0 | +| 0.9.8 | 8.3.4 | +| 0.9.5 to 0.9.7 | 8.3.3 | +| 0.9.2 to 0.9.4 | 8.3.2 | +| 0.8.4 - 0.9.1 | 8.3.1 | +| 0.8.1 to 0.8.3 | 8.3.0 | +| 0.8.0 | 8.2.3 | +| 0.7.8 - 0.7.9 | 8.2.2 | +| 0.7.4 to 0.7.7 | 8.2.1 | +| 0.7.0 to 0.7.3 | 8.2.0 | +| 0.6.8 - 0.6.9 | 8.1.3 | +| 0.6.7 | 8.1.1 | + +# Working with ABP's Preview Versions + +By default, ABP Studio uses stable versions to create solutions. Therefore, if you want to create a solution with a preview version, first you need to create a solution and then switch your solution to the preview version from the ABP Studio UI: + +![](images/abp-studio-switch-to-preview.png) diff --git a/docs/en/suite/generating-crud-page.md b/docs/en/suite/generating-crud-page.md index e1461e3d0a..00c5ca07a2 100644 --- a/docs/en/suite/generating-crud-page.md +++ b/docs/en/suite/generating-crud-page.md @@ -273,7 +273,7 @@ Alternatively, you can add `IdentityUser` entity (or any other entity) as a navi ### New book dialog -###### ![New book dialog](../images/suite-ui-new-book.png) +### ![New book dialog](../images/suite-ui-new-book.png) ### Book list page diff --git a/docs/en/tutorials/book-store/part-01.md b/docs/en/tutorials/book-store/part-01.md index 8f1d5df346..a808c36034 100644 --- a/docs/en/tutorials/book-store/part-01.md +++ b/docs/en/tutorials/book-store/part-01.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` @@ -36,7 +36,7 @@ abp install-libs > We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet. -{{if UI=="Blazor" || UI=="BlazorServer"}} +{{if UI=="Blazor" || UI=="BlazorWebApp"}} ### Bundling and Minification @@ -440,7 +440,7 @@ ABP can [**automagically**](../../framework/api-development/auto-controllers.md) ### Swagger UI -The startup template is configured to run the [Swagger UI](https://swagger.io/tools/swagger-ui/) using the [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) library. Run the application ({{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer"}}`Acme.BookStore.Blazor`{{else}}`Acme.BookStore.HttpApi.Host`{{end}}) by pressing `CTRL+F5` and navigate to `https://localhost:/swagger/` on your browser. Replace `` with your own port number. +The startup template is configured to run the [Swagger UI](https://swagger.io/tools/swagger-ui/) using the [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) library. Run the application ({{if UI=="MVC"}}`Acme.BookStore.Web`{{else if UI=="BlazorServer" || UI=="BlazorWebApp"}}`Acme.BookStore.Blazor`{{else}}`Acme.BookStore.HttpApi.Host`{{end}}) by pressing `CTRL+F5` and navigate to `https://localhost:/swagger/` on your browser. Replace `` with your own port number. You will see some built-in service endpoints as well as the `Book` service and its REST-style endpoints: @@ -480,4 +480,4 @@ If you try to execute the `[GET] /api/app/book` API to get a list of books, the } ```` -That's pretty cool since we haven't written a single line of code to create the API controller, but now we have a fully working REST API! \ No newline at end of file +That's pretty cool since we haven't written a single line of code to create the API controller, but now we have a fully working REST API! diff --git a/docs/en/tutorials/book-store/part-02.md b/docs/en/tutorials/book-store/part-02.md index df5a5ac598..bb812e7d81 100644 --- a/docs/en/tutorials/book-store/part-02.md +++ b/docs/en/tutorials/book-store/part-02.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp", "NG"], "DB": ["EF","Mongo"] } ```` @@ -514,13 +514,13 @@ Now you can see the final result on your browser: ![Book list final result](images/bookstore-book-list-angular.png) -{{else if UI == "Blazor" || UI == "BlazorServer"}} +{{else if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}} ## Create a Books Page -It's time to create something visible and usable! Right click on the `Pages` folder under the {{ if UI == "Blazor"}}`Acme.BookStore.Blazor.Client`{{ else }}`Acme.BookStore.Blazor`{{ end }} project and add a new **razor component**, named `Books.razor`: +It's time to create something visible and usable! Right click on the `Pages` folder under the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add a new **razor component**, named `Books.razor`: -{{ if UI == "Blazor"}} +{{ if UI == "Blazor" || UI == "BlazorWebApp" }} ![blazor-add-books-component](images/blazor-add-books-component-client.png) {{ else }} ![blazor-add-books-component](images/blazor-add-books-component.png) @@ -540,7 +540,7 @@ Replace the contents of this component as shown below: ### Add the Books Page to the Main Menu -Open the `BookStoreMenuContributor` class in the {{ if UI == "Blazor"}}`Acme.BookStore.Blazor.Client`{{ else }}`Acme.BookStore.Blazor`{{ end }} project add the following code to the end of the `ConfigureMainMenuAsync` method: +Open the `BookStoreMenuContributor` class in the {{ if UI == "BlazorServer"}}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project add the following code to the end of the `ConfigureMainMenuAsync` method: ````csharp context.Menu.AddItem( diff --git a/docs/en/tutorials/book-store/part-03.md b/docs/en/tutorials/book-store/part-03.md index a770d62f29..65f6d482dd 100644 --- a/docs/en/tutorials/book-store/part-03.md +++ b/docs/en/tutorials/book-store/part-03.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` @@ -1101,7 +1101,7 @@ Clicking the "Delete" action calls the `delete` method which then shows a confir {{end}} -{{if UI == "Blazor" || UI == "BlazorServer"}} +{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}} ## Creating a New Book @@ -1292,13 +1292,13 @@ We can now define a modal to edit the book. Add the following code to the end of The base `AbpCrudPageBase` uses the [object to object mapping](../../framework/infrastructure/object-to-object-mapping.md) system to convert an incoming `BookDto` object to a `CreateUpdateBookDto` object. So, we need to define the mapping. -Open the `BookStoreBlazorAutoMapperProfile` inside the `Acme.BookStore.Blazor.Client` project and change the content as the following: +Open the `BookStoreBlazorAutoMapperProfile` inside the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and change the content as the following: ````csharp using Acme.BookStore.Books; using AutoMapper; -namespace Acme.BookStore.Blazor.Client; +{{ if UI == "BlazorServer" }}namespace Acme.BookStore.Blazor;{{ else }}namespace Acme.BookStore.Blazor.Client;{{ end }} public class BookStoreBlazorAutoMapperProfile : Profile { diff --git a/docs/en/tutorials/book-store/part-04.md b/docs/en/tutorials/book-store/part-04.md index b529748efb..4ab950b0e1 100644 --- a/docs/en/tutorials/book-store/part-04.md +++ b/docs/en/tutorials/book-store/part-04.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-05.md b/docs/en/tutorials/book-store/part-05.md index 947eec65f0..95ee1f53a6 100644 --- a/docs/en/tutorials/book-store/part-05.md +++ b/docs/en/tutorials/book-store/part-05.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` @@ -389,11 +389,11 @@ Open the `/src/app/book/book.component.html` file and replace the edit and delet * Added `*abpPermission="'BookStore.Books.Edit'"` that hides the edit action if the current user has no editing permission. * Added `*abpPermission="'BookStore.Books.Delete'"` that hides the delete action if the current user has no delete permission. -{{else if UI == "Blazor"}} +{{else if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}} ### Authorize the Razor Component -Open the `/Pages/Books.razor` file in the `Acme.BookStore.Blazor.Client` project and add an `Authorize` attribute just after the `@page` directive and the following namespace imports (`@using` lines), as shown below: +Open the `/Pages/Books.razor` file in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add an `Authorize` attribute just after the `@page` directive and the following namespace imports (`@using` lines), as shown below: ````html @page "/books" @@ -479,7 +479,7 @@ You can run and test the permissions. Remove a book related permission from the Even we have secured all the layers of the book management page, it is still visible on the main menu of the application. We should hide the menu item if the current user has no permission. -Open the `BookStoreMenuContributor` class in the `Acme.BookStore.Blazor.Client` project, find the code block below: +Open the `BookStoreMenuContributor` class in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project, find the code block below: ````csharp context.Menu.AddItem( diff --git a/docs/en/tutorials/book-store/part-06.md b/docs/en/tutorials/book-store/part-06.md index a19248ec64..58a83cfc16 100644 --- a/docs/en/tutorials/book-store/part-06.md +++ b/docs/en/tutorials/book-store/part-06.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer", "BlazorWebApp", "NG"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-07.md b/docs/en/tutorials/book-store/part-07.md index 70d73da97b..b8aa17ace8 100644 --- a/docs/en/tutorials/book-store/part-07.md +++ b/docs/en/tutorials/book-store/part-07.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-08.md b/docs/en/tutorials/book-store/part-08.md index 61412ba770..679b6d84ca 100644 --- a/docs/en/tutorials/book-store/part-08.md +++ b/docs/en/tutorials/book-store/part-08.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` diff --git a/docs/en/tutorials/book-store/part-09.md b/docs/en/tutorials/book-store/part-09.md index d1c446bc3f..3c1b0cb7d5 100644 --- a/docs/en/tutorials/book-store/part-09.md +++ b/docs/en/tutorials/book-store/part-09.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` @@ -848,13 +848,13 @@ That's all! This is a fully working CRUD page, you can create, edit and delete a {{end}} -{{if UI == "Blazor" || UI == "BlazorServer"}} +{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp"}} ## The Author Management Page ### Authors Razor Component -Create a new Razor Component Page, `/Pages/Authors.razor`, in the `Acme.BookStore.Blazor.Client` project with the following content: +Create a new Razor Component Page, `/Pages/Authors.razor`, in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project with the following content: ````xml @page "/authors" @@ -1055,7 +1055,7 @@ using Blazorise.DataGrid; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; -namespace Acme.BookStore.Blazor.Client.Pages; +{{ if UI == "BlazorServer" }}namespace Acme.BookStore.Blazor.Pages;{{ else }}namespace Acme.BookStore.Blazor.Client.Pages;{{ end }} public partial class Authors { @@ -1201,7 +1201,7 @@ This class typically defines the properties and methods used by the `Authors.raz `Authors` class uses the `IObjectMapper` in the `OpenEditAuthorModal` method. So, we need to define this mapping. -Open the `BookStoreBlazorAutoMapperProfile.cs` in the `Acme.BookStore.Blazor.Client` project and add the following mapping code in the constructor: +Open the `BookStoreBlazorAutoMapperProfile.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following mapping code in the constructor: ````csharp CreateMap(); @@ -1211,7 +1211,7 @@ You will need to declare a `using Acme.BookStore.Authors;` statement to the begi ### Add to the Main Menu -Open the `BookStoreMenuContributor.cs` in the `Acme.BookStore.Blazor.Client` project and add the following code to the end of the `ConfigureMainMenuAsync` method: +Open the `BookStoreMenuContributor.cs` in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following code to the end of the `ConfigureMainMenuAsync` method: ````csharp if (await context.IsGrantedAsync(BookStorePermissions.Authors.Default)) diff --git a/docs/en/tutorials/book-store/part-10.md b/docs/en/tutorials/book-store/part-10.md index 5a6acb752b..928881ffec 100644 --- a/docs/en/tutorials/book-store/part-10.md +++ b/docs/en/tutorials/book-store/part-10.md @@ -2,7 +2,7 @@ ````json //[doc-params] { - "UI": ["MVC","Blazor","BlazorServer","NG"], + "UI": ["MVC","Blazor","BlazorServer","BlazorWebApp","NG"], "DB": ["EF","Mongo"] } ```` @@ -1071,11 +1071,11 @@ That's all. Just run the application and try to create or edit an author. {{end}} -{{if UI == "Blazor" || UI == "BlazorServer"}} +{{if UI == "Blazor" || UI == "BlazorServer" || UI == "BlazorWebApp" }} ### The Book List -It is very easy to show the *Author Name* in the book list. Open the `/Pages/Books.razor` file in the `Acme.BookStore.Blazor.Client` project and add the following `DataGridColumn` definition just after the `Name` (book name) column: +It is very easy to show the *Author Name* in the book list. Open the `/Pages/Books.razor` file in the {{ if UI == "BlazorServer" }}`Acme.BookStore.Blazor`{{ else }}`Acme.BookStore.Blazor.Client`{{ end }} project and add the following `DataGridColumn` definition just after the `Name` (book name) column: ````xml This tutorial is suitable for those who have an ABP Business or a higher [license](https://abp.io/pricing). + +ABP is designed to be a powerful platform to build microservice solutions. It provides a [microservice solution template](../../solution-templates/microservice/index.md) to easily start a sophisticated microservice solution. All of the [pre-built application modules](../../modules/index.md) are microservice compatible and the core framework fully [supports and simplifies](../../framework/architecture/microservices/index.md) distributed application development. + +In this tutorial, you will learn how to start a new microservice solution, create services and communicate between them. You will also learn to use these services from a web application through an API gateway and automatically generate CRUD pages using the [ABP Suite](../../suite/index.md) tool. + +## Tutorial Outline + +This tutorial is organized as the following parts: + +* [Part 01: Creating the initial solution](part-01.md) +* [Part 02: Creating the initial Catalog microservice](part-02.md) +* [Part 03: Building the Catalog microservice](part-03.md) +* [Part 04: Creating the initial Ordering service](part-04.md) +* [Part 05: Building the Ordering service](part-05.md) +* [Part 06: Integrating the services: HTTP API Calls](part-06.md) +* [Part 07: Integrating the services: Using Distributed Events](part-07.md) + +## Download the Source Code + +After logging in to the ABP website, you can download the source code from [here](https://abp.io/api/download/samples/cloud-crm-mvc-ef). + +## See Also + +* [Microservice solution template](../../solution-templates/microservice/index.md) \ No newline at end of file diff --git a/docs/en/tutorials/microservice/part-01.md b/docs/en/tutorials/microservice/part-01.md new file mode 100644 index 0000000000..d843e744ca --- /dev/null +++ b/docs/en/tutorials/microservice/part-01.md @@ -0,0 +1,40 @@ +# Microservice Tutorial Part 01: Creating the Initial Solution + +````json +//[doc-nav] +{ + "Next": { + "Name": "Creating the initial Catalog service", + "Path": "tutorials/microservice/part-02" + } +} +```` + +Follow the *[Get Started](../../get-started/microservice.md)* guide to create a new layered web application with the following configurations: + +* **Solution name**: `CloudCrm` +* **Database Provider**: Entity Framework Core +* **Database Management System**: SQL Server +* **UI Framework**: MVC / Razor Pages +* **Mobile framework**: None +* **Public website**: Selected + +You can select the other options based on your preference. + +> **Please complete the *[Get Started](../../get-started/layered-web-application.md)* guide and run the web application before going further.** You can skip the sections after the *Running the Solution* section, if you don't prefer to complete all. + +The initial solution structure should be like the following in ABP Studio's *[Solution Explorer](../../studio/solution-explorer.md)*: + +![abp-studio-solution-explorer-initial-cloud-crm-microservice-solution](images/abp-studio-solution-explorer-initial-cloud-crm-microservice-solution.png) + +> ABP Studio will perform a few additional steps after creating your solution. **Please wait until all the background tasks are completed** before going further. + +Initially you see three folders (`apps`, `gateways` and `services`) and ~10 ABP Studio modules (depends on your preferences while creating the solution) under the `CloudCrm` ABP Studio solution. Some of these modules represent microservices, some of them represent web applications and some others represent API gateways in our system. + +> An **ABP Studio module** is typically a .NET solution and an **ABP Studio solution** is an umbrella concept for multiple .NET Solutions (see the *[Concepts](../../studio/concepts.md)* document for more). + +You can see the *[Microservice Solution Template](../../solution-templates/microservice/index.md)* document later if you want to understand the initial solution structure with all its details. However, it is not needed to follow this tutorial. + +## Summary + +In this part, you've created the initial microservice solution, which already contains a few infrastructure services. We will create our first business service in the [next part](part-02.md). \ No newline at end of file diff --git a/docs/en/tutorials/microservice/part-02.md b/docs/en/tutorials/microservice/part-02.md new file mode 100644 index 0000000000..014daf9b11 --- /dev/null +++ b/docs/en/tutorials/microservice/part-02.md @@ -0,0 +1,123 @@ +# Microservice Tutorial Part 02: Creating the initial Catalog service + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Creating the initial solution", + "Path": "tutorials/microservice/part-01" + }, + "Next": { + "Name": "Building the Catalog service", + "Path": "tutorials/microservice/part-03" + } +} +```` + +In this tutorial, you will create a new Catalog service and integrate it to the solution. + +## Creating the Catalog Service + +Right-click the `services` folder in the *Solution Explorer* panel, select the *Add* -> *New Module* -> *Microservice* command: + +![abp-studio-add-new-microservice-command](images/abp-studio-add-new-microservice-command.png) + +This command opens a new dialog to define the properties of the new microservice. You can use the following values to create a new microservice named `CatalogService`: + +![abp-studio-add-new-microservice-dialog](images/abp-studio-add-new-microservice-dialog.png) + +When you click the *Next* button, you are redirected to the database provider selection step. + +### Selecting the Database Type + +Here, you can select the database provider to be used by the new microservice: + +![abp-studio-add-new-microservice-dialog-database-step](images/abp-studio-add-new-microservice-dialog-database-step.png) + +Select *Entity Framework Core* option and proceed the *Next* step. + +### Integrating to the Solution + +In this step, we can select the options for integrating the new microservice to the rest of the solution components: + +![abp-studio-add-new-microservice-dialog-integration-step](images/abp-studio-add-new-microservice-dialog-integration-step.png) + +ABP Studio intelligently selects the right values for you, but you should still check them carefully since they directly affect what we will do in the next parts of this tutorial. + +**Ensure the options are configured the same as in the preceding figure**, and click the *Next* button. + +### Additional Options + +![abp-studio-add-new-microservice-dialog-additional-options-step](images/abp-studio-add-new-microservice-dialog-additional-options-step.png) + +In this step, you can select additional options for the new microservice. You can leave them as default and click the *Create* button. + +That's all, ABP Studio creates the new microservice and arranges all the integration and configuration for you. + +## Exploring the New Catalog Microservice + +In this section, we will investigate the new microservice in overall. + +### Understanding the Packages of The Service + +The new microservice is added under the `services` folder in the `CloudCrm` ABP Studio solution: + +![abp-studio-new-catalog-service-in-solution-explorer](images/abp-studio-new-catalog-service-in-solution-explorer.png) + +The new microservice has its own separate .NET solution that includes three packages (.NET projects): + +* `CloudCrm.CatalogService` is the main project that you will implement your service. It typically contains your [entities](../../framework/architecture/domain-driven-design/entities.md), [repositories](../../framework/architecture/domain-driven-design/repositories.md), [application services](../../framework/architecture/domain-driven-design/application-services.md), API controllers, etc. +* `CloudCrm.CatalogService.Contracts` project can be shared with the other services and applications. It typically contains interfaces of your [application services](../../framework/architecture/domain-driven-design/application-services.md), [data transfer objects](../../framework/architecture/domain-driven-design/data-transfer-objects.md), and some other types you may want to share with the clients of this microservice. +* `CloudCrm.CatalogService.Tests` is for building your unit and integration tests for this microservice. + +### Opening the Service in an IDE + +You can open the new microservice in your favorite IDE for development. As a shortcut, you can right-click it in ABP Studio, select the *Open with* -> *Visual Studio* command for example: + +![abp-studio-open-with-visual-studio](images/abp-studio-open-with-visual-studio.png) + +Here is the `CloudCrm.CatalogService` .NET solution in Visual Studio: + +![visual-studio-solution-explorer-catalog-service](images/visual-studio-solution-explorer-catalog-service.png) + +### Running the New Service + +You can run the solution using ABP Studio's *Solution Runner*. It will also run the new Catalog service as a part of the solution. + +> Before running the solution, **ensure that all the applications are built**. If you are not sure, right-click the root item (`CloudCrm`) in the *Solution Explorer* panel and select the *Build* -> *Graph Build* command. + +Click the *Play* button near to the solution root: + +![abp-studio-solution-runner-play-all](images/abp-studio-solution-runner-play-all.png) + +### Browsing the Catalog Service + +Once all of the applications have started, right-click the Catalog service and select the *Browse* command: + +![abp-studio-browse-catalog-service](images/abp-studio-browse-catalog-service.png) + +It will open the built-in browser and you will see the Swagger UI for the Catalog service: + +![abp-studio-browser-catalog-service-swagger-ui](images/abp-studio-browser-catalog-service-swagger-ui.png) + +You can test the APIs on the Swagger UI to see if the new microservice is properly working. + +### Opening the Catalog Database + +The new Catalog microservice has its own database. That database is created automatically by the microservice application, when you run the microservice. Also, [Entity Framework's database migrations](https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/) are automatically applied by the microservice when it runs. So, you don't care about the database schema changes every time you deploy the microservice. + +Assuming you've selected SQL Server as your DBMS, you can open the SQL Server Management Studio to see its databases: + +![sql-server-management-studio-login-screen](images/sql-server-management-studio-login-screen.png) + +Use `localhost,1434` as the *Server name*, select the *SQL Server Authentication* as the *Authentication* type, use `sa` as the *Login* name and `myPassw@rd` as the *Password* value. You can find these values in the `appsettings.json` file in the `CloudCrm.CatalogService` project of the .NET solution of the Catalog microservice. + +Once you click the *Connect* button, you can see all the databases and explore their data: + +![sql-server-management-studio-databases](images/sql-server-management-studio-databases.png) + +The Catalog service's database has only three initial table. The first one is for Entity Framework Core's migration system, and the others are for ABP's [distributed event bus](../../solution-templates/microservice/distributed-events.md) to properly apply transactional events using the outbox and inbox patterns. You don't need to care about these tables since they are created and managed by Entity Framework Core and ABP. + +## Summary + +In this part of the Microservice Development Tutorial, we added a new Catalog microservice to the solution, explored its code structure and database, and browse its APIs using the Swagger UI. In the next part, we will create functionality in that new microservice. \ No newline at end of file diff --git a/docs/en/tutorials/microservice/part-03.md b/docs/en/tutorials/microservice/part-03.md new file mode 100644 index 0000000000..31491ef004 --- /dev/null +++ b/docs/en/tutorials/microservice/part-03.md @@ -0,0 +1,126 @@ +# Microservice Tutorial Part 03: Building the Catalog service + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Creating the initial Catalog service", + "Path": "tutorials/microservice/part-02" + }, + "Next": { + "Name": "Creating the initial Ordering service", + "Path": "tutorials/microservice/part-04" + } +} +```` + +In the previous part, we've created a new microservice named Catalog. In this part, we will build functionality to create and manage products in our system. + +In this part, we will use [ABP Suite](../../suite/index.md) to automatically create all the necessary code for us. So, you will see how to use ABP Suite in a microservice solution. We will do everything manually while we will create the Ordering microservice in next parts, so you will learn the details better. We suggest to use ABP Suite wherever it is possible, because it saves a lot of time. You can then investigate the changes done by ABP Suite to understand what it produced. + +## Opening the ABP Suite + +First of all, **stop all the applications** in ABP Studio's *Solution Runner* panel, because ABP Suite will make changes in the solution and it will also needs to build the solution in some steps. Running the solution prevents to build it. + +Now, select the *ABP Suite* -> *Open* command on the main menu to open ABP Suite: + +![abp-studio-open-abp-suite](images/abp-studio-open-abp-suite.png) + +It will ask to you which module you want to use: + +![abp-studio-open-abp-suite-select-module](images/abp-studio-open-abp-suite-select-module.png) + +The `CloudCrm` microservice solution contains more than one .NET solution. Typically, each ABP Studio module represents a separate .NET solution (see the [concepts](../../studio/concepts.md) document). ABP Suite works on a single .NET solution to generate code, so we should select a module here. + +Select the `CloudCrm.CatalogService` module and click the *OK* button. It will open ABP Suite as shown below: + +![abp-studio-abp-suite-inside](images/abp-studio-abp-suite-inside.png) + +## Generating a Products Page + +In the next section, we will use ABP Suite to create a fully functional CRUD page with ABP Suite. The UI part will be in the main web application (`CloudCrm.Web`) and the application service and other parts will be generated in the Catalog microservice. + +### Configuring the Product Entity Information + +Type `Product` for the *Name* field and leave the other options as is. ABP Suite will automatically calculate proper values for you: + +![abp-suite-product-info](images/abp-suite-product-info.png) + +### Configuring Properties of the Product Entity + +Open the *Properties* tab and create the properties shown in the following figure: + +![abp-suite-product-properties](images/abp-suite-product-properties.png) + +Here the details: + +* `Name` is required, minimum length is `2` and maximum length is `120`. +* `Description` is not required, it is a *Text area*, not *Filterable*, not *Shown on the list page*. +* `StockCount` has a *Default value* `0`, minimum value `0` and maximum value `999999`. +* `ReleaseDate` is *Nullable*. + +You can leave the other configurations as default. + +### Generating the Code + +![abp-suite-product-generating.png](images/abp-suite-product-generating.png) + +That's all. You can click the *Save and generate* button to start the code generation process. + +![abp-suite-product-generated](images/abp-suite-product-generated.png) + +ABP Suite will generate the necessary code for you. It will take some time to complete the process. After the process is completed, you will see a success message, click the *OK* button. + +![abp-studio-catalog-service-build-and-start](images/abp-studio-catalog-service-build-and-start.png) + +We can now build and start the `CloudCrm.CatalogService` application by clicking the *Run* -> *Build & Start* button in the *Solution Runner* panel. + +![abp-studio-browse-catalog-service-2](images/abp-studio-browse-catalog-service-2.png) + +After the application is started, you can right-click and [Browse](../../studio/running-applications.md#monitoring) on the `CloudCrm.CatalogService` application to open it in the ABP Studio's pre-integrated browser. You can see the *Products* controller in the Swagger UI. + +### Generating the UI Proxy + +Now, we need to generate the [Static API Proxy](../../framework/api-development/static-csharp-clients.md) for the *Web* project. Right-click the *CloudCrm.Web* [package](../../studio/concepts.md#package) and select the *ABP CLI* -> *Generate Proxy* -> *C#* command: + +![abp-studio-generate-proxy](images/abp-studio-generate-proxy.png) + +It will open the *Generate C# Proxies* window. Select the `CloudCrm.CatalogService` application, and it will automatically populate the *URL* field. Select the *catalog* module, set the service type to *application*, and check the *Without contracts* checkbox, as the `CloudCrm.Web` project already depends on the `CloudCrm.CatalogService.Contracts` package: + +![abp-studio-generate-proxy-window](images/abp-studio-generate-proxy-window.png) + +> To be able to select the *Application*, you must *Build & Start* the related application beforehand. You can start the application using [Solution Runner](../../studio/running-applications.md) as explained in the previous parts. + +Lastly, we need to configure the use of a static HTTP client for the `CatalogService` in the `CloudCrm.Web` project. Open the `CloudCrmWebModule.cs` file in the `Web` project and add the following line to the `ConfigureServices` method: + +```csharp +//... +using CloudCrm.CatalogService; + +public override void ConfigureServices(ServiceConfigurationContext context) +{ + // Code omitted for brevity + context.Services.AddStaticHttpClientProxies( + typeof(CloudCrmCatalogServiceContractsModule).Assembly); +} +``` + +### Running the Application + +Now, stop any application running in the *Solution Runner* panel, and then run the applications by clicking the *Run* -> *Build & Start All* button on the root item in the *Solution Runner* panel: + +![abp-studio-run-build-and-start-all](images/abp-studio-run-build-and-start-all.png) + +After the application is started, you can right-click and [Browse](../../studio/running-applications.md#monitoring) on the `CloudCrm.Web` application to open it in the ABP Studio's pre-integrated browser: + +![abp-studio-browse-cloud-crm-products](images/abp-studio-browse-cloud-crm-products.png) + +> If you can't see the *Products* menu item, you need to grant the `CatalogService` *Product* permission to the *admin* role. You can do this by navigating to *Identity Management* -> *Roles* and editing the *admin* role. Alternatively, you can restart the *CloudCrm.AdministrationService* application to automatically seed all permissions for the *admin* role. + +You can open the Sql Server Management Studio to see the created tables and data: + +![sql-server-management-studio-products](images/sql-server-management-studio-products.png) + +## Summary + +In this part, we've created a new entity named *Product* and generated the necessary code for it. We've also generated the UI proxy for the `CatalogService` application and configured the static HTTP client for it in the `Web` project. We've run the application and tested the *Products* page. \ No newline at end of file diff --git a/docs/en/tutorials/microservice/part-04.md b/docs/en/tutorials/microservice/part-04.md new file mode 100644 index 0000000000..50386ab8e1 --- /dev/null +++ b/docs/en/tutorials/microservice/part-04.md @@ -0,0 +1,97 @@ +# Microservice Tutorial Part 04: Creating the initial Ordering service + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Building the Catalog service", + "Path": "tutorials/microservice/part-03" + }, + "Next": { + "Name": "Building the Ordering service", + "Path": "tutorials/microservice/part-05" + } +} +```` + +In the previous part, we implemented the Catalog microservice functionality using ABP Suite. In this part, we will create the Ordering microservice, and the following part will cover implementing its functionality manually. + +## Creating the Ordering Microservice + +Right-click the `services` folder in the *Solution Explorer* panel, select the *Add* -> *New Module* -> *Microservice* command: + +![abp-studio-add-new-microservice-command](images/abp-studio-add-new-microservice-command-2.png) + +This command opens a new dialog to define the properties of the new microservice. You can use the following values to create a new microservice named `OrderingService`: + +![abp-studio-add-new-microservice-dialog](images/abp-studio-add-new-microservice-dialog-2.png) + +When you click the *Next* button, you are redirected to the database provider selection step. + +### Selecting the Database Type + +Here, you can select the database provider to be used by the new microservice: + +![abp-studio-add-new-microservice-dialog-database-step](images/abp-studio-add-new-microservice-dialog-database-step.png) + +Select *Entity Framework Core* option and proceed the *Next* step. + +### Integrating to the Solution + +In this step, we can select the options for integrating the new microservice to the rest of the solution components: + +![abp-studio-add-new-microservice-dialog-integration-step](images/abp-studio-add-new-microservice-dialog-integration-step.png) + +ABP Studio intelligently selects the right values for you, but you should still check them carefully since they directly affect what we will do in the next parts of this tutorial. + +**Ensure the options are configured the same as in the preceding figure**, and click the *Next* button. + +### Additional Options + +![abp-studio-add-new-microservice-dialog-additional-options-step](images/abp-studio-add-new-microservice-dialog-additional-options-step.png) + +In this step, you can select additional options for the new microservice. You can leave them as default and click the *Create* button. + +That's all, ABP Studio creates the new microservice and arranges all the integration and configuration for you. + +## Exploring the New Ordering Microservice + +In this section, we will investigate the new microservice in overall. + +### Understanding the Solution Structure + +Just like the Catalog microservice, the Ordering microservice is a .NET solution that contains multiple projects. You can see the solution structure in the *Solution Explorer* panel: + +![abp-studio-solution-explorer-ordering-microservice](images/abp-studio-solution-explorer-ordering-microservice.png) + +* `CloudCrm.OrderingService` is the main project that you will implement your service. It typically contains your [entities](../../framework/architecture/domain-driven-design/entities.md), [repositories](../../framework/architecture/domain-driven-design/repositories.md), [application services](../../framework/architecture/domain-driven-design/application-services.md), API controllers, etc. +* `CloudCrm.OrderingService.Contracts` project can be shared with the other services and applications. It typically contains interfaces of your [application services](../../framework/architecture/domain-driven-design/application-services.md), [data transfer objects](../../framework/architecture/domain-driven-design/data-transfer-objects.md), and some other types you may want to share with the clients of this microservice. +* `CloudCrm.OrderingService.Tests` is for building your unit and integration tests for this microservice. + +### Running the New Service + +You can run the solution using ABP Studio's *Solution Runner*. It will also run the new Ordering service as a part of the solution. + +> Before running the solution, **ensure that all the applications are built**. If you are not sure, right-click the root item (`CloudCrm`) in the *Solution Explorer* panel and select the *Build* -> *Graph Build* command. + +Click the *Play* button near to the solution root: + +![abp-studio-run-solution](images/abp-studio-run-solution.png) + +### Browsing the Ordering Service + +After the application is started, you can right-click and [Browse](../../studio/running-applications.md#monitoring) on the `CloudCrm.OrderingService` application to open it in the ABP Studio's pre-integrated browser. You can see the *Orders* controller in the Swagger UI: + +![abp-studio-browse-ordering-service](images/abp-studio-browse-ordering-service.png) + +### Opening the Ordering Database + +You can use the SQL Server Management Studio or any other tool to connect to the Ordering service's database. Use `localhost,1434` as the *Server name*, select the *SQL Server Authentication* as the *Authentication* type, use `sa` as the *Login* name and `myPassw@rd` as the *Password* value. You can find these values in the `appsettings.json` file in the `CloudCrm.OrderingService` project of the .NET solution of the Ordering microservice: + +![sql-server-management-studio-databases-2](images/sql-server-management-studio-databases-2.png) + +Similarly the Ordering service's database has only three initial table. The first one is for Entity Framework Core's migration system, and the others are for ABP's [distributed event bus](../../solution-templates/microservice/distributed-events.md) to properly apply transactional events using the outbox and inbox patterns. You don't need to care about these tables since they are created and managed by Entity Framework Core and ABP. + +## Summary + +In this part, we've created the initial Ordering microservice. We will implement its functionality in the next part. \ No newline at end of file diff --git a/docs/en/tutorials/microservice/part-05.md b/docs/en/tutorials/microservice/part-05.md new file mode 100644 index 0000000000..249cdc8890 --- /dev/null +++ b/docs/en/tutorials/microservice/part-05.md @@ -0,0 +1,430 @@ +# Microservice Tutorial Part 05: Building the Ordering service + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Creating the initial Ordering service", + "Path": "tutorials/microservice/part-04" + }, + "Next": { + "Name": "Integrating the services: HTTP API Calls", + "Path": "tutorials/microservice/part-06" + } +} +```` + +In the previous part, we created the Ordering microservice. In this part, we will implement the functionality of the Ordering microservice manually. We will not use ABP Suite to generate the code. Instead, we will create the necessary code step by step to understand the details better. + +## Creating the Order Entity + +We will start by creating the `Order` entity, which will represent an order in our system. We'll add this entity to the `CloudCrm.OrderingService` project. Create a new folder named `Entities` and add a class named `Order` inside it: + +```csharp +using CloudCrm.OrderingService.Enums; +using Volo.Abp.Domain.Entities.Auditing; + +namespace CloudCrm.OrderingService.Entities; + +public class Order : CreationAuditedAggregateRoot +{ + public Guid ProductId { get; set; } + public string CustomerName { get; set; } + public OrderState State { get; set; } +} +``` + +To keep this example simple, we allow users to include only a single product within an order. The `Order` entity inherits from the [CreationAuditedAggregateRoot<>](../../framework/architecture/domain-driven-design/entities.md) class. This class, provided by the ABP Framework, includes common properties like `Id`, `CreationTime`, `CreatorId`, etc. + +### Adding the OrderState Enum + +We also need to define the `OrderState` enum. In the `CloudCrm.OrderingService.Contracts` project, create a folder named `Enums` and add an `OrderState` enum inside it: + +```csharp +namespace CloudCrm.OrderingService.Enums; + +public enum OrderState : byte +{ + Placed = 0, + Delivered = 1, + Canceled = 2 +} +``` + +The final solution structure should look like this: + +![vs-ordering-entity](images/vs-ordering-entity.png) + +## Configuring the Database Mapping + +First, we need to add the `Order` entity to the `OrderingServiceDbContext` class. Open the `OrderingServiceDbContext` class in the `CloudCrm.OrderingService` project, located in the `Data` folder, and add the following code to the `DbSet` properties: + +```csharp +using CloudCrm.OrderingService.Entities; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.Data; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.DistributedEvents; +using Volo.Abp.EntityFrameworkCore.Modeling; + +namespace CloudCrm.OrderingService.Data; + +[ConnectionStringName(DatabaseName)] +public class OrderingServiceDbContext : + AbpDbContext, + IHasEventInbox, + IHasEventOutbox +{ + public const string DbTablePrefix = ""; + public const string DbSchema = null; + + public const string DatabaseName = "OrderingService"; + + public DbSet IncomingEvents { get; set; } + public DbSet OutgoingEvents { get; set; } + public DbSet Orders { get; set; } // NEW: ADD DBSET PROPERTY + + // Code omitted for brevity +} +``` + +Next, we need to configure the database mapping for the `Order` entity. We'll use the [EF Core Fluent API](https://docs.microsoft.com/en-us/ef/core/modeling/relational/tables) for this configuration. In the `OrderingServiceDbContext` class add the following code to the `OnModelCreating` method: + +```csharp +protected override void OnModelCreating(ModelBuilder builder) +{ + base.OnModelCreating(builder); + + builder.ConfigureEventInbox(); + builder.ConfigureEventOutbox(); + + builder.Entity(b => + { + // Configure table name + b.ToTable("Orders"); + + // Always call this method to set base entity properties + b.ConfigureByConvention(); + + // Properties of the entity + b.Property(q => q.CustomerName).IsRequired().HasMaxLength(120); + }); +} +``` + +In this code snippet, we configure the `Order` entity to use the `Orders` table in the database. We also specify that the `CustomerName` property is required and has a maximum length of 120 characters. + +### Add a Database Migration + +Now, we can add a new database migration. You can use Entity Framework Core's `Add-Migration` (or `dotnet ef migrations add`) terminal command, but in this tutorial, we will use ABP Studio's shortcut UI. + +Ensure that the solution has built. You can right-click the `CloudCrm.OrderingService` (under the `services` folder) on ABP Studio *Solution Explorer* and select the *Dotnet CLI* -> *Graph Build* command. + +Right-click the `CloudCrm.OrderingService` package and select the *EF Core CLI* -> *Add Migration* command: + +![abp-studio-add-entity-framework-core-migration](images/abp-studio-add-entity-framework-core-migration.png) + +The *Add Migration* command opens a new dialog to get a migration name: + +![abp-studio-entity-framework-core-add-migration-order](images/abp-studio-entity-framework-core-add-migration-order.png) + +Once you click the *OK* button, a new database migration class is added to the `Migrations` folder of the `CloudCrm.OrderingService` project: + +![visual-studio-new-migration-class](images/visual-studio-new-migration-class.png) + +The changes will be applied to the database during the next application startup. For more details, refer to the [database migrations on service startup](../../solution-templates/microservice/database-configurations.md#database-migrations-on-service-startup) section. + +## Creating the Application Service + +Now, we will create the application service to manage the `Order` entity. + +### Defining the Application Service Contract + +First, we need to define the application service contract under the `CloudCrm.OrderingService.Contracts` project. Return to your IDE, open the `CloudCrm.OrderingService` module's .NET solution and create an `IOrderAppService` interface under the `Services` folder for the `CloudCrm.OrderingService.Contracts` project: + +```csharp +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace CloudCrm.OrderingService.Services; + +public interface IOrderAppService : IApplicationService +{ + Task> GetListAsync(); + Task CreateAsync(OrderCreationDto input); +} +``` + +### Defining the Data Transfer Objects + +Next, we need to define the data transfer objects (DTOs) for the `Order` entity. The `GetListAsync` and `CreateAsync` methods will use these DTOs to communicate with the client applications. + +Create a `OrderCreationDto` class under the `Services` folder in the `CloudCrm.OrderingService.Contracts` project: + +```csharp +using System; +using System.ComponentModel.DataAnnotations; + +namespace CloudCrm.OrderingService.Services; + +public class OrderCreationDto +{ + [Required] + [StringLength(150)] + public string CustomerName { get; set; } + + [Required] + public Guid ProductId { get; set; } +} +``` + +Create a `OrderDto` class under the `Services` folder in the `CloudCrm.OrderingService.Contracts` project: + +```csharp +using System; +using CloudCrm.OrderingService.Enums; + +namespace CloudCrm.OrderingService.Services; + +public class OrderDto +{ + public Guid Id { get; set; } + public string CustomerName { get; set; } + public Guid ProductId { get; set; } + public OrderState State { get; set; } +} +``` + +The final solution structure should look like this: + +![vs-ordering-contracts](images/vs-ordering-contracts.png) + +## Implementing the Application Service + +Now, we will implement the `IOrderAppService` interface in the `OrderAppService` class. Create an `OrderAppService` class under the `Services` folder in the `CloudCrm.OrderingService` project: + +```csharp +using System; +using System.Collections.Generic; +using CloudCrm.OrderingService.Entities; +using CloudCrm.OrderingService.Enums; +using CloudCrm.OrderingService.Localization; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace CloudCrm.OrderingService.Services; + +public class OrderAppService : ApplicationService, IOrderAppService +{ + private readonly IRepository _orderRepository; + + public OrderAppService(IRepository orderRepository) + { + LocalizationResource = typeof(OrderingServiceResource); + _orderRepository = orderRepository; + } + + public async Task> GetListAsync() + { + var orders = await _orderRepository.GetListAsync(); + return ObjectMapper.Map, List>(orders); + } + + public async Task CreateAsync(OrderCreationDto input) + { + var order = new Order + { + CustomerName = input.CustomerName, + ProductId = input.ProductId, + State = OrderState.Placed + }; + + await _orderRepository.InsertAsync(order); + } +} +``` + +In this code snippet, we inject the `IRepository` into the `OrderAppService` class. We use this repository to interact with the `Order` entity. The `GetListAsync` method retrieves a list of orders from the database and maps them to the `OrderDto` class. The `CreateAsync` method creates a new order entity and inserts it into the database. + +Afterward, we need to configure the *AutoMapper* object to map the `Order` entity to the `OrderDto` class. Open the `OrderingServiceApplicationAutoMapperProfile` class in the `CloudCrm.OrderingService` project, located in the `ObjectMapping` folder, and add the following code: + +```csharp +using AutoMapper; +using CloudCrm.OrderingService.Entities; +using CloudCrm.OrderingService.Services; + +namespace CloudCrm.OrderingService.ObjectMapping; + +public class OrderingServiceApplicationAutoMapperProfile : Profile +{ + public OrderingServiceApplicationAutoMapperProfile() + { + CreateMap(); + } +} +``` + +## Testing the Application Service + +Now, we can test the `OrderAppService` class using the Swagger UI. Open the Solution Runner and right-click to `CloudCrm.OrderingService` project and select the *Run* -> *Build & Start* command. After the application starts, you can open the Swagger UI by clicking to the [Browse](../../studio/running-applications.md#monitoring) command: + +![ordering-service-swagger-ui](images/ordering-service-swagger-ui.png) + +Expand the `api/ordering/order` API and click the *Try it out* button. Then, create a few orders by filling in the request body and clicking the *Execute* button: + +![ordering-service-order-swagger-ui](images/ordering-service-order-swagger-ui.png) + +If you check the database, you should see the entities created in the `Orders` table: + +![sql-server-orders-database-table-records](images/sql-server-orders-database-table-records.png) + +> Since we're using the [Auto API Controller](../../framework/api-development/auto-controllers.md) we don't need to create a controller for the `OrderAppService`. The ABP Framework automatically creates an API controller for the `OrderAppService` class. You can find the configuration in the `CloudCrmOrderingServiceModule` class, in the `ConfigureAutoControllers` method of the `CloudCrm.OrderingService` project. + +## Creating the User Interface + +Now, we will create the user interface for the Ordering module. We will use the `CloudCrm.Web` project to create the user interface. Open the `CloudCrm.Web` .NET solution in your favorite IDE. + +### Creating the Orders Page + +Create a new `Orders` folder under the `Pages` folder in the `CloudCrm.Web` project. Then, create an `Index.cshtml` Razor Page inside that new folder and edit the `Index.cshtml.cs` file as follows: + +```csharp +using CloudCrm.OrderingService.Services; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; + +namespace CloudCrm.Web.Pages.Orders; + +public class Index : AbpPageModel +{ + public List Orders { get; set; } + + private readonly IOrderAppService _orderAppService; + + public Index(IOrderAppService orderAppService) + { + _orderAppService = orderAppService; + } + + public async Task OnGetAsync() + { + Orders = await _orderAppService.GetListAsync(); + } +} +``` + +Here, we inject the `IOrderAppService` into the `Index` Razor Page. We use this service to retrieve the list of orders from the database and assign them to the `Orders` property. Open the `Index.cshtml` file and add the following code: + +```html +@page +@model CloudCrm.Web.Pages.Orders.Index + +

    Orders

    + + + + + @foreach (var order in Model.Orders) + { + + Customer: @order.CustomerName
    + Product: @order.ProductId
    + State: @order.State +
    + } +
    +
    +
    +``` + +This page shows a list of orders on the UI. We haven't created a UI to create new orders, and we will not do it to keep this tutorial simple. If you want to learn how to create advanced UIs with ABP, please follow the [Book Store tutorial](../../tutorials/book-store/index.md). + +### Generating the UI Proxy + +To select the *Application* during proxy generation, ensure that the `CloudCrm.OrderingService` is *Started* beforehand. You can start the application using [Solution Runner](../../studio/running-applications.md). + +Now, we need to generate the [Static API Proxy](../../framework/api-development/static-csharp-clients.md) for the *Web* project. Right-click the *CloudCrm.Web* [package](../../studio/concepts.md#package) and select the *ABP CLI* -> *Generate Proxy* -> *C#* command: + +![abp-studio-generate-proxy-2](images/abp-studio-generate-proxy-2.png) + +It will open the *Generate C# Proxies* window. Select the `CloudCrm.OrderingService` application, and it will automatically populate the *URL* field. Choose the *ordering* module and service type is *application* lastly check the *Without contracts* checkbox, since we already have a dependency on the `CloudCrm.OrderingService.Contracts` package in the `CloudCrm.Web` project: + +![abp-studio-generate-proxy-window-ordering-module](images/abp-studio-generate-proxy-window-ordering-module.png) + +Lastly, we need to configure the use of a static HTTP client for the `OrderingService` in the `CloudCrm.Web` project. Open the `CloudCrmWebModule.cs` file in the `Web` project and add the following line to the `ConfigureServices` method: + +```csharp +//... +using CloudCrm.OrderingService; + +public override void ConfigureServices(ServiceConfigurationContext context) +{ + // Code omitted for brevity + context.Services.AddStaticHttpClientProxies( + typeof(CloudCrmOrderingServiceContractsModule).Assembly); +} +``` + +### Adding the Menu Item + +> ABP provides a modular navigation [menu system](../../framework/ui/mvc-razor-pages/navigation-menu.md) that allows you to define the menu items in a modular way. + +Finally, we need to add a menu item to the sidebar to navigate to the `Orders` page. Open the `CloudCrmMenus` file in the `Navigation` folder of the `CloudCrm.Web` project and edit with the following code: + +```csharp +namespace CloudCrm.Web.Navigation; + +public class CloudCrmMenus +{ + private const string Prefix = "CloudCrm"; + + public const string Home = Prefix + ".Home"; + + public const string HostDashboard = Prefix + ".HostDashboard"; + + public const string TenantDashboard = Prefix + ".TenantDashboard"; + + public const string Products = Prefix + ".Products"; + + public const string Orders = Prefix + ".Orders"; // NEW: ADD MENU ITEM +} +``` + +Then, open the `CloudCrmMenuContributor` class in the `CloudCrm.Web` project, located in the `Navigation` folder, and add the following code to `ConfigureMainMenuAsync` method: + +```csharp +private static async Task ConfigureMainMenuAsync(MenuConfigurationContext context) +{ + // Code omitted for brevity + + context.Menu.AddItem( + new ApplicationMenuItem( + CloudCrmMenus.Orders, // Unique menu id + "Orders", // Menu display text + "~/Orders", // URL + "fa-solid fa-basket-shopping" // Icon CSS class + ) + ); +} +``` + +## Building and Running the Application + +Now, we can build and run the application to see the changes. Please stop the applications if they are running. Then open the *Solution Runner* panel, right-click the `CloudCrm` root item, and select the *Run* -> *Build & Start* command: + +![abp-studio-run-build-start](images/abp-studio-run-build-start.png) + +After the applications are started, you can *Browse* and navigate to the `Orders` page to see the list of orders: + +![web-orders-page](images/web-orders-page.png) + +Great! We have successfully implemented the Ordering module. However, there is a problem: + +- We see Product's GUID ID instead of its name. This is because the *Ordering* microservice has no integration with the *Catalog* microservice and doesn't have access to Product microservice's database to perform a JOIN query. + +We will solve this problem in the next part by implementing an integration service between the *Ordering* and *Catalog* microservices. + +## Summary + +In this part, we implemented the Ordering module manually. We created the `Order` entity, the `OrderState` enum, the `OrderAppService` application service, and the user interface for the `Orders` page. We also added a menu item to the sidebar to navigate to the `Orders` page. \ No newline at end of file diff --git a/docs/en/tutorials/microservice/part-06.md b/docs/en/tutorials/microservice/part-06.md new file mode 100644 index 0000000000..f171767260 --- /dev/null +++ b/docs/en/tutorials/microservice/part-06.md @@ -0,0 +1,311 @@ +# Microservice Tutorial Part 06: Integrating the services: HTTP API Calls + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Building the Ordering service", + "Path": "tutorials/microservice/part-05" + }, + "Next": { + "Name": "Integrating the services: Using Distributed Events", + "Path": "tutorials/microservice/part-07" + } +} +```` + +In the previous part, we implemented the functionality of the Ordering microservice. However, when listing orders, we need to display the product name instead of the product ID. To achieve this, we must call the Catalog service to retrieve the product name for each order item. + +In this section, we will integrate the Ordering service with the Catalog service using HTTP API calls. + +## The Need for the Integration Services + +In a microservices architecture, each service is responsible for its own data and business logic. However, services often need to communicate with each other to fulfill their responsibilities. This communication can be synchronous or asynchronous, depending on the requirements. + +![web-orders-page](images/web-orders-page.png) + +In our case, the Ordering service needs to display the product name instead of the product ID. To achieve this, we need to call the Catalog service to retrieve the product details based on the product ID. This is a typical example of a synchronous communication pattern between microservices. As a solution to that problem, we will use an [integration service](../../framework/api-development/integration-services.md) that will handle the communication with the Catalog service. Integration service concept in ABP is designed for request/response style inter-module (in modular applications) and inter-microservice (in distributed systems) communication. + +## Creating a Products Integration Service + +First, we need to create a service that will handle the communication with the Catalog service. This service will be responsible for fetching the product details based on the product ID. + +### Defining the `IProductIntegrationService` Interface + +Open the `CloudCrm.CatalogService` .NET solution in your IDE. Locate the `CloudCrm.CatalogService.Contracts` project, and create a new folder named `IntegrationServices`. Inside this folder, add a new interface named `IProductIntegrationService` with the following code: + +```csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using CloudCrm.CatalogService.Products; +using Volo.Abp; +using Volo.Abp.Application.Services; + +namespace CloudCrm.CatalogService.IntegrationServices; + +[IntegrationService] +public interface IProductIntegrationService : IApplicationService +{ + Task> GetProductsByIdsAsync(List ids); +} +``` + +`IProductIntegrationService` is very similar to a typical [application service](../../framework/architecture/domain-driven-design/application-services.md). The only difference is that it is marked with the `[IntegrationService]` attribute. This attribute is used to identify the service as an integration service, which allows ABP to handle the communication between services. ABP behave differently for them (for example, ABP doesn't expose [integration services](../../framework/api-development/integration-services.md) as HTTP APIs by default if you've configured the [Auto API Controllers](../../framework/api-development/auto-controllers.md) feature) + +`IProductIntegrationService` contains a single method named `GetProductsByIdsAsync`. This method takes a list of product IDs and returns a list of `ProductDto` objects. This is exactly what we need in the Ordering service. + +> **Design Tip** +> +> You may think if we can use the existing application services (like `IProductAppService`) from other services instead of creating specific integration services. Technically you can use, ABP has no restriction. However, from good design and best practice points, we don't suggest it. Because, application services are designed to be consumed specifically by the presentation layer. They will have different authorization and validation logic, they will need different DTO input and output properties, they will have different performance, optimization and caching requirements, and so on. And most importantly, all these will change by the time based on UI requirements and these changes may break your integrations later. It is best to implement specific integration APIs that is designed and optimized for that purpose. +> +> We've reused the `ProductDto` object created for `IProductAppService`, which can be reasonable from a maintenance point of view. But if you think your integration service results will be different from the application service results in the future, it can be good to separate them from the first day so you don't need to introduce breaking changes later. + +### Implementing the `ProductIntegrationService` Class + +Now, let's implement the `IProductIntegrationService` interface. Create a new folder named `IntegrationServices` in the `CloudCrm.CatalogService` project. Inside this folder, add a new class named `ProductIntegrationService` with the following code: + +```csharp +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using CloudCrm.CatalogService.Localization; +using CloudCrm.CatalogService.Products; +using Volo.Abp; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace CloudCrm.CatalogService.IntegrationServices; + +[IntegrationService] +public class ProductIntegrationService : ApplicationService, IProductIntegrationService +{ + private readonly IRepository _productRepository; + + public ProductIntegrationService(IRepository productRepository) + { + LocalizationResource = typeof(CatalogServiceResource); + _productRepository = productRepository; + } + + public async Task> GetProductsByIdsAsync(List ids) + { + var products = await _productRepository.GetListAsync( + product => ids.Contains(product.Id) + ); + + return ObjectMapper.Map, List>(products); + } +} +``` + +`ProductIntegrationService` is a typical application service class that implements the `IProductIntegrationService` interface. It has a constructor that takes an `IRepository` object. This repository is used to fetch the product details from the database. + +> Here, we directly used `List` classes, but instead, you could wrap inputs and outputs into [DTOs](../../framework/architecture/domain-driven-design/data-transfer-objects.md). In that way, it can be possible to add new properties to these DTOs without changing the signature of your integration service method (and without introducing breaking changes for your client applications). + +### Exposing the Integration Service as an API + +Integration services are not exposed as HTTP APIs by default. However, you can expose them as HTTP APIs if you need to. To do this, you should configure the `AbpAspNetCoreMvcOptions` in the `ConfigureServices` method of the `CloudCrmCatalogServiceModule`. Open the `CloudCrm.CatalogService` project and locate the `CloudCrmCatalogServiceModule` class. Add the following code to the `ConfigureServices` method: + +```csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + // Other configurations... + + Configure(options => + { + options.ExposeIntegrationServices = true; + }); +} +``` + +This code configures the `AbpAspNetCoreMvcOptions` to expose integration services as HTTP APIs. This is useful when you need to call the integration service from a different service using HTTP. You can learn more about this in the [Integration Services](../../framework/api-development/integration-services.md#exposing-integration-services) document. + +## Consuming the Products Integration Service + +Now that we have created the `IProductIntegrationService` interface and the `ProductIntegrationService` class, we can consume this service from the Ordering service. + +### Adding a Reference to the `CloudCrm.CatalogService.Contracts` Package + +First, we need to add a reference to the `CloudCrm.CatalogService.Contracts` package in the Ordering service. Open the ABP Studio, and stop the application(s) if it is running. Then, open the *Solution Explorer* and right-click on the `CloudCrm.OrderingService` package. Select *Add* -> *Package Reference* command: + +![add-package-reference-ordering-service](images/add-package-reference-ordering-service.png) + +In the *Add Package Reference* window, select the `CloudCrm.CatalogService.Contracts` package from the *This solution* tab. Click the *OK* button to add the reference: + +![add-catalog-service-contracts-reference](images/add-catalog-service-contracts-reference.png) + +ABP Studio adds the package reference and arranges the [module](../../framework/architecture/modularity/basics.md) dependency. + +> Instead of directly adding such a package reference, it can be best to import the module first (right-click the `CloudCrm.OrderingService`, select the _Import Module_ command and import the `CloudCrm.CatalogService` module), then install the package reference. In that way, it would be easy to see and keep track of inter-module dependencies. + +### Using the Products Integration Service + +Now, we can use the `IProductIntegrationService` interface to fetch the product details in the `OrderAppService` class. + +Open the `OrderAppService` class (the `OrderAppService.cs` file under the `Services` folder of the `CloudCrm.OrderingService` project of the `CloudCrm.OrderingService` .NET solution) and change its content as like the following code block: + +```csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CloudCrm.CatalogService.IntegrationServices; +using CloudCrm.OrderingService.Entities; +using CloudCrm.OrderingService.Enums; +using CloudCrm.OrderingService.Localization; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace CloudCrm.OrderingService.Services; + +public class OrderAppService : ApplicationService, IOrderAppService +{ + private readonly IRepository _orderRepository; + private readonly IProductIntegrationService _productIntegrationService; + + public OrderAppService( + IRepository orderRepository, + IProductIntegrationService productIntegrationService) + { + LocalizationResource = typeof(OrderingServiceResource); + + _orderRepository = orderRepository; + _productIntegrationService = productIntegrationService; + } + + public async Task> GetListAsync() + { + var orders = await _orderRepository.GetListAsync(); + + // Prepare a list of products we need + var productIds = orders.Select(o => o.ProductId).Distinct().ToList(); + var products = (await _productIntegrationService + .GetProductsByIdsAsync(productIds)) + .ToDictionary(p => p.Id, p => p.Name); + + var orderDtos = ObjectMapper.Map, List>(orders); + + orderDtos.ForEach(orderDto => + { + orderDto.ProductName = products[orderDto.ProductId]; + }); + + return orderDtos; + } + + public async Task CreateAsync(OrderCreationDto input) + { + var order = new Order + { + CustomerName = input.CustomerName, + ProductId = input.ProductId, + State = OrderState.Placed + }; + + await _orderRepository.InsertAsync(order); + } +} +``` + +Now open the `OrderDto` class (the `OrderDto.cs` file under the `Services` folder of the `CloudCrm.OrderingService.Contracts` project of the `CloudCrm.OrderingService` .NET solution) and add a new property named `ProductName`: + +```csharp +using System; +using CloudCrm.OrderingService.Enums; + +namespace CloudCrm.OrderingService.Services; + +public class OrderDto +{ + public Guid Id { get; set; } + public string CustomerName { get; set; } + public Guid ProductId { get; set; } + public string ProductName { get; set; } // New property + public OrderState State { get; set; } +} +``` + +Lastly, open the `OrderingServiceApplicationAutoMapperProfile` class (the `OrderingServiceApplicationAutoMapperProfile.cs` file under the `ObjectMapping` folder of the `CloudCrm.OrderingService` project of the `CloudCrm.OrderingService` .NET solution) and ignore the `ProductName` property in the mapping configuration: + +```csharp +using AutoMapper; +using CloudCrm.OrderingService.Entities; +using CloudCrm.OrderingService.Services; +using Volo.Abp.AutoMapper; + +namespace CloudCrm.OrderingService.ObjectMapping; + +public class OrderingServiceApplicationAutoMapperProfile : Profile +{ + public OrderingServiceApplicationAutoMapperProfile() + { + CreateMap() + .Ignore(x => x.ProductName); // New line + } +} +``` +Let's explain the changes we made: + +- We added a new property named `ProductName` to the `OrderDto` class. This property will hold the product name. +- We modified the `GetListAsync` method of the `OrderAppService` class to fetch the product details using the `IProductIntegrationService` interface. We first fetch the product IDs from the orders, then call the `GetProductsByIdsAsync` method of the `IProductIntegrationService` interface to fetch the product details. Finally, we map the product names to the `OrderDto` objects. + +### Generating Proxy Classes for the Integration Service + +We have created the `IProductIntegrationService` interface and the `ProductIntegrationService` class in the `CloudCrm.CatalogService` solution. Now, we need to generate the proxy classes for the integration service in the `CloudCrm.OrderingService` package. First, *Build & Start* the `CloudCrm.CatalogService` application in ABP Studio *Solution Runner*. Then, open the *Solution Explorer* and right-click on the `CloudCrm.OrderingService` package. Select the *ABP CLI* -> *Generate Proxy* -> *C#* command: + +![generate-proxy-catalog-service](images/generate-proxy-catalog-service.png) + +It opens the *Generate C# proxies* window. Select the `CloudCrm.CatalogService` application from the *Application* dropdown list. Then, choose the *catalog* module from the *Module* dropdown list and choose the *integration* service from the *Service type* dropdown list. Check the *Without contracts* checkbox and click the *Generate* button: + +![generate-catalog-service-proxy](images/generate-catalog-service-proxy.png) + +We have generated the proxy classes for the `IProductIntegrationService` interface. Now, we must add the *Remote Service* url to the `appsettings.json` file of the `CloudCrm.OrderingService` project. Open the `appsettings.json` file (the `appsettings.json` file of the `CloudCrm.OrderingService` project of the `CloudCrm.OrderingService` .NET solution) and add the *CatalogService* section following configuration: + +```json +{ + "RemoteServices": { + "CatalogService": { + "BaseUrl": "http://localhost:44334" + } + } +} +``` + +> **BaseUrl** refers to the base URL of the Catalog service. You can use the *Copy Url* option from the Catalog service's context menu in the ABP Studio **Solution Runner** to paste it here. + +### Updating the UI to Display the Product Name + +Open the `Index.cshtml` file (the `Index.cshtml` file under the `Pages/Orders` folder of the `CloudCrm.Web` project of the `CloudCrm.Web` .NET solution) and update the table content to display the product name instead of the product ID: + +```html +@page +@model CloudCrm.Web.Pages.Orders.Index + +

    Orders

    + + + + + @foreach (var order in Model.Orders) + { + + Customer: @order.CustomerName
    + Product: @order.ProductName
    + State: @order.State +
    + } +
    +
    +
    +``` + +That's it! Now, you can *Build & Start* the all applications and run it in ABP Studio to see the result: + +![web-orders-page-with-product-name](images/web-orders-page-with-product-name.png) + +Now, the Ordering service displays the product name instead of the product ID. We have successfully integrated the Ordering service with the Catalog service using HTTP API calls. + +> **Design Tip** +> +> It is suggested that you keep that type of communication to a minimum and not couple your services with each other. It can make your solution complicated and may also decrease your system performance. When you need to do it, think about performance and try to make some optimizations. For example, if the Ordering service frequently needs product data, you can use a kind of [cache layer](../../framework/fundamentals/caching.md), so it doesn't make frequent requests to the Catalog service. diff --git a/docs/en/tutorials/microservice/part-07.md b/docs/en/tutorials/microservice/part-07.md new file mode 100644 index 0000000000..0351df2a52 --- /dev/null +++ b/docs/en/tutorials/microservice/part-07.md @@ -0,0 +1,231 @@ +# Microservice Tutorial Part 07: Integrating the services: Using Distributed Events + +````json +//[doc-nav] +{ + "Previous": { + "Name": "Integrating the services: HTTP API Calls", + "Path": "tutorials/microservice/part-06" + } +} +```` + +Another common approach to communicating between microservices is messaging. By publishing and handling messages, a microservice can perform an operation when an event happens in another microservice. + +ABP provides two types of event buses for loosely coupled communication: + +* [Local Event Bus](../../framework/infrastructure/event-bus/local/index.md) is suitable for in-process messaging. However, it’s not suitable for microservices as it cannot communicate across different processes. For distributed systems, consider using a distributed event bus. + +* **[Distributed Event Bus](../../framework/infrastructure/event-bus/distributed/index.md)** is normal for inter-process messaging, like microservices, for publishing and subscribing to distributed events. However, ABP's distributed event bus works as local (in-process) by default (actually, it uses the Local Event Bus under the hood by default) unless you configure an external message broker. + +In this tutorial, we will use the distributed event bus to communicate between the `Order` and `Catalog` microservices. + +## Publishing an Event + +In the example scenario, we want to publish an event when a new order is placed. The Ordering service will publish the event since it knows when a new order is placed. The Catalog service will subscribe to that event and get notified when a new order is placed. This will decrease the stock count of the product related to the new order. The scenario is pretty simple; let's implement it. + +### Defining the Event Class + +Open the `CloudCrm.OrderingService` .NET solution in your IDE, create an `Events` folder and create a new class named `OrderPlacedEto` under the `CloudCrm.OrderingService.Contracts` project: + +```csharp +using System; + +namespace CloudCrm.OrderingService.Events; + +public class OrderPlacedEto +{ + public string CustomerName { get; set; } + public Guid ProductId { get; set; } +} +``` + +`OrderPlacedEto` is very simple. It is a plain C# class used to transfer data related to the event (*ETO* is an acronym for *Event Transfer Object*, a suggested naming convention but not required). You can add more properties if needed, but for this tutorial, it is more than enough. + +### Using the `IDistributedEventBus` Service + +The `IDistributedEventBus` service publishes events to the event bus. Until this point, the Ordering service only creates an Order and insert to database. Let's change that and publish `OrderPlacedEto` event, for that purpose open the `CloudCrm.OrderingService` project and update to the `OrderAppService` class as shown below: + +```csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using CloudCrm.CatalogService.IntegrationServices; +using CloudCrm.OrderingService.Entities; +using CloudCrm.OrderingService.Enums; +using CloudCrm.OrderingService.Events; +using CloudCrm.OrderingService.Localization; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.EventBus.Distributed; + +namespace CloudCrm.OrderingService.Services; + +public class OrderAppService : ApplicationService, IOrderAppService +{ + private readonly IRepository _orderRepository; + private readonly IProductIntegrationService _productIntegrationService; + private readonly IDistributedEventBus _distributedEventBus; + + public OrderAppService( + IRepository orderRepository, + IProductIntegrationService productIntegrationService, + IDistributedEventBus distributedEventBus) + { + LocalizationResource = typeof(OrderingServiceResource); + + _orderRepository = orderRepository; + _productIntegrationService = productIntegrationService; + _distributedEventBus = distributedEventBus; + } + + public async Task> GetListAsync() + { + var orders = await _orderRepository.GetListAsync(); + + // Prepare a list of products we need + var productIds = orders.Select(o => o.ProductId).Distinct().ToList(); + var products = (await _productIntegrationService + .GetProductsByIdsAsync(productIds)) + .ToDictionary(p => p.Id, p => p.Name); + + var orderDtos = ObjectMapper.Map, List>(orders); + + orderDtos.ForEach(orderDto => + { + orderDto.ProductName = products[orderDto.ProductId]; + }); + + return orderDtos; + } + + public async Task CreateAsync(OrderCreationDto input) + { + // Create a new Order entity + var order = new Order + { + CustomerName = input.CustomerName, + ProductId = input.ProductId, + State = OrderState.Placed + }; + + // Save it to the database + await _orderRepository.InsertAsync(order); + + // Publish an event so other microservices can be informed + await _distributedEventBus.PublishAsync( + new OrderPlacedEto + { + ProductId = order.ProductId, + CustomerName = order.CustomerName + }); + } +} +``` +The `OrderAppService.CreateAsync` method creates a new `Order` entity, saves it to the database and finally publishes an `OrderPlacedEto` event. + +## Subscribing to an Event + +The Catalog service will subscribe to the `OrderPlacedEto` event and decrease the stock count of the product related to the new order. Let's implement it. + +### Adding a Reference to the `CloudCrm.OrderingService.Contracts` Package + +Since the `OrderPlacedEto` class is in the `CloudCrm.OrderingService.Contracts` project, we must add that package's reference to the Catalog service. This time, we will use the Import Module feature of ABP Studio (as an alternative to the approach we used in the Adding a Reference to the `CloudCrm.CatalogService.Contracts` Package section of the [previous part](./part-06.md#adding-a-reference-to-the-cloudcrmcatalogservicecontracts-package)). + +Open the ABP Studio UI and stop the applications if they are running. Then, open the *Solution Explorer* panel and right-click on the `CloudCrm.CatalogService`. Select *Import Module* from the context menu: + +![Import Module](images/import-module.png) + +In the opening dialog, find and select the `CloudCrm.OrderingService` module, check the *Install this module* option, click the *OK* button: + +![Import Module Dialog](images/import-module-dialog.png) + +Once you click the OK button, the Ordering service is imported to the Catalog service. It opens the *Install Module* dialog: + +![Install Module Dialog](images/install-module-dialog.png) + +Here, select the `CloudCrm.OrderingService.Contracts` package on the left side (because we want to add that package reference) and `CloudCrm.CatalogService` package on the middle area (because we want to add the package reference to that project). + +You can check the ABP Studio's *Solution Explorer* panel to see the module and the project reference (dependency): + +![catalog-service-dependency](images/catalog-service-dependency.png) + +### Handling the `OrderPlacedEto` Event + +Now, it's time to handle the `OrderPlacedEto` event in the Catalog service. Open the `CloudCrm.CatalogService` .NET solution in your IDE. Create a new `Orders` folder, and add a new class named `OrderEventHandler` inside that folder within the `CloudCrm.CatalogService` project: + +```csharp +using System; +using System.Threading.Tasks; +using CloudCrm.CatalogService.Products; +using CloudCrm.OrderingService.Events; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.EventBus.Distributed; + +namespace CloudCrm.CatalogService.Orders; + +public class OrderEventHandler : + IDistributedEventHandler, + ITransientDependency +{ + private readonly IRepository _productRepository; + + public OrderEventHandler(IRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task HandleEventAsync(OrderPlacedEto eventData) + { + // Find the related product + var product = await _productRepository.FindAsync(eventData.ProductId); + if (product == null) + { + return; + } + + // Decrease the stock count + product.StockCount = product.StockCount - 1; + + // Update the entity in the database + await _productRepository.UpdateAsync(product); + } +} +``` + +The `OrderEventHandler` class implements the `IDistributedEventHandler` interface to handle the `OrderPlacedEto` event. When the event is published, the `HandleEventAsync` method is called. In this method, we find the related product, decrease the stock count by one, and update the entity in the database. + +Implementing `ITransientDependency` registers the `OrderEventHandler` class to the dependency injection system as a transient object. + +### Testing the Order Creation + +To keep this tutorial simple, we will not implement a user interface for creating orders. Instead, we will use the Swagger UI to create an order. Open the *Solution Runner* panel in ABP Studio and use *Build & Start* to launch the `CloudCrm.OrderingService` and `CloudCrm.CatalogService` applications. Then, go to *Run* -> *Start All* to start the remaining applications listed in the [Solution Runner root item](../../studio/running-applications.md#run). + +Once the application is running and ready, [Browse](../../studio/running-applications.md#c-application) the `CloudCrm.OrderingService` application. Use the `POST /api/ordering/order` endpoint to create a new order: + +![Create Order](images/create-order.png) + +Find the *Order* API, click the *Try it out* button, enter a sample value the *Request body* section, and click the *Execute* button: + +```json +{ + "customerName": "David", + "productId": "5995897b-1de9-7272-b31c-3a165bbe7b18" +} +``` + +> **IMPORTANT:** Here, you should type a valid Product Id from the Products table of your database! + +Once you press the *Execute* button, a new order is created. At that point, you can check the `/Orders` page to see if the new order is listed. You can also check the `/Products` page to see if the stock count of the related product is decreased by one in the `CloudCrm.Web` application. + +Here are sample screenshots from the Orders and Products pages of the `CloudCrm.Web` application: + +![Orders](images/orders.png) + +We placed a new order for *Product A*. As a result, the stock count of *Product A* is decreased from 53 to 52 and a new line is added to the Orders page. + +## Conclusion + +In this tutorial, we used the distributed event bus to communicate between the `Order` and `Catalog` microservices. We published an event when a new order is placed and handled that event in the Catalog service to decrease the stock count of the related product. This is a simple example, but it shows how you can use distributed events to communicate between microservices. \ No newline at end of file diff --git a/docs/en/tutorials/modular-crm/part-01.md b/docs/en/tutorials/modular-crm/part-01.md index 61698fb48a..316aff6150 100644 --- a/docs/en/tutorials/modular-crm/part-01.md +++ b/docs/en/tutorials/modular-crm/part-01.md @@ -10,7 +10,7 @@ } ```` -Follow the *[Get Stared](../../get-started/layered-web-application.md)* guide to create a new layered web application with the following configuration: +Follow the *[Get Started](../../get-started/layered-web-application.md)* guide to create a new layered web application with the following configuration: * **Solution name**: `ModularCrm` * **UI Framework**: ASP.NET Core MVC / Razor Pages @@ -34,4 +34,4 @@ Initially, you see a `ModularCrm` solution and a `ModularCrm` module under that ## Summary -We've created the initial layered monolith solution. In the next part, we will learn how to create a new application module and install it to the main application. \ No newline at end of file +We've created the initial layered monolith solution. In the next part, we will learn how to create a new application module and install it to the main application. diff --git a/docs/en/tutorials/modular-crm/part-02.md b/docs/en/tutorials/modular-crm/part-02.md index 6ebc22f20c..8a5b4b9e6c 100644 --- a/docs/en/tutorials/modular-crm/part-02.md +++ b/docs/en/tutorials/modular-crm/part-02.md @@ -14,7 +14,7 @@ } ```` -In this part, you will build a new product management module and install it in the main CRM application. +In this part, you will create a new product management module and install it in the main CRM application. ## Creating Solution Folders diff --git a/docs/en/tutorials/todo/layered/index.md b/docs/en/tutorials/todo/layered/index.md index 2eef34bbd2..a67076dad1 100644 --- a/docs/en/tutorials/todo/layered/index.md +++ b/docs/en/tutorials/todo/layered/index.md @@ -74,7 +74,7 @@ dotnet tool install -g Volo.Abp.Studio.Cli Create an empty folder, open a command-line terminal and execute the following command in the terminal: ````bash -abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} +abp new TodoApp{{if UI=="Blazor"}} -u blazor{{else if UI=="BlazorServer"}} -u blazor-server{{else if UI=="BlazorWebApp"}} -u blazor-webapp{{else if UI=="NG"}} -u angular{{end}}{{if DB=="Mongo"}} -d mongodb{{end}} ```` {{if UI=="NG"}} @@ -113,13 +113,14 @@ abp install-libs > We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet. -{{if UI=="Blazor" || UI=="BlazorServer"}} +{{if UI=="Blazor" || UI=="BlazorWebApp"}} #### Bundling and Minification `abp bundle` command offers bundling and minification support for client-side resources (JavaScript and CSS files) for Blazor projects. This command automatically run when you create a new solution with the [ABP CLI](../../../cli/index.md). -However, sometimes you might need to run this command manually. To update script & style references without worrying about dependencies, ordering, etc. in a project, you can run this command in the directory of your blazor application: +However, sometimes you might need to run this command manually. To update script & style references without worrying about dependencies, ordering, etc. in a project, you can run this command in the directory of your `Blazor.Client` application: + ````bash abp bundle @@ -131,7 +132,7 @@ abp bundle ### Run the Application -{{if UI=="MVC" || UI=="BlazorServer"}} +{{if UI=="MVC" || UI=="BlazorServer" || UI=="BlazorWebApp"}} It is good to run the application before starting the development. Ensure the {{if UI=="BlazorServer"}}`TodoApp.Blazor`{{else}}`TodoApp.Web`{{end}} project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI: @@ -148,10 +149,6 @@ Ensure the `TodoApp.HttpApi.Host` project is the startup project, then run the a You can explore and test your HTTP API with this UI. Now, we can set the `TodoApp.Blazor` as the startup project and run it to open the actual Blazor application UI: -{{else if UI=="BlazorWebApp" }} - -It is good to run the application before starting the development. Ensure the `TodoApp.Blazor` project is the startup project, then run the application (Ctrl+F5 in Visual Studio) to see the initial UI: - {{else if UI=="NG"}} It is good to run the application before starting the development. The solution has two main applications: @@ -589,7 +586,7 @@ If you open the [Swagger UI](https://swagger.io/tools/swagger-ui/) by entering t ### Index.razor.cs -Open the `Index.razor.cs` file in the `Pages` folder of the {{if UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}}*TodoApp.Blazor*{{end}} project and replace the content with the following code block: +Open the `Index.razor.cs` file in the `Pages` folder of the {{if UI=="Blazor" || UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}}*TodoApp.Blazor*{{end}} project and replace the content with the following code block: ```csharp using Microsoft.AspNetCore.Components; @@ -638,7 +635,7 @@ See the *Dynamic C# Proxies & Auto API Controllers* section below to learn how w ### Index.razor -Open the `Index.razor` file in the `Pages` folder of the {{if UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}} *TodoApp.Blazor* {{end}} project and replace the content with the following code block: +Open the `Index.razor` file in the `Pages` folder of the {{if UI=="Blazor" || UI=="BlazorWebApp"}} *TodoApp.Blazor.Client* {{else}} *TodoApp.Blazor* {{end}} project and replace the content with the following code block: ```xml @page "/" @@ -680,7 +677,7 @@ Open the `Index.razor` file in the `Pages` folder of the {{if UI=="BlazorWebApp" ### Index.razor.css -As the final touch, open the `Index.razor.css` file in the `Pages` folder of the {{if UI=="BlazorWebApp"}}*TodoApp.Blazor.Client*{{else}}*TodoApp.Blazor*{{end}} project and replace it with the following content: +As the final touch, open the `Index.razor.css` file in the `Pages` folder of the {{if UI=="Blazor" || UI=="BlazorWebApp"}}*TodoApp.Blazor.Client*{{else}}*TodoApp.Blazor*{{end}} project and replace it with the following content: ```css #TodoList{ diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js index e43c7caad9..0f2b028daf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js @@ -226,7 +226,7 @@ var abp = abp || {}; }; var hideColumnWithoutRedraw = function (tableInstance, colIndex) { - tableInstance.fnSetColumnVis(colIndex, false, false); + tableInstance.api().column(colIndex).visible(false, false); }; var hideEmptyColumn = function (cellContent, tableInstance, colIndex) { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs index 62dfc66f93..48919e56da 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; @@ -63,7 +64,7 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep //Add secondary Id var secondaryIds = action.Parameters .Where(p => p.ParameterName.EndsWith("Id", StringComparison.Ordinal)).ToList(); - if (secondaryIds.Count == 1) + if (secondaryIds.Count == 1 && !secondaryIds[0].Attributes.Any(x => x is OptionalAttribute)) { url += $"/{{{NormalizeSecondaryIdNameCase(secondaryIds[0], configuration)}}}"; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs index e806996ebb..410260674b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Libs/AbpMvcLibsService.cs @@ -34,7 +34,7 @@ public class AbpMvcLibsService : IAbpMvcLibsService, ITransientDependency app.Use(async (httpContext, next) => { - if (!await CheckLibsAsyncOnceAsync(httpContext)) + if (!httpContext.Request.IsAjax() && !await CheckLibsAsyncOnceAsync(httpContext)) { var errorPage = new AbpMvcLibsErrorPage(); await errorPage.ExecuteAsync(httpContext); diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs index b2bbb78e7b..36012a123b 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs @@ -2,7 +2,6 @@ using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features.Authentication; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Middleware; @@ -27,12 +26,10 @@ public class AbpDynamicClaimsMiddleware : AbpMiddlewareBase, ITransientDependenc var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService(); var user = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User); - authenticateResultFeature.AuthenticateResult = AuthenticateResult.Success(new AuthenticationTicket(user, authenticationType)); - var httpAuthenticationFeature = context.Features.Get(); - if (httpAuthenticationFeature != null) - { - httpAuthenticationFeature.User = authenticateResultFeature.AuthenticateResult.Principal; - } + authenticateResultFeature.AuthenticateResult = AuthenticateResult.Success(new AuthenticationTicket( + user, + authenticateResultFeature?.AuthenticateResult?.Properties, + authenticationType)); } if (context.User.Identity?.IsAuthenticated == false) 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 900f252a77..7ad3dbd7bf 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 @@ -93,21 +93,21 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems RecycleMethodInfo.Invoke(this, new object[] { lease! }); } - public byte[]?[] GetMany(IEnumerable keys) + public virtual byte[]?[] GetMany(IEnumerable keys) { keys = Check.NotNull(keys, nameof(keys)); return GetAndRefreshMany(keys, true); } - public async Task GetManyAsync(IEnumerable keys, CancellationToken token = default) + public virtual async Task GetManyAsync(IEnumerable keys, CancellationToken token = default) { keys = Check.NotNull(keys, nameof(keys)); return await GetAndRefreshManyAsync(keys, true, token); } - public void SetMany(IEnumerable> items, DistributedCacheEntryOptions options) + public virtual void SetMany(IEnumerable> items, DistributedCacheEntryOptions options) { var cache = Connect(); @@ -126,7 +126,7 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems } } - public async Task SetManyAsync( IEnumerable> items, DistributedCacheEntryOptions options, CancellationToken token = default) + public virtual async Task SetManyAsync(IEnumerable> items, DistributedCacheEntryOptions options, CancellationToken token = default) { token.ThrowIfCancellationRequested(); @@ -147,21 +147,21 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems } } - public void RefreshMany(IEnumerable keys) + public virtual void RefreshMany(IEnumerable keys) { keys = Check.NotNull(keys, nameof(keys)); GetAndRefreshMany(keys, false); } - public async Task RefreshManyAsync(IEnumerable keys, CancellationToken token = default) + public virtual async Task RefreshManyAsync(IEnumerable keys, CancellationToken token = default) { keys = Check.NotNull(keys, nameof(keys)); await GetAndRefreshManyAsync(keys, false, token); } - public void RemoveMany(IEnumerable keys) + public virtual void RemoveMany(IEnumerable keys) { keys = Check.NotNull(keys, nameof(keys)); @@ -169,7 +169,7 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems try { - cache.KeyDelete(keys.Select(key => InstancePrefix.Append(key)).ToArray()); + Task.WaitAll(PipelineRemoveManyAsync(cache, keys)); } catch (Exception ex) { @@ -178,7 +178,7 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems } } - public async Task RemoveManyAsync(IEnumerable keys, CancellationToken token = default) + public virtual async Task RemoveManyAsync(IEnumerable keys, CancellationToken token = default) { keys = Check.NotNull(keys, nameof(keys)); @@ -187,7 +187,7 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems try { - await cache.KeyDeleteAsync(keys.Select(key => InstancePrefix.Append(key)).ToArray()); + await Task.WhenAll(PipelineRemoveManyAsync(cache, keys)); } catch (Exception ex) { @@ -195,6 +195,11 @@ public class AbpRedisCache : RedisCache, ICacheSupportsMultipleItems throw; } } + + protected virtual Task[] PipelineRemoveManyAsync(IDatabase cache, IEnumerable keys) + { + return keys.Select(key => cache.KeyDeleteAsync(InstancePrefix.Append(key))).ToArray(); + } protected virtual byte[]?[] GetAndRefreshMany(IEnumerable keys, bool getData) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs index 988b9aacc1..667b95b444 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs @@ -141,6 +141,11 @@ public class NugetPackageToLocalReferenceConverter : ITransientDependency private static string[] GetProjectFilesUnder(string path) { + if (!Directory.Exists(path)) + { + return []; + } + return Directory.GetFiles(path, "*.csproj", SearchOption.AllDirectories); diff --git a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs index 58d67e1caf..15956b159e 100644 --- a/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs +++ b/framework/src/Volo.Abp.DistributedLocking.Abstractions/Volo/Abp/DistributedLocking/LocalAbpDistributedLock.cs @@ -30,12 +30,11 @@ public class LocalAbpDistributedLock : IAbpDistributedLock, ISingletonDependency Check.NotNullOrWhiteSpace(name, nameof(name)); var key = DistributedLockKeyNormalizer.NormalizeKey(name); - var timeoutReleaser = await _localSyncObjects.LockAsync(key, timeout, cancellationToken); - if (!timeoutReleaser.EnteredSemaphore) + var timeoutReleaser = await _localSyncObjects.LockOrNullAsync(key, timeout, cancellationToken); + if (timeoutReleaser is not null) { - timeoutReleaser.Dispose(); - return null; + return new LocalAbpDistributedLockHandle(timeoutReleaser); } - return new LocalAbpDistributedLockHandle(timeoutReleaser); + return null; } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj index bfe9bea75a..db32e24bef 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo.Abp.EntityFrameworkCore.Oracle.Devart.csproj @@ -22,6 +22,7 @@ + diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index abcdb97a5a..e9bf710d7d 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -630,13 +630,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, originalExtraProperties = entry.OriginalValues.GetValue(nameof(IHasExtraProperties.ExtraProperties)); } - //TODO: Reload will throw an exception. Check it when new EF Core versions released. - //entry.Reload(); - - var storeValues = entry.OriginalValues; - entry.CurrentValues.SetValues(storeValues); - entry.OriginalValues.SetValues(storeValues); - entry.State = EntityState.Unchanged; + entry.Reload(); if (entry.Entity is IHasExtraProperties) { @@ -785,21 +779,18 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, return; } - AbpDateTimeValueConverter.Clock = Clock; - AbpNullableDateTimeValueConverter.Clock = Clock; - foreach (var property in mutableEntityType.GetProperties(). Where(property => property.PropertyInfo != null && (property.PropertyInfo.PropertyType == typeof(DateTime) || property.PropertyInfo.PropertyType == typeof(DateTime?)) && property.PropertyInfo.CanWrite && ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(property.PropertyInfo) == null)) { - modelBuilder + modelBuilder .Entity() .Property(property.Name) .HasConversion(property.ClrType == typeof(DateTime) - ? new AbpDateTimeValueConverter() - : new AbpNullableDateTimeValueConverter()); + ? new AbpDateTimeValueConverter(Clock) + : new AbpNullableDateTimeValueConverter(Clock)); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs index 174967cd05..31eab98c7c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpDateTimeValueConverter.cs @@ -6,26 +6,20 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters; public class AbpDateTimeValueConverter : ValueConverter { - public static IClock? Clock { get; set; } - - public AbpDateTimeValueConverter(ConverterMappingHints? mappingHints = null) + public AbpDateTimeValueConverter(IClock clock, ConverterMappingHints? mappingHints = null) : base( - x => Clock!.Normalize(x), - x => Clock!.Normalize(x), - mappingHints) + x => clock.Normalize(x), + x => clock.Normalize(x), mappingHints) { } } public class AbpNullableDateTimeValueConverter : ValueConverter { - public static IClock? Clock { get; set; } - - public AbpNullableDateTimeValueConverter(ConverterMappingHints? mappingHints = null) + public AbpNullableDateTimeValueConverter(IClock clock, ConverterMappingHints? mappingHints = null) : base( - x => x.HasValue ? Clock!.Normalize(x.Value) : x, - x => x.HasValue ? Clock!.Normalize(x.Value) : x, - mappingHints) + x => x.HasValue ? clock.Normalize(x.Value) : x, + x => x.HasValue ? clock.Normalize(x.Value) : x, mappingHints) { } } diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo.Abp.EventBus.Rebus.csproj b/framework/src/Volo.Abp.EventBus.Rebus/Volo.Abp.EventBus.Rebus.csproj index 3b6660447f..11bff169be 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo.Abp.EventBus.Rebus.csproj +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo.Abp.EventBus.Rebus.csproj @@ -21,8 +21,11 @@ - - + + + + + + - diff --git a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/AbpRebusEventBusOptions.cs b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/AbpRebusEventBusOptions.cs index d128621396..4b93082722 100644 --- a/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/AbpRebusEventBusOptions.cs +++ b/framework/src/Volo.Abp.EventBus.Rebus/Volo/Abp/EventBus/Rebus/AbpRebusEventBusOptions.cs @@ -29,7 +29,6 @@ public class AbpRebusEventBusOptions private void DefaultConfigure(RebusConfigurer configure) { - configure.Subscriptions(s => s.StoreInMemory()); configure.Transport(t => t.UseInMemoryTransport(new InMemNetwork(), InputQueueName)); } } diff --git a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/FixedLocalizableString.cs b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/FixedLocalizableString.cs index 07eaa4a357..773884a938 100644 --- a/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/FixedLocalizableString.cs +++ b/framework/src/Volo.Abp.Localization.Abstractions/Volo/Abp/Localization/FixedLocalizableString.cs @@ -8,6 +8,7 @@ public class FixedLocalizableString : ILocalizableString public FixedLocalizableString(string value) { + Check.NotNull(value, nameof(value)); Value = value; } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs index 02b9cc8fac..4a3f68626a 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/LocalizableStringSerializer.cs @@ -35,7 +35,12 @@ public class LocalizableStringSerializer : ILocalizableStringSerializer, ITransi public virtual ILocalizableString Deserialize(string value) { - if (value.IsNullOrEmpty() || + if (value == null) + { + throw new AbpException($"{nameof(value)} can not be null!"); + } + + if (value.IsNullOrWhiteSpace() || value.Length < 3 || value[1] != ':') { diff --git a/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/SwaggerHtmlResolver.cs b/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/SwaggerHtmlResolver.cs index 628a361826..f9b39faf1d 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/SwaggerHtmlResolver.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/SwaggerHtmlResolver.cs @@ -15,7 +15,7 @@ public class SwaggerHtmlResolver : ISwaggerHtmlResolver, ITransientDependency var html = new StreamReader(stream!) .ReadToEnd() - .Replace("SwaggerUIBundle(configObject)", "abp.SwaggerUIBundle(configObject)"); + .Replace("src=\"index.js\"", "src=\"ui/index.js\""); return new MemoryStream(Encoding.UTF8.GetBytes(html)); } diff --git a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/index.js b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/index.js new file mode 100644 index 0000000000..d7b6ebdb53 --- /dev/null +++ b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/index.js @@ -0,0 +1,75 @@ +//Copy from https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerUI/index.js + +/* Source: https://gist.github.com/lamberta/3768814 + * Parse a string function definition and return a function object. Does not use eval. + * @param {string} str + * @return {function} + * + * Example: + * var f = function (x, y) { return x * y; }; + * var g = parseFunction(f.toString()); + * g(33, 3); //=> 99 + */ +function parseFunction(str) { + if (!str) return void (0); + + var fn_body_idx = str.indexOf('{'), + fn_body = str.substring(fn_body_idx + 1, str.lastIndexOf('}')), + fn_declare = str.substring(0, fn_body_idx), + fn_params = fn_declare.substring(fn_declare.indexOf('(') + 1, fn_declare.lastIndexOf(')')), + args = fn_params.split(','); + + args.push(fn_body); + + function Fn() { + return Function.apply(this, args); + } + Fn.prototype = Function.prototype; + + return new Fn(); +} + +window.onload = function () { + var configObject = JSON.parse('%(ConfigObject)'); + var oauthConfigObject = JSON.parse('%(OAuthConfigObject)'); + + // Workaround for https://github.com/swagger-api/swagger-ui/issues/5945 + configObject.urls.forEach(function (item) { + if (item.url.startsWith("http") || item.url.startsWith("/")) return; + item.url = window.location.href.replace("index.html", item.url).split('#')[0]; + }); + + // If validatorUrl is not explicitly provided, disable the feature by setting to null + if (!configObject.hasOwnProperty("validatorUrl")) + configObject.validatorUrl = null + + // If oauth2RedirectUrl isn't specified, use the built-in default + if (!configObject.hasOwnProperty("oauth2RedirectUrl")) + configObject.oauth2RedirectUrl = (new URL("oauth2-redirect.html", window.location.href)).href; + + // Apply mandatory parameters + configObject.dom_id = "#swagger-ui"; + configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset]; + configObject.layout = "StandaloneLayout"; + + // Parse and add interceptor functions + var interceptors = JSON.parse('%(Interceptors)'); + if (interceptors.RequestInterceptorFunction) + configObject.requestInterceptor = parseFunction(interceptors.RequestInterceptorFunction); + if (interceptors.ResponseInterceptorFunction) + configObject.responseInterceptor = parseFunction(interceptors.ResponseInterceptorFunction); + + if (configObject.plugins) { + configObject.plugins = configObject.plugins.map(eval); + } + + // Begin Swagger UI call region + + const ui = abp.SwaggerUIBundle(configObject); + + ui.initOAuth(oauthConfigObject); + + // End Swagger UI call region + + window.ui = ui +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json index df75ed8799..7870ccff7b 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json @@ -21,7 +21,7 @@ "Language": "Idioma", "LoadMore": "Cargar más", "ProcessingWithThreeDot": "Procesando...", - "LoadingWithThreeDot": "Cargardo...", + "LoadingWithThreeDot": "Cargando...", "Welcome": "Bienvenido", "Login": "Iniciar sesión", "Register": "Registrarse", diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs index 609f5501a8..6d809a73bc 100644 --- a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWork.cs @@ -34,7 +34,11 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency public string? ReservationName { get; set; } protected List> CompletedHandlers { get; } = new List>(); + + protected List?>> DistributedEventWithPredicates { get; } = new List?>>(); protected List DistributedEvents { get; } = new List(); + + protected List?>> LocalEventWithPredicates { get; } = new List?>>(); protected List LocalEvents { get; } = new List(); public event EventHandler Failed = default!; @@ -135,11 +139,15 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency _isCompleting = true; await SaveChangesAsync(cancellationToken); + DistributedEvents.AddRange(GetEventsRecords(DistributedEventWithPredicates)); + LocalEvents.AddRange(GetEventsRecords(LocalEventWithPredicates)); + while (LocalEvents.Any() || DistributedEvents.Any()) { if (LocalEvents.Any()) { var localEventsToBePublished = LocalEvents.OrderBy(e => e.EventOrder).ToArray(); + LocalEventWithPredicates.Clear(); LocalEvents.Clear(); await UnitOfWorkEventPublisher.PublishLocalEventsAsync( localEventsToBePublished @@ -149,6 +157,7 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency if (DistributedEvents.Any()) { var distributedEventsToBePublished = DistributedEvents.OrderBy(e => e.EventOrder).ToArray(); + DistributedEventWithPredicates.Clear(); DistributedEvents.Clear(); await UnitOfWorkEventPublisher.PublishDistributedEventsAsync( distributedEventsToBePublished @@ -156,6 +165,9 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency } await SaveChangesAsync(cancellationToken); + + LocalEvents.AddRange(GetEventsRecords(LocalEventWithPredicates)); + DistributedEvents.AddRange(GetEventsRecords(DistributedEventWithPredicates)); } await CommitTransactionsAsync(cancellationToken); @@ -244,38 +256,44 @@ public class UnitOfWork : IUnitOfWork, ITransientDependency UnitOfWorkEventRecord eventRecord, Predicate? replacementSelector = null) { - AddOrReplaceEvent(LocalEvents, eventRecord, replacementSelector); + LocalEventWithPredicates.Add(new KeyValuePair?>(eventRecord, replacementSelector)); } public virtual void AddOrReplaceDistributedEvent( UnitOfWorkEventRecord eventRecord, Predicate? replacementSelector = null) { - AddOrReplaceEvent(DistributedEvents, eventRecord, replacementSelector); + DistributedEventWithPredicates.Add(new KeyValuePair?>(eventRecord, replacementSelector)); } - public virtual void AddOrReplaceEvent( - List eventRecords, - UnitOfWorkEventRecord eventRecord, - Predicate? replacementSelector = null) + protected virtual List GetEventsRecords(List?>> eventWithPredicates) { - if (replacementSelector == null) - { - eventRecords.Add(eventRecord); - } - else + var eventRecords = new List(); + foreach (var eventWithPredicate in eventWithPredicates) { - var foundIndex = eventRecords.FindIndex(replacementSelector); - if (foundIndex < 0) + var eventRecord = eventWithPredicate.Key; + var replacementSelector = eventWithPredicate.Value; + + if (replacementSelector == null) { eventRecords.Add(eventRecord); } else { - eventRecord.SetOrder(eventRecords[foundIndex].EventOrder); - eventRecords[foundIndex] = eventRecord; + var foundIndex = eventRecords.FindIndex(replacementSelector); + if (foundIndex < 0) + { + eventRecords.Add(eventRecord); + } + else + { + eventRecord.SetOrder(eventRecords[foundIndex].EventOrder); + eventRecords[foundIndex] = eventRecord; + } } } + + return eventRecords; } protected virtual async Task OnCompletedAsync() diff --git a/global.json b/global.json index 0344c423c0..cdbb589eda 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-rc.2.24474.11", + "version": "9.0.100", "rollForward": "latestFeature" } } diff --git a/latest-versions.json b/latest-versions.json index 4a15449c88..b99c7202b6 100644 --- a/latest-versions.json +++ b/latest-versions.json @@ -1,6 +1,6 @@ [ { - "version": "8.3.2", + "version": "9.0.0", "releaseDate": "", "type": "stable", "message": "" diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json index 7ff41d8a35..04d78b830f 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json @@ -3,8 +3,8 @@ "name": "asp.net", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "~9.0.0-rc.1", - "@abp/prismjs": "~9.0.0-rc.1", - "@abp/highlight.js": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared": "~9.0.0", + "@abp/prismjs": "~9.0.0", + "@abp/highlight.js": "~9.0.0" } } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/yarn.lock b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/yarn.lock index ea19387118..0ec23ef2e3 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/yarn.lock +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/yarn.lock @@ -2,212 +2,212 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/clipboard@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0-rc.1.tgz#6997a792bbad262ccb9351913ec668e73cae5dc0" - integrity sha512-zQ6XIAehIfPBENs8intL3ekZhl1Sgh6EOn9QgkIzgLsyrnUrXgFdOHz96TGo5ttYOIEx8L5zoR29iCSLYBjDpg== +"@abp/clipboard@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0.tgz#21ae924dfef6ccf3c8a3913bb81caf22b57404e4" + integrity sha512-W6S7pihpQ6Wfj48Clk7hYgDvUtnRwkNIsk5t8s9+LxoAdJQGQFxh7SAW1QNavUv8QqsClNE1VtSU87c7rSoAbA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" clipboard "^2.0.11" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/highlight.js@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.0.0-rc.1.tgz#6b2deccf3b8079d4f4cd7d4fb02d6ac6ad455ed0" - integrity sha512-r3stRcyfDsp+fUCC6JZq+k5U0/mhCygUF0+S9fqcoCCKEtRb0el8S0AFw8/zaWHz9RLZNRtib9JtyJl07SMJIQ== +"@abp/highlight.js@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.0.0.tgz#6d924c9bb3d6b11dcd66a9a71aea873c9866ed6c" + integrity sha512-eGvgMUNYKW2B2h3QcpMRniaoQ1/9RJBXkn2VsyM8lVSfrfbOg26mMyw7J2BXvuEnXqtnVdFEG45cSFlAnTAVXQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@highlightjs/cdn-assets" "~11.10.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/prismjs@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0-rc.1.tgz#be4f23d69f780a693d65a1eacefb2aef51c5d205" - integrity sha512-tgTo+GlBzGH1qwbzdAd+MHgf6BIbGraCQwaeuKu13EXMt1vi4vB9i14YzaZClgaQ0cxEN3+6qheejPjkWU623A== +"@abp/prismjs@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0.tgz#2ac4a5ddc0c8e0462af027a4dd97a177a3d6f7a5" + integrity sha512-+evmBq5qV+Ix/TNqO2ljJn0jygW2rEgKNtABcBGmrZC8xiI7+2hjKmSE0e43qb+RDib8aJjwH8ya8wF7p68ZFw== dependencies: - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/core" "~9.0.0-rc.1" + "@abp/clipboard" "~9.0.0" + "@abp/core" "~9.0.0" prismjs "^1.29.0" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/package.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/package.json index 4936a79ad0..8857cdc4b9 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/package.json +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/package.json @@ -3,8 +3,8 @@ "name": "asp.net", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1", - "@abp/prismjs": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0", + "@abp/prismjs": "~9.0.0" }, "devDependencies": {} } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/yarn.lock b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/yarn.lock index 8e176a1c01..01d7637c9e 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/yarn.lock +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/yarn.lock @@ -2,211 +2,211 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/clipboard@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0-rc.1.tgz#6997a792bbad262ccb9351913ec668e73cae5dc0" - integrity sha512-zQ6XIAehIfPBENs8intL3ekZhl1Sgh6EOn9QgkIzgLsyrnUrXgFdOHz96TGo5ttYOIEx8L5zoR29iCSLYBjDpg== +"@abp/clipboard@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0.tgz#21ae924dfef6ccf3c8a3913bb81caf22b57404e4" + integrity sha512-W6S7pihpQ6Wfj48Clk7hYgDvUtnRwkNIsk5t8s9+LxoAdJQGQFxh7SAW1QNavUv8QqsClNE1VtSU87c7rSoAbA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" clipboard "^2.0.11" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/prismjs@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0-rc.1.tgz#be4f23d69f780a693d65a1eacefb2aef51c5d205" - integrity sha512-tgTo+GlBzGH1qwbzdAd+MHgf6BIbGraCQwaeuKu13EXMt1vi4vB9i14YzaZClgaQ0cxEN3+6qheejPjkWU623A== +"@abp/prismjs@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0.tgz#2ac4a5ddc0c8e0462af027a4dd97a177a3d6f7a5" + integrity sha512-+evmBq5qV+Ix/TNqO2ljJn0jygW2rEgKNtABcBGmrZC8xiI7+2hjKmSE0e43qb+RDib8aJjwH8ya8wF7p68ZFw== dependencies: - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/core" "~9.0.0-rc.1" + "@abp/clipboard" "~9.0.0" + "@abp/core" "~9.0.0" prismjs "^1.29.0" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.abppkg b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.abppkg index e1c64f0175..7a73a41bfd 100644 --- a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.abppkg +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.abppkg @@ -1,3 +1,2 @@ { - "role": "lib.ef" } \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.abppkg b/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.abppkg index 8b23fd1e69..7a73a41bfd 100644 --- a/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.abppkg +++ b/modules/blogging/app/Volo.BloggingTestApp.MongoDB/Volo.BloggingTestApp.MongoDB.abppkg @@ -1,3 +1,2 @@ { - "role": "lib.mongodb" } \ No newline at end of file diff --git a/modules/blogging/app/Volo.BloggingTestApp/package.json b/modules/blogging/app/Volo.BloggingTestApp/package.json index 50db657dde..25c37cda9f 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/package.json +++ b/modules/blogging/app/Volo.BloggingTestApp/package.json @@ -3,7 +3,7 @@ "name": "volo.blogtestapp", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1", - "@abp/blogging": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0", + "@abp/blogging": "~9.0.0" } } diff --git a/modules/blogging/app/Volo.BloggingTestApp/yarn.lock b/modules/blogging/app/Volo.BloggingTestApp/yarn.lock index 4c75e091d2..4a01d58b56 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/yarn.lock +++ b/modules/blogging/app/Volo.BloggingTestApp/yarn.lock @@ -2,237 +2,237 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/blogging@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/blogging/-/blogging-9.0.0-rc.1.tgz#791ddb76ce9e0cd8074b6425979212beb8ea5da1" - integrity sha512-gkGc9LqAjVE2KnTxBJgZc0SmPV77MvGd/mkb7pPVBmB5odSFFn5iivMrnAumxzhp1GOuAuyyYjYlQQxIgsxnYg== +"@abp/blogging@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/blogging/-/blogging-9.0.0.tgz#bba9e0288e215473b1851ab58d4898a2455c2afe" + integrity sha512-tsKqEYnVhDrBHVMOwSTLR+OudEnxBpj5RhDiLPA+MO+FSqiJpuxlDI2SlH2Sz7alCF1RnAM/alITvrKq9TR/gg== dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - "@abp/owl.carousel" "~9.0.0-rc.1" - "@abp/prismjs" "~9.0.0-rc.1" - "@abp/tui-editor" "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + "@abp/owl.carousel" "~9.0.0" + "@abp/prismjs" "~9.0.0" + "@abp/tui-editor" "~9.0.0" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/clipboard@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0-rc.1.tgz#6997a792bbad262ccb9351913ec668e73cae5dc0" - integrity sha512-zQ6XIAehIfPBENs8intL3ekZhl1Sgh6EOn9QgkIzgLsyrnUrXgFdOHz96TGo5ttYOIEx8L5zoR29iCSLYBjDpg== +"@abp/clipboard@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0.tgz#21ae924dfef6ccf3c8a3913bb81caf22b57404e4" + integrity sha512-W6S7pihpQ6Wfj48Clk7hYgDvUtnRwkNIsk5t8s9+LxoAdJQGQFxh7SAW1QNavUv8QqsClNE1VtSU87c7rSoAbA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" clipboard "^2.0.11" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/owl.carousel@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/owl.carousel/-/owl.carousel-9.0.0-rc.1.tgz#eca47e03e98938de8878eca524a120a19a5d24dc" - integrity sha512-biLiqRIKCrYAfppav2q6HWGJ2pJ3PzfAxzjwSY3SgEZaFd/akfRB+nnl4X5gXoOEcsD0m/vupQw+3jyT8sdIZg== +"@abp/owl.carousel@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/owl.carousel/-/owl.carousel-9.0.0.tgz#44f6b35199940aa98b9b97bfaeb7872779133ae5" + integrity sha512-zwlrvm4wxvM/4OlUsJPhEy4I+N+wX27dwCQ640eAZirHlmRrOydAADDP964LDX6ay3PqvW8VzH/e0iEFqUBLWg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" owl.carousel "^2.3.4" -"@abp/prismjs@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0-rc.1.tgz#be4f23d69f780a693d65a1eacefb2aef51c5d205" - integrity sha512-tgTo+GlBzGH1qwbzdAd+MHgf6BIbGraCQwaeuKu13EXMt1vi4vB9i14YzaZClgaQ0cxEN3+6qheejPjkWU623A== +"@abp/prismjs@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0.tgz#2ac4a5ddc0c8e0462af027a4dd97a177a3d6f7a5" + integrity sha512-+evmBq5qV+Ix/TNqO2ljJn0jygW2rEgKNtABcBGmrZC8xiI7+2hjKmSE0e43qb+RDib8aJjwH8ya8wF7p68ZFw== dependencies: - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/core" "~9.0.0-rc.1" + "@abp/clipboard" "~9.0.0" + "@abp/core" "~9.0.0" prismjs "^1.29.0" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/tui-editor@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.0.0-rc.1.tgz#92606f96f692daf8b9be55b95ace1258d836aba2" - integrity sha512-ibsRk0fxRaNvBjmNS4kJGYpr0jDFk7EEVCjuR9QF9Eca2MPembnS5+W6xAwlsGtTfhxBhqLnA/GWG4agw2F/Xg== +"@abp/tui-editor@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.0.0.tgz#d9f7721c3d8e361d901a0e0e11e786b2e12b234a" + integrity sha512-TVadK2Yi3wlwyvEVshh1PxkNRppYmqaPB6QE1cOhrWZAFbP1fh1oFvfqQiHN3o+9RGHFcEnhEK3D+49aHuDh3Q== dependencies: - "@abp/jquery" "~9.0.0-rc.1" - "@abp/prismjs" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" + "@abp/prismjs" "~9.0.0" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json index 9848b53085..e625cd894f 100644 --- a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json +++ b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json @@ -3,6 +3,6 @@ "name": "client-simulation-web", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock index a8f2acc272..9e01130758 100644 --- a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock +++ b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock @@ -2,194 +2,194 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/cms-kit/angular/package.json b/modules/cms-kit/angular/package.json index 597190664c..898a2d3e9c 100644 --- a/modules/cms-kit/angular/package.json +++ b/modules/cms-kit/angular/package.json @@ -15,11 +15,11 @@ }, "private": true, "dependencies": { - "@abp/ng.account": "~9.0.0-rc.1", - "@abp/ng.identity": "~9.0.0-rc.1", - "@abp/ng.setting-management": "~9.0.0-rc.1", - "@abp/ng.tenant-management": "~9.0.0-rc.1", - "@abp/ng.theme.basic": "~9.0.0-rc.1", + "@abp/ng.account": "~9.0.0", + "@abp/ng.identity": "~9.0.0", + "@abp/ng.setting-management": "~9.0.0", + "@abp/ng.tenant-management": "~9.0.0", + "@abp/ng.theme.basic": "~9.0.0", "@angular/animations": "~10.0.0", "@angular/common": "~10.0.0", "@angular/compiler": "~10.0.0", diff --git a/modules/cms-kit/angular/projects/cms-kit/package.json b/modules/cms-kit/angular/projects/cms-kit/package.json index c3a211518d..a7ab8c38c1 100644 --- a/modules/cms-kit/angular/projects/cms-kit/package.json +++ b/modules/cms-kit/angular/projects/cms-kit/package.json @@ -4,8 +4,8 @@ "peerDependencies": { "@angular/common": "^9.1.11", "@angular/core": "^9.1.11", - "@abp/ng.core": ">=9.0.0-rc.1", - "@abp/ng.theme.shared": ">=9.0.0-rc.1" + "@abp/ng.core": ">=9.0.0", + "@abp/ng.theme.shared": ">=9.0.0" }, "dependencies": { "tslib": "^2.0.0" diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json index 589220f2e7..0150cbe740 100644 --- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json +++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/package.json @@ -3,6 +3,6 @@ "name": "my-app-identityserver", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock index a8f2acc272..9e01130758 100644 --- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock +++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock @@ -2,194 +2,194 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Host/package.json b/modules/cms-kit/host/Volo.CmsKit.Web.Host/package.json index 57114aba35..8b5210b25f 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Host/package.json +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Host/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Host/yarn.lock b/modules/cms-kit/host/Volo.CmsKit.Web.Host/yarn.lock index a8f2acc272..9e01130758 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Host/yarn.lock +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Host/yarn.lock @@ -2,194 +2,194 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json index f05446294e..5619ca083e 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1", - "@abp/cms-kit": "9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0", + "@abp/cms-kit": "9.0.0" } } diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock index 5e88660800..3c5c5f9e97 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock @@ -2,302 +2,302 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/clipboard@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0-rc.1.tgz#6997a792bbad262ccb9351913ec668e73cae5dc0" - integrity sha512-zQ6XIAehIfPBENs8intL3ekZhl1Sgh6EOn9QgkIzgLsyrnUrXgFdOHz96TGo5ttYOIEx8L5zoR29iCSLYBjDpg== +"@abp/clipboard@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0.tgz#21ae924dfef6ccf3c8a3913bb81caf22b57404e4" + integrity sha512-W6S7pihpQ6Wfj48Clk7hYgDvUtnRwkNIsk5t8s9+LxoAdJQGQFxh7SAW1QNavUv8QqsClNE1VtSU87c7rSoAbA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" clipboard "^2.0.11" -"@abp/cms-kit.admin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/cms-kit.admin/-/cms-kit.admin-9.0.0-rc.1.tgz#8c8eae7bc91aadd8a2ac5f3fde70da14f6facfbd" - integrity sha512-DHOkQ6qnLrOioj/jnLmM0F8bHm8XwKbmoHN2ZsMq23QgUar0RNVix1t+awM7YKehzaP83vK+dodl8r+3hkAIyA== +"@abp/cms-kit.admin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/cms-kit.admin/-/cms-kit.admin-9.0.0.tgz#584337c9d751c9eae26be8f276683b5c3c23a499" + integrity sha512-SYixIuy7McA9UhaKmun8IG0QBmegvk8KBrE/6Uvo1Cmd6Z/oT9SS+i/f09+7UVtU+7x5kkL+9sIs/7sS79cY0g== dependencies: - "@abp/codemirror" "~9.0.0-rc.1" - "@abp/jstree" "~9.0.0-rc.1" - "@abp/markdown-it" "~9.0.0-rc.1" - "@abp/slugify" "~9.0.0-rc.1" - "@abp/tui-editor" "~9.0.0-rc.1" - "@abp/uppy" "~9.0.0-rc.1" + "@abp/codemirror" "~9.0.0" + "@abp/jstree" "~9.0.0" + "@abp/markdown-it" "~9.0.0" + "@abp/slugify" "~9.0.0" + "@abp/tui-editor" "~9.0.0" + "@abp/uppy" "~9.0.0" -"@abp/cms-kit.public@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/cms-kit.public/-/cms-kit.public-9.0.0-rc.1.tgz#c6823d831e8e444d792b64e754c2d932ced850e5" - integrity sha512-DNo/u+OYQ+oCBmHwi12cBqA1ftBzAe8B5Aj6IQzegxQoMPPuav7WQVWoQuvZ0200CPmLr3gLTIBmmLHV9p7FFg== +"@abp/cms-kit.public@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/cms-kit.public/-/cms-kit.public-9.0.0.tgz#bdc8f60bc5b1ffa640baced8c5562f93f7e8b754" + integrity sha512-s141fUfN9rcRdT4KKjR7PthITnFSx6RXrxPaXiOfNXPdnVQmgKRg7HhO92KJQKO+CeYbiMNO3Fpt9MSffvkEJQ== dependencies: - "@abp/highlight.js" "~9.0.0-rc.1" - "@abp/star-rating-svg" "~9.0.0-rc.1" + "@abp/highlight.js" "~9.0.0" + "@abp/star-rating-svg" "~9.0.0" -"@abp/cms-kit@9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/cms-kit/-/cms-kit-9.0.0-rc.1.tgz#4b2d5a45c3b273c7620ba2448dace2b195916845" - integrity sha512-/EYtwoLqEGi7603J0Y+wPT9EBN5iKq3kud6ObWFSq+pxGUu6OcRM/UBx/XjYHd8FndzS8rnLMao6kFjBFfSMag== +"@abp/cms-kit@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/cms-kit/-/cms-kit-9.0.0.tgz#19364cf6ccfbf6ec927c21ce302a85dfe4215f1b" + integrity sha512-ZjakEuhKvDh1r3tVnDUxkQWj+9TJuqaFEI2vEiHysB81rM5mqKaOtATfhtC75CN5LDqiKCAzDs+6ty4YmTe1PQ== dependencies: - "@abp/cms-kit.admin" "~9.0.0-rc.1" - "@abp/cms-kit.public" "~9.0.0-rc.1" + "@abp/cms-kit.admin" "~9.0.0" + "@abp/cms-kit.public" "~9.0.0" -"@abp/codemirror@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/codemirror/-/codemirror-9.0.0-rc.1.tgz#6c063c405eb6c0e5858c738e26ec7326fab9250b" - integrity sha512-lpywCpqV7krfcpnc7qCO13sXFaIAS2qFQIrhmDD6BMleU7XDGVFTj4QAO/TmcsPU4dLC4JRPwYQTZatzuEyIvg== +"@abp/codemirror@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/codemirror/-/codemirror-9.0.0.tgz#d398edce6ececdaf1f62e216f98a91b26fb595bd" + integrity sha512-tXcdoXjpco8VnjE/on4ax9USfz3lu03Y+TehAt1tbVQRBdhkGL+qFB/MrewRKUNM8TjSewuT7D4RxpmThABpNw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" codemirror "^5.65.1" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/highlight.js@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.0.0-rc.1.tgz#6b2deccf3b8079d4f4cd7d4fb02d6ac6ad455ed0" - integrity sha512-r3stRcyfDsp+fUCC6JZq+k5U0/mhCygUF0+S9fqcoCCKEtRb0el8S0AFw8/zaWHz9RLZNRtib9JtyJl07SMJIQ== +"@abp/highlight.js@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.0.0.tgz#6d924c9bb3d6b11dcd66a9a71aea873c9866ed6c" + integrity sha512-eGvgMUNYKW2B2h3QcpMRniaoQ1/9RJBXkn2VsyM8lVSfrfbOg26mMyw7J2BXvuEnXqtnVdFEG45cSFlAnTAVXQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@highlightjs/cdn-assets" "~11.10.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/jstree@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jstree/-/jstree-9.0.0-rc.1.tgz#2637d318cf60b6eb8f7557befa41ecc1ef1500d4" - integrity sha512-3MSE0Hy/hXWxhkr293RfUPnMQq8jAF7YGk4ziVw2Wqzxmux/3YWIYxMErF/tlXmUTd2y+jsr6sNOa/8rxsiNeg== +"@abp/jstree@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jstree/-/jstree-9.0.0.tgz#08190074df54e45fe414b7a349c25d6b1f1058a1" + integrity sha512-ZbXPazP2Yy/qDMw/b4U8Hz1ZxbxQej/PAREaAawd2R2GJoGi10U8iTt5WKJJQP8Fm42kFgQa/8EtVcckwIo4FA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jstree "^3.3.17" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/markdown-it@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/markdown-it/-/markdown-it-9.0.0-rc.1.tgz#f48d7cbea9f6c17611a913e01e0e76d2abb2e3ec" - integrity sha512-TKYFAf7jFGCZGjcuYbVWNtFnrGGMgjCJ4cWLMKbAyDNyci3+mDHCZSLbiIefPXZI1dnnzZkXGPB9dRNai98YGA== +"@abp/markdown-it@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/markdown-it/-/markdown-it-9.0.0.tgz#f61e74e7f9205f3015074896cf184f90b8a11a1c" + integrity sha512-frjJ539DiM4H0nHwnt77T1ryoazJhy9836L7HEFiYsfXJHs92VohUr/K27899I3gRdA6h0tbLYumFK3ug83qiw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" markdown-it "^14.1.0" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/prismjs@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0-rc.1.tgz#be4f23d69f780a693d65a1eacefb2aef51c5d205" - integrity sha512-tgTo+GlBzGH1qwbzdAd+MHgf6BIbGraCQwaeuKu13EXMt1vi4vB9i14YzaZClgaQ0cxEN3+6qheejPjkWU623A== +"@abp/prismjs@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0.tgz#2ac4a5ddc0c8e0462af027a4dd97a177a3d6f7a5" + integrity sha512-+evmBq5qV+Ix/TNqO2ljJn0jygW2rEgKNtABcBGmrZC8xiI7+2hjKmSE0e43qb+RDib8aJjwH8ya8wF7p68ZFw== dependencies: - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/core" "~9.0.0-rc.1" + "@abp/clipboard" "~9.0.0" + "@abp/core" "~9.0.0" prismjs "^1.29.0" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/slugify@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/slugify/-/slugify-9.0.0-rc.1.tgz#912ba3024c4e5551d990633c4ebf3b2f115494a9" - integrity sha512-cnccOxIfqBcKh63jyQ7PEUJ3b8oZyZxhKwPTOVhFk+jvrkUovlPG0RLvFD/BkNK0oPvqnnEfk6qp5Cg0xndZ7g== +"@abp/slugify@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/slugify/-/slugify-9.0.0.tgz#4bf4cade338697b68502cc73ac830d8dab10bbb8" + integrity sha512-tjHsQndDNDsQYubzQY8d+I/o1pQx4ehaSIw6xt0WyozogRegrxQ9QJUxOEQYtfNAgap0GipnxxvZSRBJINB4Cg== dependencies: slugify "^1.6.6" -"@abp/star-rating-svg@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/star-rating-svg/-/star-rating-svg-9.0.0-rc.1.tgz#9f48d7fd8bf6e93beec49ebd8ac6e2a0daa6ce41" - integrity sha512-zmoQ+4voxzH4UNW36otg4wv20/zaDcf31qA0b405repzcwcxAvoafbWTMQF44DToJmbuxjjvGvEsxGDx+mawlg== +"@abp/star-rating-svg@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/star-rating-svg/-/star-rating-svg-9.0.0.tgz#1e0d2ca6e589d3f7b63e6cfe6f7ad6c723f86a81" + integrity sha512-OZtWoFG2n5KdnSYeMH4SMYaeET3ISmyREBy5rNVM4peacNejyEHrPadzHDMWcGFMjqveTn/jmN19Jyn9+HG0Vw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" star-rating-svg "^3.5.0" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/tui-editor@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.0.0-rc.1.tgz#92606f96f692daf8b9be55b95ace1258d836aba2" - integrity sha512-ibsRk0fxRaNvBjmNS4kJGYpr0jDFk7EEVCjuR9QF9Eca2MPembnS5+W6xAwlsGtTfhxBhqLnA/GWG4agw2F/Xg== +"@abp/tui-editor@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.0.0.tgz#d9f7721c3d8e361d901a0e0e11e786b2e12b234a" + integrity sha512-TVadK2Yi3wlwyvEVshh1PxkNRppYmqaPB6QE1cOhrWZAFbP1fh1oFvfqQiHN3o+9RGHFcEnhEK3D+49aHuDh3Q== dependencies: - "@abp/jquery" "~9.0.0-rc.1" - "@abp/prismjs" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" + "@abp/prismjs" "~9.0.0" -"@abp/uppy@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/uppy/-/uppy-9.0.0-rc.1.tgz#8d427cdf838ba15b14d771e371bbc0674edfb201" - integrity sha512-Bf8z+mp5DkaOiQhbNwTdMgjoXT31Bynf+RoyzqU2dzzW8lsf5Y2svk8sEKYgwp7/9oatqiMP0Cy3jpBNT2obvg== +"@abp/uppy@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/uppy/-/uppy-9.0.0.tgz#4def1e889093a4299f1c2445a87793cb3da2d4d7" + integrity sha512-Y9IbGu/t3rJefF7FSrsiHs9V+C/lAMtolivPwKhnOzxmUtoxbyc0O2W2uExZEihevbnk3PWe7dkFY5mZ30i6BA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" uppy "^4.4.1" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs index 0245b1348e..93c5374281 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/BlogDto.cs @@ -11,4 +11,6 @@ public class BlogDto : ExtensibleEntityDto, IHasConcurrencyStamp public string Slug { get; set; } public string ConcurrencyStamp { get; set; } + + public int BlogPostCount { get; set; } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs index 647c2bde15..e0f2b3311b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/Blogs/IBlogAdminAppService.cs @@ -1,8 +1,13 @@ using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; namespace Volo.CmsKit.Admin.Blogs; public interface IBlogAdminAppService : ICrudAppService { + Task> GetAllListAsync(); + + Task MoveAllBlogPostsAsync(Guid blogId, Guid? assignToBlogId = null); } 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 d5f32c4bfc..e3ef03e2de 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,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Dtos; @@ -20,16 +21,19 @@ namespace Volo.CmsKit.Admin.Blogs; public class BlogAdminAppService : CmsKitAdminAppServiceBase, IBlogAdminAppService { protected IBlogRepository BlogRepository { get; } + protected IBlogPostRepository BlogPostRepository { get; } protected BlogManager BlogManager { get; } protected BlogFeatureManager BlogFeatureManager { get; } public BlogAdminAppService( IBlogRepository blogRepository, - BlogManager blogManager, + BlogManager blogManager, + IBlogPostRepository blogPostRepository, BlogFeatureManager blogFeatureManager = null) { BlogRepository = blogRepository; BlogManager = blogManager; + BlogPostRepository = blogPostRepository; BlogFeatureManager = blogFeatureManager; } @@ -37,20 +41,44 @@ public class BlogAdminAppService : CmsKitAdminAppServiceBase, IBlogAdminAppServi { var blog = await BlogRepository.GetAsync(id); - return ObjectMapper.Map(blog); + var blogDto = ObjectMapper.Map(blog); + blogDto.BlogPostCount = await BlogPostRepository.GetCountAsync(blogId : blog.Id); + + return blogDto; } public virtual async Task> GetListAsync(BlogGetListInput input) { var totalCount = await BlogRepository.GetCountAsync(input.Filter); - var blogs = await BlogRepository.GetListAsync( + var blogs = await BlogRepository.GetListWithBlogPostCountAsync( input.Filter, input.Sorting, input.MaxResultCount, input.SkipCount); + + var blogDtos = new PagedResultDto(totalCount, ObjectMapper.Map, List>(blogs.Select(x => x.Blog).ToList())); + + foreach (var blogDto in blogDtos.Items) + { + blogDto.BlogPostCount = blogs.First(x => x.Blog.Id == blogDto.Id).BlogPostCount; + } - return new PagedResultDto(totalCount, ObjectMapper.Map, List>(blogs)); + return blogDtos; + } + + public virtual async Task> GetAllListAsync() + { + var blogs = await BlogRepository.GetListWithBlogPostCountAsync(maxResultCount: int.MaxValue); + + var blogDtos = new ListResultDto(ObjectMapper.Map, List>(blogs.Select(x => x.Blog).ToList())); + + foreach (var blogDto in blogDtos.Items) + { + blogDto.BlogPostCount = blogs.First(x => x.Blog.Id == blogDto.Id).BlogPostCount; + } + + return blogDtos; } [Authorize(CmsKitAdminPermissions.Blogs.Create)] @@ -79,10 +107,18 @@ public class BlogAdminAppService : CmsKitAdminAppServiceBase, IBlogAdminAppServi return ObjectMapper.Map(blog); } + + [Authorize(CmsKitAdminPermissions.Blogs.Delete)] + public virtual async Task MoveAllBlogPostsAsync(Guid blogId, Guid? assignToBlogId) + { + var blog = await BlogRepository.GetAsync(blogId); + await BlogPostRepository.UpdateBlogAsync(blog.Id, assignToBlogId); + } [Authorize(CmsKitAdminPermissions.Blogs.Delete)] public virtual Task DeleteAsync(Guid id) { + return BlogRepository.DeleteAsync(id); } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs index a6a0d6512a..60f8ccb8a8 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/CmsKitAdminApplicationAutoMapperProfile.cs @@ -38,7 +38,7 @@ public class CmsKitAdminApplicationAutoMapperProfile : Profile CreateMap(MemberList.Source).MapExtraProperties(); CreateMap(MemberList.Source).MapExtraProperties(); - CreateMap().MapExtraProperties(); + CreateMap().Ignore(b => b.BlogPostCount).MapExtraProperties(); CreateMap(MemberList.Destination); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Blogs/BlogAdminClientProxy.Generated.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Blogs/BlogAdminClientProxy.Generated.cs index d102ea4d1f..7eb5d91f3b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Blogs/BlogAdminClientProxy.Generated.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/Volo/CmsKit/Admin/Blogs/BlogAdminClientProxy.Generated.cs @@ -57,4 +57,18 @@ public partial class BlogAdminClientProxy : ClientProxyBase> GetAllListAsync() + { + return await RequestAsync>(nameof(GetAllListAsync)); + } + + public virtual async Task MoveAllBlogPostsAsync(Guid blogId, Guid? assignToBlogId) + { + await RequestAsync(nameof(MoveAllBlogPostsAsync), new ClientProxyRequestTypeValue + { + { typeof(Guid), blogId }, + { typeof(Guid?), assignToBlogId } + }); + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json index cf4bbd1034..8f0e7e677d 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi.Client/ClientProxies/cms-kit-admin-generate-proxy.json @@ -16,6 +16,39 @@ "type": "Volo.CmsKit.Admin.Blogs.IBlogAdminAppService", "name": "IBlogAdminAppService", "methods": [ + { + "name": "GetAllListAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.ListResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" + } + }, + { + "name": "MoveAllBlogPostsAsync", + "parametersOnMethod": [ + { + "name": "blogId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "assignToBlogId", + "typeAsString": "System.Nullable`1[[System.Guid, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib", + "type": "System.Guid?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, { "name": "GetAsync", "parametersOnMethod": [ @@ -353,6 +386,90 @@ }, "allowAnonymous": false, "implementFrom": "Volo.Abp.Application.Services.IDeleteAppService" + }, + "GetAllListAsync": { + "uniqueName": "GetAllListAsync", + "name": "GetAllListAsync", + "httpMethod": "GET", + "url": "api/cms-kit-admin/blogs/all", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.ListResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogAdminAppService" + }, + "MoveAllBlogPostsAsyncByBlogIdAndAssignToBlogId": { + "uniqueName": "MoveAllBlogPostsAsyncByBlogIdAndAssignToBlogId", + "name": "MoveAllBlogPostsAsync", + "httpMethod": "PUT", + "url": "api/cms-kit-admin/blogs/{id}/move-all-blog-posts", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "blogId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "assignToBlogId", + "typeAsString": "System.Nullable`1[[System.Guid, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib", + "type": "System.Guid?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "blogId", + "name": "blogId", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "" + }, + { + "nameOnMethod": "assignToBlogId", + "name": "assignToBlogId", + "jsonName": null, + "type": "System.Guid?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Query", + "descriptorName": "" + }, + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": null, + "typeSimple": null, + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": false, + "implementFrom": "Volo.CmsKit.Admin.Blogs.IBlogAdminAppService" } } }, 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 e7d59ddbcd..f90215ed38 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 @@ -62,4 +62,19 @@ public class BlogAdminController : CmsKitAdminController, IBlogAdminAppService { return BlogAdminAppService.DeleteAsync(id); } + + [HttpGet] + [Route("all")] + public Task> GetAllListAsync() + { + return BlogAdminAppService.GetAllListAsync(); + } + + [HttpPut] + [Route("{id}/move-all-blog-posts")] + [Authorize(CmsKitAdminPermissions.Blogs.Delete)] + public Task MoveAllBlogPostsAsync(Guid blogId, [FromQuery]Guid? assignToBlogId) + { + return BlogAdminAppService.MoveAllBlogPostsAsync(blogId, assignToBlogId); + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/DeleteBlogModal.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/DeleteBlogModal.cshtml new file mode 100644 index 0000000000..5f32d8e9bf --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/DeleteBlogModal.cshtml @@ -0,0 +1,59 @@ +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs +@using Volo.CmsKit.Localization +@model DeleteBlogModal +@inject IHtmlLocalizer L +@{ + Layout = null; +} + +
    + @{ + var deleteAllClicked = "checked"; + var deleteButtonDisabled = ""; + + + + + + +

    @L.GetString("BlogDeletionConfirmationMessage", Model.Blog.Name).Value

    + + @if (Model.Blog.BlogPostCount > 0) + { +

    @L.GetString("ChooseAnActionForBlog", Model.Blog.BlogPostCount).Value

    + + + if (Model.Blog.OtherBlogs.Any()) + { + deleteAllClicked = ""; + deleteButtonDisabled = "disabled"; +
    + + +
    + + } + +
    + + +
    + } +
    + + + + +
    + } + +
    diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/DeleteBlogModal.cshtml.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/DeleteBlogModal.cshtml.cs new file mode 100644 index 0000000000..08e320b6f5 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/DeleteBlogModal.cshtml.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Volo.Abp.ObjectExtending; +using Volo.CmsKit.Admin.Blogs; + +namespace Volo.CmsKit.Admin.Web.Pages.CmsKit.Blogs; + +public class DeleteBlogModal : CmsKitAdminPageModel +{ + [BindProperty] + public BlogInfoModel Blog { get; set; } + + protected IBlogAdminAppService BlogAdminAppService { get; } + + public DeleteBlogModal(IBlogAdminAppService blogAdminAppService) + { + BlogAdminAppService = blogAdminAppService; + } + + public virtual async Task OnGetAsync(Guid id) + { + var blog = await BlogAdminAppService.GetAsync(id); + var allBlogs = await BlogAdminAppService.GetAllListAsync(); + + Blog = new BlogInfoModel + { + Id = blog.Id, + Name = blog.Name, + BlogPostCount = blog.BlogPostCount, + OtherBlogs = allBlogs.Items.Where(b => b.Id != blog.Id).Select(e => new KeyValuePair(e.Id, e.Name)).ToList() + }; + } + + public virtual async Task OnPostAsync() + { + await BlogAdminAppService.MoveAllBlogPostsAsync(Blog.Id, Blog.AssignToBlogId); + await BlogAdminAppService.DeleteAsync(Blog.Id); + return NoContent(); + } + + public class BlogInfoModel : ExtensibleObject + { + public Guid Id { get; set; } + + public string Name { get; set; } + + public int BlogPostCount { get; set; } + + public List> OtherBlogs { get; set; } + + public Guid? AssignToBlogId { get; set; } + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/index.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/index.js index 0ead857f17..eef9af3f09 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/index.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Blogs/index.js @@ -6,6 +6,35 @@ $(function () { var updateModal = new abp.ModalManager({ viewUrl: abp.appPath + "CmsKit/Blogs/UpdateModal", modalClass: 'updateBlog' }); var featuresModal = new abp.ModalManager(abp.appPath + "CmsKit/Blogs/FeaturesModal"); + + var deleteBlogModal = new abp.ModalManager(abp.appPath + 'CmsKit/Blogs/DeleteBlogModal'); + + deleteBlogModal.onResult(function(){ + abp.notify.success(l('DeletedSuccessfully')); + }); + + deleteBlogModal.onOpen(function () { + var $form = deleteBlogModal.getForm(); + $form.find('#assign').click(function () { + $form.find('#Blog_AssignToBlogId').show(); + $form.find('[type=submit]').attr("disabled","disabled") + }) + $form.find('#deleteAll').click(function () { + $form.find('#Blog_AssignToBlogId').hide(); + $form.find('#Blog_AssignToBlogId').val(""); + $form.find('[type=submit]').removeAttr("disabled"); + }) + + $("#Blog_AssignToBlogId").on("change", function () { + var val = $(this).val(); + if(val === ''){ + $form.find('[type=submit]').attr("disabled","disabled") + }else{ + $form.find('[type=submit]').removeAttr("disabled"); + } + }) + }) + var blogsService = volo.cmsKit.admin.blogs.blogAdmin; var dataTable = $("#BlogsTable").DataTable(abp.libs.datatables.normalizeConfiguration({ @@ -41,16 +70,10 @@ $(function () { { text: l('Delete'), visible: abp.auth.isGranted('CmsKit.Blogs.Delete'), - confirmMessage: function (data) { - return l("BlogDeletionConfirmationMessage", data.record.name) - }, action: function (data) { - blogsService - .delete(data.record.id) - .then(function () { - dataTable.ajax.reloadEx(); - abp.notify.success(l('DeletedSuccessfully')); - }); + deleteBlogModal.open({ + id: data.record.id + }); } } ] @@ -74,6 +97,7 @@ $(function () { createModal.open(); }); + createModal.onResult(function () { dataTable.ajax.reloadEx(); }); @@ -81,4 +105,8 @@ $(function () { updateModal.onResult(function () { dataTable.ajax.reloadEx(); }); + + deleteBlogModal.onResult(function () { + dataTable.ajax.reloadEx(); + }); }); \ No newline at end of file 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 c86c314d87..1236f52999 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 @@ -237,6 +237,10 @@ "CssClass": "فئة CSS", "TagsHelpText": "يجب أن تكون العلامات مفصولة بفواصل (على سبيل المثال: tag1، tag2، tag3)", "ThisPartOfContentCouldntBeLoaded": "لا يمكن تحميل هذا الجزء من المحتوى.", - "DuplicateCommentAttemptMessage": "تم اكتشاف محاولة نشر تعليق مكررة. لقد تم بالفعل تقديم تعليقك." + "DuplicateCommentAttemptMessage": "تم اكتشاف محاولة نشر تعليق مكررة. لقد تم بالفعل تقديم تعليقك.", + "ChooseAnActionForBlog": "اختر إجراءً للمدونة", + "AssignBlogPostsToOtherBlog": "تعيين مشاركات المدونة إلى مدونة أخرى", + "SelectAnBlogToAssign": "حدد مدونة لتعيين مشاركات المدونة إليها", + "DeleteAllBlogPostsOfThisBlog": "حذف جميع مشاركات المدونة" } } \ No newline at end of file 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 c4534837fa..946336668f 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 @@ -227,6 +227,10 @@ "CssClass": "Třída CSS", "TagsHelpText": "Značky by měly být odděleny čárkami (např.: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Tato část obsahu nemohla být načtena.", - "DuplicateCommentAttemptMessage": "Byl zjištěn duplicitní pokus o vložení komentáře. Váš komentář již byl odeslán." + "DuplicateCommentAttemptMessage": "Byl zjištěn duplicitní pokus o vložení komentáře. Váš komentář již byl odeslán.", + "ChooseAnActionForBlog": "Vyberte akci pro blog", + "AssignBlogPostsToOtherBlog": "Přiřaďte blogové příspěvky k jinému blogu", + "SelectAnBlogToAssign": "Vyberte blog, ke kterému chcete přiřadit blogové příspěvky", + "DeleteAllBlogPostsOfThisBlog": "Smazat všechny blogové příspěvky tohoto blogu" } } \ No newline at end of file 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 98b8b731c4..49b5f96ff5 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 @@ -161,6 +161,10 @@ "YourFullName": "Ihren vollständigen Namen", "YourMessage": "Ihre Nachricht", "YourReply": "Ihre Antwort", - "ThisPartOfContentCouldntBeLoaded": "Dieser Teil des Inhalts konnte nicht geladen werden." + "ThisPartOfContentCouldntBeLoaded": "Dieser Teil des Inhalts konnte nicht geladen werden.", + "ChooseAnActionForBlog": "Wählen Sie eine Aktion für den Blog", + "AssignBlogPostsToOtherBlog": "Blogbeiträge einem anderen Blog zuweisen", + "SelectAnBlogToAssign": "Wählen Sie einen Blog aus, um Blogbeiträge zuzuweisen", + "DeleteAllBlogPostsOfThisBlog": "Alle Blogbeiträge dieses Blogs löschen" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de.json index 31bae240c3..e950983d9c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/de.json @@ -227,6 +227,10 @@ "CssClass": "CSS-Klasse", "TagsHelpText": "Tags sollten durch Kommas getrennt werden (z. B. Tag1, Tag2, Tag3).", "ThisPartOfContentCouldntBeLoaded": "Dieser Teil des Inhalts konnte nicht geladen werden.", - "DuplicateCommentAttemptMessage": "Es wurde versucht, einen doppelten Kommentar zu posten. Ihr Kommentar wurde bereits übermittelt." + "DuplicateCommentAttemptMessage": "Es wurde versucht, einen doppelten Kommentar zu posten. Ihr Kommentar wurde bereits übermittelt.", + "ChooseAnActionForBlog": "Wählen Sie eine Aktion für den Blog", + "AssignBlogPostsToOtherBlog": "Blogbeiträge einem anderen Blog zuweisen", + "SelectAnBlogToAssign": "Wählen Sie einen Blog aus, um Blogbeiträge zuzuweisen", + "DeleteAllBlogPostsOfThisBlog": "Alle Blogbeiträge dieses Blogs löschen" } } \ No newline at end of file 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 695cdd21eb..5c3bd58461 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 @@ -184,6 +184,10 @@ "SelectAStatus": "Επιλέξτε μια κατάσταση", "Status": "Κατάσταση", "CmsKit.BlogPost.ScrollIndex": "Γραμμή γρήγορης πλοήγησης σε αναρτήσεις ιστολογίου", - "ThisPartOfContentCouldntBeLoaded": "Αυτό το τμήμα του περιεχομένου δεν μπορούσε να φορτωθεί." + "ThisPartOfContentCouldntBeLoaded": "Αυτό το τμήμα του περιεχομένου δεν μπορούσε να φορτωθεί.", + "ChooseAnActionForBlog": "Επιλέξτε μια ενέργεια για το ιστολόγιο", + "AssignBlogPostsToOtherBlog": "Ανάθεση αναρτήσεων ιστολογίου σε άλλο ιστολόγιο", + "SelectAnBlogToAssign": "Επιλέξτε ένα ιστολόγιο για να αναθέσετε αναρτήσεις ιστολογίου", + "DeleteAllBlogPostsOfThisBlog": "Διαγραφή όλων των αναρτήσεων ιστολογίου αυτού του ιστολογίου" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en-GB.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en-GB.json index f6256d81ba..b8b9060f45 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en-GB.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/en-GB.json @@ -28,6 +28,10 @@ "Undo": "Undo", "Update": "Update", "YourComment": "Your comment", - "YourReply": "Your reply" + "YourReply": "Your reply", + "ChooseAnActionForBlog": "Choose an action for the blog", + "AssignBlogPostsToOtherBlog": "Assign blog posts to another blog", + "SelectAnBlogToAssign": "Select a blog to assign", + "DeleteAllBlogPostsOfThisBlog": "Delete all blog posts of this blog" } } \ No newline at end of file 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 149f1072bf..596b9250f6 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 @@ -255,6 +255,10 @@ "CommentAlertMessage": "There are {0} comments waiting for approval", "Settings:Menu:CmsKit": "CMS", "CommentsAwaitingApproval": "Comments Awaiting Approval", - "CommentSubmittedForApproval": "Your comment has been submitted for approval." + "CommentSubmittedForApproval": "Your comment has been submitted for approval.", + "ChooseAnActionForBlog": "Choose an action for the blog", + "AssignBlogPostsToOtherBlog": "Assign blog posts to another blog", + "SelectAnBlogToAssign": "Select a blog to assign", + "DeleteAllBlogPostsOfThisBlog": "Delete all blog posts of this blog" } } \ 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 e1ff8d7fc8..ffe5b410be 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 @@ -227,6 +227,10 @@ "CssClass": "Clase CSS", "TagsHelpText": "Las etiquetas deben estar separadas por comas (por ejemplo: etiqueta1, etiqueta2, etiqueta3)", "ThisPartOfContentCouldntBeLoaded": "Esta parte del contenido no se pudo cargar.", - "DuplicateCommentAttemptMessage": "Intento de publicación de comentario duplicado detectado. Tu comentario ya ha sido enviado." + "DuplicateCommentAttemptMessage": "Intento de publicación de comentario duplicado detectado. Tu comentario ya ha sido enviado.", + "ChooseAnActionForBlog": "Elija una acción para el blog", + "AssignBlogPostsToOtherBlog": "Asignar publicaciones de blog a otro blog", + "SelectAnBlogToAssign": "Seleccione un blog para asignar publicaciones de blog", + "DeleteAllBlogPostsOfThisBlog": "Eliminar todas las publicaciones de blog de este blog" } } \ No newline at end of file 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 e044cde1a5..fa6695709d 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 @@ -183,6 +183,10 @@ "Status": "وضعیت", "CmsKit.BlogPost.ScrollIndex": "نوار پیمایش سریع در پست های وبلاگ", "CmsKit.BlogPost.PreventXssFeature": "جلوگیری از XSS", - "ThisPartOfContentCouldntBeLoaded": "این قسمت از محتوا قابل بارگیری نیست." + "ThisPartOfContentCouldntBeLoaded": "این قسمت از محتوا قابل بارگیری نیست.", + "ChooseAnActionForBlog": "یک عمل برای وبلاگ انتخاب کنید", + "AssignBlogPostsToOtherBlog": "پست های وبلاگ را به وبلاگ دیگری اختصاص دهید", + "SelectAnBlogToAssign": "یک وبلاگ برای اختصاص دادن انتخاب کنید", + "DeleteAllBlogPostsOfThisBlog": "تمام پست های وبلاگ این وبلاگ را حذف کنید" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/fi.json index 82d622f05f..f13dc7620c 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 @@ -227,6 +227,10 @@ "CssClass": "CSS-luokka", "TagsHelpText": "Tunnisteet on erotettava pilkuilla (esim. tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Tämä sisällön osa ei voitu ladata.", - "DuplicateCommentAttemptMessage": "Kopiokommenttiyritys havaittiin. Kommenttisi on jo lähetetty." + "DuplicateCommentAttemptMessage": "Kopiokommenttiyritys havaittiin. Kommenttisi on jo lähetetty.", + "ChooseAnActionForBlog": "Valitse toiminto blogille", + "AssignBlogPostsToOtherBlog": "Määritä blogiviestit toiseen blogiin", + "SelectAnBlogToAssign": "Valitse blogi, johon haluat määrittää", + "DeleteAllBlogPostsOfThisBlog": "Poista tämän blogin kaikki blogiviestit" } } \ No newline at end of file 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 634c1fec85..f2828aa40e 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 @@ -227,6 +227,10 @@ "CssClass": "Classe CSS", "TagsHelpText": "Les balises doivent être séparées par des virgules (par exemple : tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Cette partie du contenu n'a pas pu être chargée.", - "DuplicateCommentAttemptMessage": "Tentative de publication de commentaire en double détectée. Votre commentaire a déjà été soumis." + "DuplicateCommentAttemptMessage": "Tentative de publication de commentaire en double détectée. Votre commentaire a déjà été soumis.", + "ChooseAnActionForBlog": "Choisissez une action pour le blog", + "AssignBlogPostsToOtherBlog": "Attribuer des articles de blog à un autre blog", + "SelectAnBlogToAssign": "Sélectionnez un blog à attribuer", + "DeleteAllBlogPostsOfThisBlog": "Supprimer tous les articles de blog de ce blog" } } \ No newline at end of file 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 dcea398df5..ad2dbc18d9 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 @@ -227,6 +227,10 @@ "CssClass": "सीएसएस क्लास", "TagsHelpText": "टैग को अल्पविराम से अलग किया जाना चाहिए (जैसे: टैग1, टैग2, टैग3)", "ThisPartOfContentCouldntBeLoaded": "यह भाग लोड नहीं किया जा सका।", - "DuplicateCommentAttemptMessage": "डुप्लिकेट टिप्पणी पोस्ट प्रयास का पता चला। आपकी टिप्पणी पहले ही सबमिट की जा चुकी है." + "DuplicateCommentAttemptMessage": "डुप्लिकेट टिप्पणी पोस्ट प्रयास का पता चला। आपकी टिप्पणी पहले ही सबमिट की जा चुकी है.", + "ChooseAnActionForBlog": "ब्लॉग के लिए कोई कार्रवाई चुनें", + "AssignBlogPostsToOtherBlog": "अन्य ब्लॉग को ब्लॉग पोस्ट असाइन करें", + "SelectAnBlogToAssign": "असाइन करने के लिए एक ब्लॉग चुनें", + "DeleteAllBlogPostsOfThisBlog": "इस ब्लॉग के सभी ब्लॉग पोस्ट हटाएं" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hr.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hr.json index d2dff83aee..8e35745e21 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hr.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/hr.json @@ -227,6 +227,10 @@ "CssClass": "CSS klasa", "TagsHelpText": "Oznake trebaju biti odvojene zarezom (npr. oznaka1, oznaka2, oznaka3)", "ThisPartOfContentCouldntBeLoaded": "Ovaj dio sadržaja nije bilo moguće učitati.", - "DuplicateCommentAttemptMessage": "Otkriven pokušaj postavljanja duplikata komentara. Vaš komentar je već poslan." + "DuplicateCommentAttemptMessage": "Otkriven pokušaj postavljanja duplikata komentara. Vaš komentar je već poslan.", + "ChooseAnActionForBlog": "Odaberite radnju za blog", + "AssignBlogPostsToOtherBlog": "Dodijelite postove na blogu drugom blogu", + "SelectAnBlogToAssign": "Odaberite blog za dodjelu", + "DeleteAllBlogPostsOfThisBlog": "Izbrišite sve postove na blogu" } } \ No newline at end of file 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 219d9f95a7..9a3e4fb64e 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 @@ -227,6 +227,10 @@ "CssClass": "CSS osztály", "TagsHelpText": "A címkéket vesszővel kell elválasztani (pl.: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "A tartalom ezen része nem tölthető be.", - "DuplicateCommentAttemptMessage": "Ismétlődő megjegyzés közzétételi kísérlet észlelve. Megjegyzését már elküldtük." + "DuplicateCommentAttemptMessage": "Ismétlődő megjegyzés közzétételi kísérlet észlelve. Megjegyzését már elküldtük.", + "ChooseAnActionForBlog": "Válasszon egy műveletet a bloghoz", + "AssignBlogPostsToOtherBlog": "Blogbejegyzések hozzárendelése egy másik bloghoz", + "SelectAnBlogToAssign": "Válasszon egy blogot a hozzárendeléshez", + "DeleteAllBlogPostsOfThisBlog": "Ez a művelet törli az összes blogbejegyzést ebből a blogból. Biztos vagy benne?" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json index 6788847dd7..bf02d1ff68 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/is.json @@ -227,6 +227,10 @@ "CssClass": "CSS flokkur", "TagsHelpText": "Merki ættu að vera aðskilin með kommum (td: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Þessi hluti af efni gat ekki verið hlaðið inn.", - "DuplicateCommentAttemptMessage": "Tvítekin tilraun til að skrifa athugasemd fannst. Athugasemd þín hefur þegar verið send." + "DuplicateCommentAttemptMessage": "Tvítekin tilraun til að skrifa athugasemd fannst. Athugasemd þín hefur þegar verið send.", + "ChooseAnActionForBlog": "Veldu aðgerð fyrir blogg", + "AssignBlogPostsToOtherBlog": "Úthluta bloggfærslum til annars bloggs", + "SelectAnBlogToAssign": "Veldu blogg til að úthluta", + "DeleteAllBlogPostsOfThisBlog": "Eyða öllum bloggfærslum þessa bloggs" } } \ No newline at end of file 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 c6d84a4f62..7506c439f3 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 @@ -227,6 +227,10 @@ "CssClass": "Classe CSS", "TagsHelpText": "I tag devono essere separati da virgole (ad esempio: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Questa parte del contenuto non può essere caricata.", - "DuplicateCommentAttemptMessage": "Rilevato tentativo di pubblicare commenti duplicati. Il tuo commento è già stato inviato." + "DuplicateCommentAttemptMessage": "Rilevato tentativo di pubblicare commenti duplicati. Il tuo commento è già stato inviato.", + "ChooseAnActionForBlog": "Scegli un'azione per il blog", + "AssignBlogPostsToOtherBlog": "Assegna i post del blog ad un altro blog", + "SelectAnBlogToAssign": "Seleziona un blog a cui assegnare i post del blog", + "DeleteAllBlogPostsOfThisBlog": "Elimina tutti i post del blog di questo blog" } } \ No newline at end of file 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 b7c275078a..1d367dfa5c 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 @@ -227,6 +227,10 @@ "CssClass": "CSS-klasse", "TagsHelpText": "Tags moeten door komma's worden gescheiden (bijvoorbeeld: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Dit deel van de inhoud kon niet worden geladen.", - "DuplicateCommentAttemptMessage": "Dubbele poging tot posten van commentaar gedetecteerd. Uw reactie is al verzonden." + "DuplicateCommentAttemptMessage": "Dubbele poging tot posten van commentaar gedetecteerd. Uw reactie is al verzonden.", + "ChooseAnActionForBlog": "Kies een actie voor de blog", + "AssignBlogPostsToOtherBlog": "Wijs blogberichten toe aan een andere blog", + "SelectAnBlogToAssign": "Selecteer een blog om toe te wijzen", + "DeleteAllBlogPostsOfThisBlog": "Verwijder alle blogberichten van deze blog" } } \ No newline at end of file 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 5237c0dc95..0b084f585c 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 @@ -227,6 +227,10 @@ "CssClass": "Klasa CSS", "TagsHelpText": "Tagi powinny być oddzielone przecinkami (np. tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Ta część zawartości nie mogła zostać załadowana.", - "DuplicateCommentAttemptMessage": "Wykryto zduplikowaną próbę opublikowania komentarza. Twój komentarz został już przesłany." + "DuplicateCommentAttemptMessage": "Wykryto zduplikowaną próbę opublikowania komentarza. Twój komentarz został już przesłany.", + "ChooseAnActionForBlog": "Wybierz akcję dla bloga", + "AssignBlogPostsToOtherBlog": "Przypisz posty na blogu do innego bloga", + "SelectAnBlogToAssign": "Wybierz blog, do którego chcesz przypisać posty na blogu", + "DeleteAllBlogPostsOfThisBlog": "Usuń wszystkie posty na blogu tego bloga" } } \ No newline at end of file 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 3182469634..3991bc0595 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 @@ -227,6 +227,10 @@ "CssClass": "Classe CSS", "TagsHelpText": "As tags devem ser separadas por vírgula (por exemplo: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Esta parte do conteúdo não pôde ser carregada.", - "DuplicateCommentAttemptMessage": "Tentativa duplicada de postagem de comentário detectada. Seu comentário já foi enviado." + "DuplicateCommentAttemptMessage": "Tentativa duplicada de postagem de comentário detectada. Seu comentário já foi enviado.", + "ChooseAnActionForBlog": "Escolha uma ação para o blog", + "AssignBlogPostsToOtherBlog": "Atribuir postagens de blog a outro blog", + "SelectAnBlogToAssign": "Selecione um blog para atribuir", + "DeleteAllBlogPostsOfThisBlog": "Excluir todas as postagens de blog deste blog" } } \ 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 7b9173f477..c6b486a11a 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 @@ -227,6 +227,10 @@ "CssClass": "Clasa CSS", "TagsHelpText": "Etichetele ar trebui să fie separate prin virgulă (de exemplu: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Această parte a conţinutului nu a putut fi încărcată.", - "DuplicateCommentAttemptMessage": "A fost detectată o încercare de postare de comentarii duplicată. Comentariul dvs. a fost deja trimis." + "DuplicateCommentAttemptMessage": "A fost detectată o încercare de postare de comentarii duplicată. Comentariul dvs. a fost deja trimis.", + "ChooseAnActionForBlog": "Alegeţi o acţiune pentru blog", + "AssignBlogPostsToOtherBlog": "Atribuiţi postările de blog la alt blog", + "SelectAnBlogToAssign": "Selectaţi un blog pentru a atribui postările de blog", + "DeleteAllBlogPostsOfThisBlog": "Ştergeţi toate postările de blog ale acestui blog" } } \ No newline at end of file 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 491435bc02..c23671c843 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 @@ -227,6 +227,10 @@ "CssClass": "CSS-класс", "TagsHelpText": "Теги должны быть разделены запятыми (например: тег1, тег2, тег3).", "ThisPartOfContentCouldntBeLoaded": "Эта часть содержимого не может быть загружена.", - "DuplicateCommentAttemptMessage": "Обнаружена повторная попытка публикации комментария. Ваш комментарий уже отправлен." + "DuplicateCommentAttemptMessage": "Обнаружена повторная попытка публикации комментария. Ваш комментарий уже отправлен.", + "ChooseAnActionForBlog": "Выберите действие для блога", + "AssignBlogPostsToOtherBlog": "Назначить сообщения в блоге другому блогу", + "SelectAnBlogToAssign": "Выберите блог для назначения", + "DeleteAllBlogPostsOfThisBlog": "Удалить все сообщения в блоге этого блога" } } \ No newline at end of file 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 c579340750..a1ff2cfb01 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 @@ -227,6 +227,10 @@ "CssClass": "CSS trieda", "TagsHelpText": "Značky by mali byť oddelené čiarkou (napr.: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Táto časť obsahu sa nedá načítať.", - "DuplicateCommentAttemptMessage": "Zistil sa duplicitný pokus o uverejnenie komentára. Váš komentár už bol odoslaný." + "DuplicateCommentAttemptMessage": "Zistil sa duplicitný pokus o uverejnenie komentára. Váš komentár už bol odoslaný.", + "ChooseAnActionForBlog": "Vyberte akciu pre blog", + "AssignBlogPostsToOtherBlog": "Priradiť blogové príspevky k inému blogu", + "SelectAnBlogToAssign": "Vyberte blog, na ktorý chcete priradiť blogové príspevky", + "DeleteAllBlogPostsOfThisBlog": "Zmazať všetky blogové príspevky tohto blogu" } } \ No newline at end of file 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 6e3157f56e..b4d525c3e4 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 @@ -227,6 +227,10 @@ "CssClass": "Razred CSS", "TagsHelpText": "Oznake morajo biti ločene z vejicami (npr. oznaka1, oznaka2, oznaka3)", "ThisPartOfContentCouldntBeLoaded": "Ta del vsebine ni bil naložen.", - "DuplicateCommentAttemptMessage": "Zaznan poskus podvojene objave komentarja. Vaš komentar je že oddan." + "DuplicateCommentAttemptMessage": "Zaznan poskus podvojene objave komentarja. Vaš komentar je že oddan.", + "ChooseAnActionForBlog": "Izberite dejanje za blog", + "AssignBlogPostsToOtherBlog": "Dodeli objave v blogu drugemu blogu", + "SelectAnBlogToAssign": "Izberite blog, ki mu želite dodeliti objave", + "DeleteAllBlogPostsOfThisBlog": "Izbriši vse objave v tem blogu" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sv.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sv.json index 6e8962915b..f9604657ce 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sv.json +++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/sv.json @@ -254,6 +254,10 @@ "CommentAlertMessage": "Det finns {0} kommentarer som väntar på godkännande", "Settings:Menu:CmsKit": "CMS", "CommentsAwaitingApproval": "Kommentarer som väntar på godkännande", - "CommentSubmittedForApproval": "Din kommentar har skickats in för godkännande." + "CommentSubmittedForApproval": "Din kommentar har skickats in för godkännande.", + "ChooseAnActionForBlog": "Välj en åtgärd för bloggen", + "AssignBlogPostsToOtherBlog": "Tilldela blogginlägg till en annan blogg", + "SelectAnBlogToAssign": "Välj en blogg att tilldela", + "DeleteAllBlogPostsOfThisBlog": "Radera alla blogginlägg i denna blogg" } } \ No newline at end of file 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 3605cb9d3b..0e5d6d7c11 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 @@ -218,6 +218,10 @@ "CaptchaCode": "Captcha kodu", "CommentTextRequired": "Yorum zorunlu", "PopularTags": "Popüler Etiketler", - "ThisPartOfContentCouldntBeLoaded": "Bu içerik yüklenemedi" + "ThisPartOfContentCouldntBeLoaded": "Bu içerik yüklenemedi", + "ChooseAnActionForBlog": "Blog için bir eylem seçin", + "AssignBlogPostsToOtherBlog": "Diğer bloglara blog yazıları atayın", + "SelectAnBlogToAssign": "Atanacak bir blog seçin", + "DeleteAllBlogPostsOfThisBlog": "Bu blogun tüm blog yazılarını sil" } } 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 1ec430edc3..0a2159e104 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 @@ -227,6 +227,10 @@ "CssClass": "Lớp CSS", "TagsHelpText": "Các thẻ phải được phân tách bằng dấu phẩy (ví dụ: tag1, tag2, tag3)", "ThisPartOfContentCouldntBeLoaded": "Phần này của nội dung không thể được tải.", - "DuplicateCommentAttemptMessage": "Đã phát hiện nỗ lực đăng bình luận trùng lặp. Bình luận của bạn đã được gửi." + "DuplicateCommentAttemptMessage": "Đã phát hiện nỗ lực đăng bình luận trùng lặp. Bình luận của bạn đã được gửi.", + "ChooseAnActionForBlog": "Chọn một hành động cho blog", + "AssignBlogPostsToOtherBlog": "Gán bài đăng trên blog cho blog khác", + "SelectAnBlogToAssign": "Chọn một blog để gán", + "DeleteAllBlogPostsOfThisBlog": "Xóa tất cả bài đăng trên blog của blog này" } } \ No newline at end of file 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 c02fcf614d..18ae3004cb 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 @@ -227,6 +227,10 @@ "CssClass": "CSS 类", "TagsHelpText": "标签应以逗号分隔(例如:标签 1,标签 2,标签 3)", "ThisPartOfContentCouldntBeLoaded": "这部分内容无法加载。", - "DuplicateCommentAttemptMessage": "检测到重复发表评论。您的评论已经提交。" + "DuplicateCommentAttemptMessage": "检测到重复发表评论。您的评论已经提交。", + "ChooseAnActionForBlog": "选择博客的操作", + "AssignBlogPostsToOtherBlog": "将博客文章分配给其他博客", + "SelectAnBlogToAssign": "选择要分配的博客", + "DeleteAllBlogPostsOfThisBlog": "删除此博客的所有博客文章" } } \ No newline at end of file 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 866fd3fcea..80c30a6be3 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 @@ -227,6 +227,10 @@ "CssClass": "CSS類", "TagsHelpText": "標籤應以逗號分隔(例如:tag1、tag2、tag3)", "ThisPartOfContentCouldntBeLoaded": "這部分內容無法加載", - "DuplicateCommentAttemptMessage": "偵測到重複的評論貼文嘗試。您的評論已經提交。" + "DuplicateCommentAttemptMessage": "偵測到重複的評論貼文嘗試。您的評論已經提交。", + "ChooseAnActionForBlog": "選擇部落格的操作", + "AssignBlogPostsToOtherBlog": "將部落格文章分配給其他部落格", + "SelectAnBlogToAssign": "選擇要分配的部落格", + "DeleteAllBlogPostsOfThisBlog": "刪除此部落格的所有部落格文章" } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs index 3a4cf26c1b..a34a303008 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogPost.cs @@ -53,7 +53,7 @@ public class BlogPost : FullAuditedAggregateRoot, IMultiTenant, IHasEntity ) : base(id) { TenantId = tenantId; - BlogId = blogId; + SetBlogId(blogId); AuthorId = authorId; SetTitle(title); SetSlug(slug); @@ -68,6 +68,11 @@ public class BlogPost : FullAuditedAggregateRoot, IMultiTenant, IHasEntity Title = Check.NotNullOrWhiteSpace(title, nameof(title), BlogPostConsts.MaxTitleLength); } + public virtual void SetBlogId(Guid blogId) + { + BlogId = blogId; + } + internal void SetSlug(string slug) { Check.NotNullOrWhiteSpace(slug, nameof(slug), BlogPostConsts.MaxSlugLength, BlogPostConsts.MinSlugLength); diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogWithBlogPostCount.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogWithBlogPostCount.cs new file mode 100644 index 0000000000..9a84402375 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/BlogWithBlogPostCount.cs @@ -0,0 +1,14 @@ +namespace Volo.CmsKit.Blogs; + +public class BlogWithBlogPostCount +{ + public Blog Blog { get; set; } + + public int BlogPostCount { get; set; } + + public BlogWithBlogPostCount(Blog blog, int blogPostCount) + { + Blog = blog; + BlogPostCount = blogPostCount; + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostRepository.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostRepository.cs index 404d21dc83..885d0de800 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogPostRepository.cs @@ -44,4 +44,6 @@ public interface IBlogPostRepository : IBasicRepository Task GetAuthorHasBlogPostAsync(Guid id, CancellationToken cancellationToken = default); Task HasBlogPostWaitingForReviewAsync(CancellationToken cancellationToken = default); + + Task UpdateBlogAsync(Guid sourceBlogId, Guid? targetBlogId = null, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs index 60005db319..aebdfc3f24 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Domain/Volo/CmsKit/Blogs/IBlogRepository.cs @@ -16,6 +16,13 @@ public interface IBlogRepository : IBasicRepository CancellationToken cancellationToken = default ); + Task> GetListWithBlogPostCountAsync( + string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + CancellationToken cancellationToken = default); + Task GetCountAsync( string filter = null, CancellationToken cancellationToken = default diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogPostRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogPostRepository.cs index 266a04a910..1160387151 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogPostRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogPostRepository.cs @@ -160,4 +160,17 @@ public class EfCoreBlogPostRepository : EfCoreRepository x.Status == BlogPostStatus.WaitingForReview, GetCancellationToken(cancellationToken)); } + + public async Task UpdateBlogAsync(Guid sourceBlogId, Guid? targetBlogId = null, CancellationToken cancellationToken = default) + { + if (targetBlogId != null) + { + await (await GetDbSetAsync()).Where(x => x.BlogId == sourceBlogId).ExecuteUpdateAsync(x => x.SetProperty(b => b.BlogId, targetBlogId.Value), GetCancellationToken(cancellationToken)); + + } + else + { + await (await GetDbSetAsync()).Where(x => x.BlogId == sourceBlogId).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); + } + } } \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs index daf915f675..5234577f02 100644 --- a/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.EntityFrameworkCore/Volo/CmsKit/Blogs/EfCoreBlogRepository.cs @@ -43,6 +43,31 @@ public class EfCoreBlogRepository : EfCoreRepository> GetListWithBlogPostCountAsync( + string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + CancellationToken cancellationToken = default) + { + var blogs = await (await GetListQueryAsync(filter)).OrderBy(sorting.IsNullOrEmpty() ? "creationTime desc" : sorting) + .PageBy(skipCount, maxResultCount).ToListAsync(GetCancellationToken(cancellationToken)); + + var blogIds = blogs.Select(x => x.Id).ToArray(); + + var blogPostCount = await (await GetDbContextAsync()).Set() + .Where(blogPost => blogIds.Contains(blogPost.BlogId)) + .GroupBy(blogPost => blogPost.BlogId) + .Select(x => new + { + BlogId = x.Key, + Count = x.Count() + }) + .ToListAsync(GetCancellationToken(cancellationToken)); + + return blogs.Select(blog => new BlogWithBlogPostCount(blog, blogPostCount.FirstOrDefault(x => x.BlogId == blog.Id)?.Count ?? 0)).ToList(); + } + public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { var query = await GetListQueryAsync(filter); diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs index d3ae31926b..d27fdf16b6 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogPostRepository.cs @@ -192,4 +192,24 @@ public class MongoBlogPostRepository : MongoDbRepository x.Status == BlogPostStatus.WaitingForReview, cancellationToken); } + + public async Task UpdateBlogAsync(Guid sourceBlogId, Guid? targetBlogId, CancellationToken cancellationToken = default) + { + cancellationToken = GetCancellationToken(cancellationToken); + var blogPosts = await (await GetMongoQueryableAsync(cancellationToken)).Where(x => x.BlogId == sourceBlogId).ToListAsync(cancellationToken); + if (targetBlogId.HasValue) + { + foreach (var blogPost in blogPosts) + { + blogPost.SetBlogId(targetBlogId.Value); + } + + await UpdateManyAsync(blogPosts, false, cancellationToken); + } + else + { + + await DeleteManyAsync(blogPosts, false, cancellationToken); + } + } } diff --git a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs index b34c452621..98567899e5 100644 --- a/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs +++ b/modules/cms-kit/src/Volo.CmsKit.MongoDB/Volo/CmsKit/MongoDB/Blogs/MongoBlogRepository.cs @@ -49,6 +49,33 @@ public class MongoBlogRepository : MongoDbRepository> GetListWithBlogPostCountAsync( + string filter = null, + string sorting = null, + int maxResultCount = int.MaxValue, + int skipCount = 0, + CancellationToken cancellationToken = default) + { + var token = GetCancellationToken(cancellationToken); + + var blogs = await GetListQueryAsync(filter, token); + + var blogIds = blogs.OrderBy(sorting.IsNullOrEmpty() ? "creationTime desc" : sorting) + .PageBy(skipCount, maxResultCount).Select(x => x.Id).ToList(); + + var blogPostCount = await (await GetMongoQueryableAsync(token)) + .Where(blogPost => blogIds.Contains(blogPost.Id)) + .GroupBy(blogPost => blogPost.BlogId) + .Select(x => new + { + BlogId = x.Key, + Count = x.Count() + }) + .ToListAsync(GetCancellationToken(cancellationToken)); + + return blogs.Select(blog => new BlogWithBlogPostCount(blog, blogPostCount.FirstOrDefault(x => x.BlogId == blog.Id) != null ? blogPostCount.FirstOrDefault(x => x.BlogId == blog.Id).Count : 0)).ToList(); + } + public virtual async Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { var token = GetCancellationToken(cancellationToken); diff --git a/modules/docs/app/VoloDocs.Web/package.json b/modules/docs/app/VoloDocs.Web/package.json index e3bab9ca58..9b2bca3795 100644 --- a/modules/docs/app/VoloDocs.Web/package.json +++ b/modules/docs/app/VoloDocs.Web/package.json @@ -3,7 +3,7 @@ "name": "volo.docstestapp", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1", - "@abp/docs": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0", + "@abp/docs": "~9.0.0" } } diff --git a/modules/docs/app/VoloDocs.Web/yarn.lock b/modules/docs/app/VoloDocs.Web/yarn.lock index ed31829545..a17bc5cd05 100644 --- a/modules/docs/app/VoloDocs.Web/yarn.lock +++ b/modules/docs/app/VoloDocs.Web/yarn.lock @@ -2,238 +2,238 @@ # yarn lockfile v1 -"@abp/anchor-js@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/anchor-js/-/anchor-js-9.0.0-rc.1.tgz#df4b8c61134f72f54838139a84eca0feb14ba4fd" - integrity sha512-ol/4isPURDYR/WoO5ZvufvW4zlxsF2w2CWhSXYgpipbIkGFOy9RgpZ92rg8UgjLgmd11z0oZwZoijcbcUSpHtg== +"@abp/anchor-js@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/anchor-js/-/anchor-js-9.0.0.tgz#6b87875ba144ad551df43f7dece4e8ac306a4d2a" + integrity sha512-0cSp5zOKsddu6riwAhSEw0y5OOK+0aAdiXPAx7Ivnj1WuzMBn6A42oxV00rt/3vJAtAP3l5Tt6aFSG8FHgHkQQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" anchor-js "^5.0.0" -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/clipboard@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0-rc.1.tgz#6997a792bbad262ccb9351913ec668e73cae5dc0" - integrity sha512-zQ6XIAehIfPBENs8intL3ekZhl1Sgh6EOn9QgkIzgLsyrnUrXgFdOHz96TGo5ttYOIEx8L5zoR29iCSLYBjDpg== +"@abp/clipboard@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0.tgz#21ae924dfef6ccf3c8a3913bb81caf22b57404e4" + integrity sha512-W6S7pihpQ6Wfj48Clk7hYgDvUtnRwkNIsk5t8s9+LxoAdJQGQFxh7SAW1QNavUv8QqsClNE1VtSU87c7rSoAbA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" clipboard "^2.0.11" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/docs@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/docs/-/docs-9.0.0-rc.1.tgz#c126830c47fdf11d31bcb67ebcad34a01a099eff" - integrity sha512-VHIhqTKc7egrBWLvuBSFlGs3UBZZfuVLVyEhLCt/qTVrq0uoWJNeWyusVt8hpHRPX8A27ktBcnPBeRtG/+PPuw== +"@abp/docs@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/docs/-/docs-9.0.0.tgz#37d785447de4230a92d742f7aa0560e702ae1671" + integrity sha512-wo7iImXCO+KRowEkYqPFK3Xkqi7k4tOBn3Mctye4BtPCRnwW1kIQuzAWJr7algXgE8OF3+jjMpy1A4tqTTrgLw== dependencies: - "@abp/anchor-js" "~9.0.0-rc.1" - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/popper.js" "~9.0.0-rc.1" - "@abp/prismjs" "~9.0.0-rc.1" + "@abp/anchor-js" "~9.0.0" + "@abp/clipboard" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/popper.js" "~9.0.0" + "@abp/prismjs" "~9.0.0" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/popper.js@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/popper.js/-/popper.js-9.0.0-rc.1.tgz#b8eb317ae83a62084658b90e7622de75b2c9fdc3" - integrity sha512-fi9UFpWPuQxQtGPL1V8CFF2HI9COZk3ungITPuiCZw6wTCIEqoZEz0zabM8iSbMy4K048srZP1wH0BChUKNn2Q== +"@abp/popper.js@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/popper.js/-/popper.js-9.0.0.tgz#daeb5d966af64cb386633f0b17d68ab01af41557" + integrity sha512-Uc9yxvIySV/iDtXdPSb8J2wlw6OhnsC5pKRLdvV7lmFjxawVJF0eJQ7Wg5k77tMirEESL3VZMT2mekwT47c8zA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@popperjs/core" "^2.11.8" -"@abp/prismjs@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0-rc.1.tgz#be4f23d69f780a693d65a1eacefb2aef51c5d205" - integrity sha512-tgTo+GlBzGH1qwbzdAd+MHgf6BIbGraCQwaeuKu13EXMt1vi4vB9i14YzaZClgaQ0cxEN3+6qheejPjkWU623A== +"@abp/prismjs@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0.tgz#2ac4a5ddc0c8e0462af027a4dd97a177a3d6f7a5" + integrity sha512-+evmBq5qV+Ix/TNqO2ljJn0jygW2rEgKNtABcBGmrZC8xiI7+2hjKmSE0e43qb+RDib8aJjwH8ya8wF7p68ZFw== dependencies: - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/core" "~9.0.0-rc.1" + "@abp/clipboard" "~9.0.0" + "@abp/core" "~9.0.0" prismjs "^1.29.0" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DynamicFeatureDefinitionStoreInMemoryCache.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DynamicFeatureDefinitionStoreInMemoryCache.cs index cefa0b3ade..a64f21af64 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DynamicFeatureDefinitionStoreInMemoryCache.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/DynamicFeatureDefinitionStoreInMemoryCache.cs @@ -48,7 +48,7 @@ public class DynamicFeatureDefinitionStoreInMemoryCache: { var featureGroup = context.AddGroup( featureGroupRecord.Name, - LocalizableStringSerializer.Deserialize(featureGroupRecord.DisplayName) + featureGroupRecord.DisplayName != null ? LocalizableStringSerializer.Deserialize(featureGroupRecord.DisplayName) : null ); FeatureGroupDefinitions[featureGroup.Name] = featureGroup; @@ -92,8 +92,8 @@ public class DynamicFeatureDefinitionStoreInMemoryCache: var feature = featureContainer.CreateChildFeature( featureRecord.Name, featureRecord.DefaultValue, - LocalizableStringSerializer.Deserialize(featureRecord.DisplayName), - LocalizableStringSerializer.Deserialize(featureRecord.Description), + featureRecord.DisplayName != null ? LocalizableStringSerializer.Deserialize(featureRecord.DisplayName) : null, + featureRecord.Description != null ? LocalizableStringSerializer.Deserialize(featureRecord.Description) : null, StateCheckerSerializer.Deserialize(featureRecord.ValueType), featureRecord.IsVisibleToClients, featureRecord.IsAvailableToHost diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json index 21dd7ac142..074d02f00e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ar.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "يجب أن يكون عدد التكرار عددًا صحيحًا موجبًا.", "Volo.Abp.Identity:InvalidRoleName": "اسم الدور '{0}' غير صالح.", "Volo.Abp.Identity:InvalidToken": "غير صالح token.", - "Volo.Abp.Identity:InvalidUserName": "اسم المستخدم '{0}' غير صالح ، يمكن أن يحتوي على أحرف أو أرقام فقط.", - "InvalidUserName": "لااسم المستخدم '{0}' غير صالح .", + "Volo.Abp.Identity:InvalidUserName": "لااسم المستخدم '{0}' غير صالح .", "Volo.Abp.Identity:LoginAlreadyAssociated": "يوجد مستخدم لديه معلومات تسجيل الدخول هذه بالفعل.", "Volo.Abp.Identity:PasswordMismatch": "كلمة مرور غير صحيحة.", "Volo.Abp.Identity:PasswordRequiresDigit": "يجب أن تحتوي كلمات المرور على رقم واحد على الأقل ('0' - '9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json index ca65951c3e..ea26d685f8 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/cs.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Počet iterací musí být kladné celé číslo.", "Volo.Abp.Identity:InvalidRoleName": "Role '{0}' je neplatná.", "Volo.Abp.Identity:InvalidToken": "Neplatný token.", - "Volo.Abp.Identity:InvalidUserName": "Uživatelské jméno '{0}' je neplatné, může obsahovat pouze písmena a číslice.", - "InvalidUserName": "Uživatelské jméno '{0}' je neplatné.", + "Volo.Abp.Identity:InvalidUserName": "Uživatelské jméno '{0}' je neplatné.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Uživatel s tímto přihlášením již existuje.", "Volo.Abp.Identity:PasswordMismatch": "Chybné heslo.", "Volo.Abp.Identity:PasswordRequiresDigit": "Hesla musí obsahovat alespoň jednu číslici ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json index 009d41fd0b..56bb75d104 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/de.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Die Iterationszahl muss eine positive Ganzzahl sein.", "Volo.Abp.Identity:InvalidRoleName": "Der Rollenname '{0}' ist ungültig.", "Volo.Abp.Identity:InvalidToken": "Ungültiger Token.", - "Volo.Abp.Identity:InvalidUserName": "Der Benutzername '{0}' ist ungültig und darf nur Buchstaben oder Ziffern enthalten.", - "InvalidUserName": "Der Benutzername '{0}' ist ungültig.", + "Volo.Abp.Identity:InvalidUserName": "Der Benutzername '{0}' ist ungültig.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Ein Benutzer mit diesem Login existiert bereits.", "Volo.Abp.Identity:PasswordMismatch": "Falsches Passwort.", "Volo.Abp.Identity:PasswordRequiresDigit": "Passwörter müssen mindestens eine Ziffer haben ('0' - '9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json index 97dfcb9a50..c75e1f2ce9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/el.json @@ -47,8 +47,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Το πλήθος των επαναλήψεων πρέπει να είναι θετικός ακέραιος.", "Volo.Abp.Identity:InvalidRoleName": "Το όνομα ρόλου '{0}' δεν είναι έγκυρο.", "Volo.Abp.Identity:InvalidToken": "Μη έγκυρο διακριτικό.", - "Volo.Abp.Identity:InvalidUserName": "Το όνομα χρήστη '{0}' δεν είναι έγκυρο, μπορεί να περιέχει μόνο γράμματα ή ψηφία.", - "InvalidUserName": "Το όνομα χρήστη '{0}' δεν είναι έγκυρο.", + "Volo.Abp.Identity:InvalidUserName": "Το όνομα χρήστη '{0}' δεν είναι έγκυρο.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Ένας χρήστης με αυτήν τη σύνδεση υπάρχει ήδη.", "Volo.Abp.Identity:PasswordMismatch": "Λάθος κωδικός.", "Volo.Abp.Identity:PasswordRequiresDigit": "Οι κωδικοί πρόσβασης πρέπει να έχουν τουλάχιστον ένα ψηφίο ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json index 999b387032..caa7c8691f 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json @@ -47,8 +47,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "The iteration count must be a positive integer.", "Volo.Abp.Identity:InvalidRoleName": "Role name '{0}' is invalid.", "Volo.Abp.Identity:InvalidToken": "Invalid token.", - "Volo.Abp.Identity:InvalidUserName": "Username '{0}' is invalid, it should only contain letters or digits.", - "InvalidUserName": "Username '{0}' is invalid.", + "Volo.Abp.Identity:InvalidUserName": "Username '{0}' is invalid.", "Volo.Abp.Identity:LoginAlreadyAssociated": "A user with this login already exists.", "Volo.Abp.Identity:PasswordMismatch": "Incorrect password.", "Volo.Abp.Identity:PasswordRequiresDigit": "Passwords must have at least one digit ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json index e8f2abba48..ff8d8aec80 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "The iteration count must be a positive integer.", "Volo.Abp.Identity:InvalidRoleName": "Role name '{0}' is invalid.", "Volo.Abp.Identity:InvalidToken": "Invalid token.", - "Volo.Abp.Identity:InvalidUserName": "Username '{0}' is invalid, can only contain letters or digits.", - "InvalidUserName": "Username '{0}' is invalid.", + "Volo.Abp.Identity:InvalidUserName": "Username '{0}' is invalid.", "Volo.Abp.Identity:LoginAlreadyAssociated": "A user with this login already exists.", "Volo.Abp.Identity:PasswordMismatch": "Incorrect password.", "Volo.Abp.Identity:PasswordRequiresDigit": "Passwords must have at least one digit ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json index 7cf85929a6..198e08e287 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "La cuenta iterativa debe ser una entero positivo.", "Volo.Abp.Identity:InvalidRoleName": "El nombre de rol '{0}' no es válido.", "Volo.Abp.Identity:InvalidToken": "token no válido", - "Volo.Abp.Identity:InvalidUserName": "Nombre de usuario '{0}' no es válido. Sólo puede contener letras o dígitos", - "InvalidUserName": "Nombre de usuario '{0}' no es válido.", + "Volo.Abp.Identity:InvalidUserName": "Nombre de usuario '{0}' no es válido.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Usuario con este inicio de sesión en uso.", "Volo.Abp.Identity:PasswordMismatch": "Contraseña incorrecta.", "Volo.Abp.Identity:PasswordRequiresDigit": "Contraseñas deben tener al menos un dígito ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json index f21b2204db..187f13a210 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fa.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "تعداد تکرارها باید یک عدد صحیح مثبت باشد.", "Volo.Abp.Identity:InvalidRoleName": "عنوان نقش/وظیفه {0} نامعتبر است.", "Volo.Abp.Identity:InvalidToken": "گذرواژه وارد شده معتبر نیست.", - "Volo.Abp.Identity:InvalidUserName": "نام کاربری '{0}' نامعتبر است، نام کاربری فقط می تواند شامل حروف یا ارقام باشد.", - "InvalidUserName": "ام کاربری '{0}' نامعتبر است", + "Volo.Abp.Identity:InvalidUserName": "ام کاربری '{0}' نامعتبر است", "Volo.Abp.Identity:LoginAlreadyAssociated": "یک کاربر با این نام کاربری از قبل موجود می باشد.", "Volo.Abp.Identity:PasswordMismatch": "گذرواژه اشتباه است.", "Volo.Abp.Identity:PasswordRequiresDigit": "گذرواژه ها باید حداقل یک رقم داشته باشند ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json index 5aab8fb4d2..f212e0d9fc 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fi.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Iteraatiolaskun on oltava positiivinen kokonaisluku.", "Volo.Abp.Identity:InvalidRoleName": "Roolin nimi {0} on virheellinen.", "Volo.Abp.Identity:InvalidToken": "Virheellinen tunnus.", - "Volo.Abp.Identity:InvalidUserName": "Käyttäjätunnus {0} on virheellinen, voi sisältää vain kirjaimia tai numeroita.", - "InvalidUserName": "Käyttäjätunnus {0} on virheellinen.", + "Volo.Abp.Identity:InvalidUserName": "Käyttäjätunnus {0} on virheellinen.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Käyttäjä, jolla on tämä sisäänkirjautuminen, on jo olemassa.", "Volo.Abp.Identity:PasswordMismatch": "Väärä salasana.", "Volo.Abp.Identity:PasswordRequiresDigit": "Salasanoissa on oltava vähintään yksi numero ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json index 776233b642..2dc00005fd 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/fr.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Le nombre d’itérations doit être un entier positif.", "Volo.Abp.Identity:InvalidRoleName": "Le nom de rôle '{0}' n’est pas valide.", "Volo.Abp.Identity:InvalidToken": "Jeton non valide.", - "Volo.Abp.Identity:InvalidUserName": "Le nom d’utilisateur '{0}' n’est pas valide, ne peut contenir que des lettres ou des chiffres.", - "InvalidUserName": "Le nom d’utilisateur '{0}' n’est pas valide.", + "Volo.Abp.Identity:InvalidUserName": "Le nom d’utilisateur '{0}' n’est pas valide.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Un utilisateur avec cette connexion existe déjà.", "Volo.Abp.Identity:PasswordMismatch": "Mot de passe incorrect.", "Volo.Abp.Identity:PasswordRequiresDigit": "Les mots de passe doivent avoir au moins un chiffre ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json index 630e1c3103..8f35089f94 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hi.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "चलना गणना एक सकारात्मक पूर्णांक होना चाहिए।", "Volo.Abp.Identity:InvalidRoleName": "भूमिका नाम '{0}' अमान्य है।", "Volo.Abp.Identity:InvalidToken": "अमान्य टोकन।", - "Volo.Abp.Identity:InvalidUserName": "उपयोगकर्ता नाम '{0}' अमान्य है, इसमें केवल अक्षर या अंक हो सकते हैं।", - "InvalidUserName": "उपयोगकर्ता नाम '{0}' अमान्य है", + "Volo.Abp.Identity:InvalidUserName": "उपयोगकर्ता नाम '{0}' अमान्य है", "Volo.Abp.Identity:LoginAlreadyAssociated": "इस लॉगिन वाला उपयोगकर्ता पहले से मौजूद है।", "Volo.Abp.Identity:PasswordMismatch": "गलत पासवर्ड।", "Volo.Abp.Identity:PasswordRequiresDigit": "पासवर्ड में कम से कम एक अंक ('0'-'9') होना चाहिए।", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json index a5203a7067..c18404d51d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Broj ponavljanja mora biti pozitivan cijeli broj.", "Volo.Abp.Identity:InvalidRoleName": "Naziv uloge '{0}' nije valjan.", "Volo.Abp.Identity:InvalidToken": "Pogrešan token.", - "Volo.Abp.Identity:InvalidUserName": "Korisničko ime '{0}' nije važeće, može sadržavati samo slova ili znamenke.", - "InvalidUserName": "Korisničko ime '{0}' nije važeće.", + "Volo.Abp.Identity:InvalidUserName": "Korisničko ime '{0}' nije važeće.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Korisnik s ovom prijavom već postoji.", "Volo.Abp.Identity:PasswordMismatch": "Netočna lozinka.", "Volo.Abp.Identity:PasswordRequiresDigit": "Lozinke moraju imati najmanje jednu znamenku ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json index 79e58d5b6a..58440d13f1 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hu.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Az iterációszámnak pozitív egész számnak kell lennie.", "Volo.Abp.Identity:InvalidRoleName": "'{0}' szerepkör név érvénytelen.", "Volo.Abp.Identity:InvalidToken": "Érvénytelen token.", - "Volo.Abp.Identity:InvalidUserName": "'{0}' felhasználónév érvénytelen, csak betűket és számokat tartalmazhat.", - "InvalidUserName": "'{0}' felhasználónév érvénytelen.", + "Volo.Abp.Identity:InvalidUserName": "'{0}' felhasználónév érvénytelen.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Az ilyen bejelentkezéssel rendelkező felhasználó már létezik.", "Volo.Abp.Identity:PasswordMismatch": "Érvénytelen jelszó.", "Volo.Abp.Identity:PasswordRequiresDigit": "A jelszavaknak legalább egy számjegyet kell rendelkezniük ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json index 6a9406c832..6436d4b7ed 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/is.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Talning endurtekningar verður að vera jákvæð heil tala.", "Volo.Abp.Identity:InvalidRoleName": "Hlutverkanafnið '{0}' er ógilt.", "Volo.Abp.Identity:InvalidToken": "Ógilt token.", - "Volo.Abp.Identity:InvalidUserName": "Notandanafnið '{0}' er ógilt, getur aðeins innihaldið bókstafi eða tölustafi.", - "InvalidUserName": "Notandanafnið '{0}' er ógilt.", + "Volo.Abp.Identity:InvalidUserName": "Notandanafnið '{0}' er ógilt.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Notandi með þessa innskráningu er þegar til.", "Volo.Abp.Identity:PasswordMismatch": "Rangt lykilorð.", "Volo.Abp.Identity:PasswordRequiresDigit": "Lykilorð verða að hafa að minnsta kosti einn staf ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json index 9ad338ef73..af8dc46329 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/it.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Il conteggio delle iterazioni deve essere un numero intero positivo.", "Volo.Abp.Identity:InvalidRoleName": "Il nome del ruolo '{0}' non è valido.", "Volo.Abp.Identity:InvalidToken": "Token non valido.", - "Volo.Abp.Identity:InvalidUserName": "Il nome utente '{0}' non è valido, può contenere solo lettere o cifre.", - "InvalidUserName": "Il nome utente '{0}' non è valido.", + "Volo.Abp.Identity:InvalidUserName": "Il nome utente '{0}' non è valido.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Esiste già un utente con questo account.", "Volo.Abp.Identity:PasswordMismatch": "Password errata.", "Volo.Abp.Identity:PasswordRequiresDigit": "La password deve contenere almeno una cifra ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json index c5f10d7dfb..9304c85fbf 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/nl.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "De iteratietelling moet een positief geheel getal zijn.", "Volo.Abp.Identity:InvalidRoleName": "Rol naam '{0}' is ongeldig.", "Volo.Abp.Identity:InvalidToken": "Ongeldig token.", - "Volo.Abp.Identity:InvalidUserName": "Gebruikersnaam '{0}' is ongeldig, mag alleen letters of cijfers bevatten.", - "InvalidUserName": "Gebruikersnaam '{0}' is ongeldig.", + "Volo.Abp.Identity:InvalidUserName": "Gebruikersnaam '{0}' is ongeldig.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Er bestaat al een gebruiker met deze login.", "Volo.Abp.Identity:PasswordMismatch": "Incorrect wachtwoord.", "Volo.Abp.Identity:PasswordRequiresDigit": "Wachtwoorden moeten minimaal één cijfer bevatten ('0' - '9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json index 5eb3c85b6d..54984c8656 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pl-PL.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Wartość iteracji musi być większa od zera.", "Volo.Abp.Identity:InvalidRoleName": "Rola '{0}' jest niepoprawna.", "Volo.Abp.Identity:InvalidToken": "Niepoprawny token.", - "Volo.Abp.Identity:InvalidUserName": "Nazwa użytkownika '{0}' jest niepoprawna, może zawierać tylko litery i cyfry.", - "InvalidUserName": "Nazwa użytkownika '{0}' jest niepoprawna.", + "Volo.Abp.Identity:InvalidUserName": "Nazwa użytkownika '{0}' jest niepoprawna.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Użytkownik o tym loginie już istnieje.", "Volo.Abp.Identity:PasswordMismatch": "Niepoprawne hasło.", "Volo.Abp.Identity:PasswordRequiresDigit": "Hasło musi zawierać przynajmniej jedną cyfrę ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json index d9bff0967e..fedeeab54c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "A contagem de iterações deve ser um inteiro positivo.", "Volo.Abp.Identity:InvalidRoleName": "Perfil '{0}' inválido.", "Volo.Abp.Identity:InvalidToken": "Token inválido.", - "Volo.Abp.Identity:InvalidUserName": "Usuário '{0}' é inválido, somente pode conter letras ou números.", - "InvalidUserName": "Usuário '{0}' é inválido.", + "Volo.Abp.Identity:InvalidUserName": "Usuário '{0}' é inválido.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Um usuário com este login já existe.", "Volo.Abp.Identity:PasswordMismatch": "Senha incorreta.", "Volo.Abp.Identity:PasswordRequiresDigit": "Senhas devem possuir pelo menos um dígito ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json index b03357bd6d..d3fdce6f0a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Numărul de iteraţii trebuie să fie un număr întreg pozitiv..", "Volo.Abp.Identity:InvalidRoleName": "Numele de rol '{0}' este invalid.", "Volo.Abp.Identity:InvalidToken": "Invalid token.", - "Volo.Abp.Identity:InvalidUserName": "Numele de utilizator '{0}' este invalid, poate conţine doar litere şi cifre.", - "InvalidUserName": "Numele de utilizator '{0}' este invalid.", + "Volo.Abp.Identity:InvalidUserName": "Numele de utilizator '{0}' este invalid.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Un utilizator cu această autentificare există deja.", "Volo.Abp.Identity:PasswordMismatch": "Parolă incorectă.", "Volo.Abp.Identity:PasswordRequiresDigit": "Parolele trebuie să conţină cel puţin o cifră ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json index c7a4869ec0..1120c67d35 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ru.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Число итераций должно быть положительным целым числом.", "Volo.Abp.Identity:InvalidRoleName": "Имя роли '{0}' недопустимо.", "Volo.Abp.Identity:InvalidToken": "Недопустимый маркер.", - "Volo.Abp.Identity:InvalidUserName": "Имя пользователя '{0}' недопустимо и может содержать только буквы или цифры.", - "InvalidUserName": "Имя пользователя '{0}' недопустимо.", + "Volo.Abp.Identity:InvalidUserName": "Имя пользователя '{0}' недопустимо.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Пользователь с таким логином уже существует.", "Volo.Abp.Identity:PasswordMismatch": "Неверный пароль.", "Volo.Abp.Identity:PasswordRequiresDigit": "Пароль должен содержать по крайней мере одну цифру.", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json index d8f7fa8d46..7e5eb79096 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sk.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Počet iterácií musí byť kladné celé číslo.", "Volo.Abp.Identity:InvalidRoleName": "Názov roly '{0}' je neplatný.", "Volo.Abp.Identity:InvalidToken": "Neplatný token.", - "Volo.Abp.Identity:InvalidUserName": "Používateľské meno '{0}' je neplatné, môže obsahovať len písmená alebo číslice.", - "InvalidUserName": "Používateľské meno '{0}' je neplatné.", + "Volo.Abp.Identity:InvalidUserName": "Používateľské meno '{0}' je neplatné.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Používateľ s týmto prihlasovacím menom už existuje.", "Volo.Abp.Identity:PasswordMismatch": "Nesprávne heslo.", "Volo.Abp.Identity:PasswordRequiresDigit": "Heslá musia obsahovať aspoň jednu číslicu ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json index 9273c257a6..17ad0dd8db 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sl.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Število iteracij mora biti pozitivno celo število.", "Volo.Abp.Identity:InvalidRoleName": "Naziv vloge '{0}' ni veljaven.", "Volo.Abp.Identity:InvalidToken": "Neveljaven žeton.", - "Volo.Abp.Identity:InvalidUserName": "Uporabniško ime '{0}' ni veljavno, vsebuje lahko le črke in številke.", - "InvalidUserName": "Uporabniško ime '{0}' ni veljavno.", + "Volo.Abp.Identity:InvalidUserName": "Uporabniško ime '{0}' ni veljavno.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Uporabnik s to prijavo že obstaja.", "Volo.Abp.Identity:PasswordMismatch": "Nepravilno geslo.", "Volo.Abp.Identity:PasswordRequiresDigit": "Gesla morajo imeti vsaj eno številko ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json index 3a2139a240..e6acc9d7dd 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/sv.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Antalet iterationer måste vara ett positivt heltal.", "Volo.Abp.Identity:InvalidRoleName": "Rollnamnet '{0}' är ogiltigt.", "Volo.Abp.Identity:InvalidToken": "Ogiltig token.", - "Volo.Abp.Identity:InvalidUserName": "Användarnamn '{0}' är ogiltigt, kan bara innehålla bokstäver eller siffror.", - "InvalidUserName": "Användarnamnet '{0}' är ogiltigt.", + "Volo.Abp.Identity:InvalidUserName": "Användarnamnet '{0}' är ogiltigt.", "Volo.Abp.Identity:LoginAlreadyAssociated": "En användare med den här inloggningen finns redan.", "Volo.Abp.Identity:PasswordMismatch": "Felaktigt lösenord.", "Volo.Abp.Identity:PasswordRequiresDigit": "Lösenord måste innehålla minst en siffra ('0'-'9').", @@ -129,4 +128,4 @@ "LockoutEndTime": "Sluttid för låsning", "FailedAccessCount": "Antal misslyckade åtkomster" } -} \ No newline at end of file +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json index 69667e5ad7..b2e08d2b4c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Iterasyon sayısı sıfırdan büyük bir sayı olmalı.", "Volo.Abp.Identity:InvalidRoleName": "'{0}' rol ismi geçersizdir.", "Volo.Abp.Identity:InvalidToken": "Geçersiz token.", - "Volo.Abp.Identity:InvalidUserName": "'{0}' kullanıcı adı geçersiz, sadece harf ve rakamlardan oluşmalı.", - "InvalidUserName": "'{0}' kullanıcı adı geçersiz.", + "Volo.Abp.Identity:InvalidUserName": "'{0}' kullanıcı adı geçersiz.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Bu giriş bilgilerine sahip bir kullanıcı zaten var.", "Volo.Abp.Identity:PasswordMismatch": "Hatalı şifre.", "Volo.Abp.Identity:PasswordRequiresDigit": "Şifre en az bir sayı içermeli ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json index de42bfc2d8..ba9a8365f9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/vi.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Số lần lặp phải là số nguyên dương.", "Volo.Abp.Identity:InvalidRoleName": "Tên người dùng '{0}' Không hợp lệ.", "Volo.Abp.Identity:InvalidToken": "Token không hợp lệ.", - "Volo.Abp.Identity:InvalidUserName": "Tên người dùng '{0}' không hợp lệ, chỉ có thể chứa chữ cái hoặc chữ số.", - "InvalidUserName": "Tên người dùng '{0}' không hợp lệ.", + "Volo.Abp.Identity:InvalidUserName": "Tên người dùng '{0}' không hợp lệ.", "Volo.Abp.Identity:LoginAlreadyAssociated": "Một người dùng có thông tin đăng nhập này đã tồn tại.", "Volo.Abp.Identity:PasswordMismatch": "Mật khẩu không đúng.", "Volo.Abp.Identity:PasswordRequiresDigit": "Mật khẩu phải có ít nhất một chữ số ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json index 9a55ce9ad2..f9f9f77607 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "迭代计数必须是正整数。", "Volo.Abp.Identity:InvalidRoleName": "角色名 '{0}' 无效。", "Volo.Abp.Identity:InvalidToken": "token无效。", - "Volo.Abp.Identity:InvalidUserName": "用户名 '{0}' 无效, 只能包含字母或数字。", - "InvalidUserName": "用户名 '{0}' 无效。", + "Volo.Abp.Identity:InvalidUserName": "用户名 '{0}' 无效。", "Volo.Abp.Identity:LoginAlreadyAssociated": "此登录名的用户已存在。", "Volo.Abp.Identity:PasswordMismatch": "密码错误。", "Volo.Abp.Identity:PasswordRequiresDigit": "密码至少包含一位数字 ('0'-'9')。", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json index 055482121f..676e871e0b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json @@ -48,8 +48,7 @@ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "迭代計數必須是正整數.", "Volo.Abp.Identity:InvalidRoleName": "角色名 '{0}' 無效.", "Volo.Abp.Identity:InvalidToken": "token無效.", - "Volo.Abp.Identity:InvalidUserName": "使用者名稱 '{0}' 無效, 只能包含字母或數字.", - "InvalidUserName": "使用者名稱 '{0}' 無效.", + "Volo.Abp.Identity:InvalidUserName": "使用者名稱 '{0}' 無效.", "Volo.Abp.Identity:LoginAlreadyAssociated": "此登入名的使用者已存在.", "Volo.Abp.Identity:PasswordMismatch": "密碼錯誤.", "Volo.Abp.Identity:PasswordRequiresDigit": "密碼至少包含一位數字 ('0'-'9').", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/AbpIdentityResultExtensions.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/AbpIdentityResultExtensions.cs index d9c335991d..eda4f950e5 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/AbpIdentityResultExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Microsoft/AspNetCore/Identity/AbpIdentityResultExtensions.cs @@ -39,6 +39,12 @@ public static class AbpIdentityResultExtensions } } + if (IdentityStrings.ContainsKey("InvalidUserName")) + { + // The default text of `InvalidUserName` is `Username '{0}' is invalid, can only contain letters or digits.` + IdentityStrings["InvalidUserName"] = "Username '{0}' is invalid."; + } + if (!IdentityStrings.Any()) { throw new AbpException("ResourceSet values of Identity is empty."); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs index 149ff3bf31..84d1a09c25 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityUserValidator.cs @@ -37,11 +37,11 @@ namespace Volo.Abp.Identity errors.Add(new IdentityError { Code = "InvalidUserName", - Description = Localizer["InvalidUserName", userName] + Description = Localizer["Volo.Abp.Identity:InvalidUserName", userName] }); } } - + var email = await manager.GetEmailAsync(user); if (email == null) { diff --git a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityUserValidator_Tests.cs b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityUserValidator_Tests.cs index 0333ad7dec..6af6b4ff57 100644 --- a/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityUserValidator_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.AspNetCore.Tests/Volo/Abp/Identity/AspNetCore/AbpIdentityUserValidator_Tests.cs @@ -31,7 +31,7 @@ public class AbpIdentityUserValidator_Tests : AbpIdentityAspNetCoreTestBase identityResult.Succeeded.ShouldBeFalse(); identityResult.Errors.Count().ShouldBe(1); identityResult.Errors.First().Code.ShouldBe("InvalidUserName"); - identityResult.Errors.First().Description.ShouldBe(Localizer["InvalidUserName", "user1@volosoft.com"]); + identityResult.Errors.First().Description.ShouldBe(Localizer["Volo.Abp.Identity:InvalidUserName", "user1@volosoft.com"]); } [Fact] @@ -40,7 +40,7 @@ public class AbpIdentityUserValidator_Tests : AbpIdentityAspNetCoreTestBase var user1 = new IdentityUser(Guid.NewGuid(), "user1@volosoft.com", "user@volosoft.com"); var identityResult = await _identityUserManager.CreateAsync(user1); identityResult.Succeeded.ShouldBeTrue(); - + var user2 = new IdentityUser(Guid.NewGuid(), "user2", "user1@volosoft.com"); identityResult = await _identityUserManager.CreateAsync(user2); identityResult.Succeeded.ShouldBeFalse(); diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/package.json b/modules/openiddict/app/OpenIddict.Demo.Server/package.json index 57114aba35..8b5210b25f 100644 --- a/modules/openiddict/app/OpenIddict.Demo.Server/package.json +++ b/modules/openiddict/app/OpenIddict.Demo.Server/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/modules/openiddict/app/angular/package.json b/modules/openiddict/app/angular/package.json index 85f0d71eb6..2dc6f65e2e 100644 --- a/modules/openiddict/app/angular/package.json +++ b/modules/openiddict/app/angular/package.json @@ -12,15 +12,15 @@ }, "private": true, "dependencies": { - "@abp/ng.account": "~9.0.0-rc.1", - "@abp/ng.components": "~9.0.0-rc.1", - "@abp/ng.core": "~9.0.0-rc.1", - "@abp/ng.oauth": "~9.0.0-rc.1", - "@abp/ng.identity": "~9.0.0-rc.1", - "@abp/ng.setting-management": "~9.0.0-rc.1", - "@abp/ng.tenant-management": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", - "@abp/ng.theme.lepton-x": "~4.0.0-rc.1", + "@abp/ng.account": "~9.0.0", + "@abp/ng.components": "~9.0.0", + "@abp/ng.core": "~9.0.0", + "@abp/ng.oauth": "~9.0.0", + "@abp/ng.identity": "~9.0.0", + "@abp/ng.setting-management": "~9.0.0", + "@abp/ng.tenant-management": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", + "@abp/ng.theme.lepton-x": "~4.0.0", "@angular/animations": "^15.0.1", "@angular/common": "^15.0.1", "@angular/compiler": "^15.0.1", @@ -36,7 +36,7 @@ "zone.js": "~0.11.4" }, "devDependencies": { - "@abp/ng.schematics": "~9.0.0-rc.1", + "@abp/ng.schematics": "~9.0.0", "@angular-devkit/build-angular": "^15.0.1", "@angular-eslint/builder": "~15.1.0", "@angular-eslint/eslint-plugin": "~15.1.0", diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpErrorDescriptionConsts.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpErrorDescriptionConsts.cs new file mode 100644 index 0000000000..93839fa6e3 --- /dev/null +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpErrorDescriptionConsts.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.OpenIddict; + +public static class AbpErrorDescriptionConsts +{ + public const string RequiresTwoFactor = "RequiresTwoFactor"; + + public const string RequiresConfirmUser = "RequiresConfirmUser"; +} diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs index 1b8fb5d39c..61f254f255 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/AbpOpenIddictAspNetCoreModule.cs @@ -140,7 +140,5 @@ public class AbpOpenIddictAspNetCoreModule : AbpModule services.ExecutePreConfiguredActions(builder); }); - - services.ExecutePreConfiguredActions(openIddictBuilder); } } diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs index 470debf115..392e696d08 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs @@ -127,7 +127,12 @@ public partial class TokenController return await HandlePeriodicallyChangePasswordAsync(request, user, request.Password); } - errorDescription = "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number."; + if (user.IsActive) + { + return await HandleConfirmUserAsync(request, user); + } + + errorDescription = "You are not allowed to login! Your account is inactive."; } else { @@ -235,7 +240,7 @@ public partial class TokenController items: new Dictionary { [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant, - [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = nameof(SignInResult.RequiresTwoFactor) + [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = AbpErrorDescriptionConsts.RequiresTwoFactor }, parameters: new Dictionary { @@ -337,6 +342,26 @@ public partial class TokenController } } + protected virtual Task HandleConfirmUserAsync(OpenIddictRequest request, IdentityUser user) + { + Logger.LogInformation($"{request.Username} needs to confirm email/phone number"); + + var properties = new AuthenticationProperties( + items: new Dictionary + { + [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant, + [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = AbpErrorDescriptionConsts.RequiresConfirmUser + }, + parameters: new Dictionary + { + ["userId"] = user.Id.ToString("N"), + ["email"] = user.Email, + ["phoneNumber"] = user.PhoneNumber ?? "" + }); + + return Task.FromResult(Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)); + } + protected virtual async Task SetSuccessResultAsync(OpenIddictRequest request, IdentityUser user) { // Clear the dynamic claims cache. diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/DynamicPermissionDefinitionStoreInMemoryCache.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/DynamicPermissionDefinitionStoreInMemoryCache.cs index 3b09c922dc..1040ea84a0 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/DynamicPermissionDefinitionStoreInMemoryCache.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/DynamicPermissionDefinitionStoreInMemoryCache.cs @@ -10,28 +10,28 @@ using Volo.Abp.SimpleStateChecking; namespace Volo.Abp.PermissionManagement; -public class DynamicPermissionDefinitionStoreInMemoryCache : +public class DynamicPermissionDefinitionStoreInMemoryCache : IDynamicPermissionDefinitionStoreInMemoryCache, ISingletonDependency { public string CacheStamp { get; set; } - + protected IDictionary PermissionGroupDefinitions { get; } protected IDictionary PermissionDefinitions { get; } protected ISimpleStateCheckerSerializer StateCheckerSerializer { get; } protected ILocalizableStringSerializer LocalizableStringSerializer { get; } public SemaphoreSlim SyncSemaphore { get; } = new(1, 1); - + public DateTime? LastCheckTime { get; set; } public DynamicPermissionDefinitionStoreInMemoryCache( - ISimpleStateCheckerSerializer stateCheckerSerializer, + ISimpleStateCheckerSerializer stateCheckerSerializer, ILocalizableStringSerializer localizableStringSerializer) { StateCheckerSerializer = stateCheckerSerializer; LocalizableStringSerializer = localizableStringSerializer; - + PermissionGroupDefinitions = new Dictionary(); PermissionDefinitions = new Dictionary(); } @@ -42,16 +42,16 @@ public class DynamicPermissionDefinitionStoreInMemoryCache : { PermissionGroupDefinitions.Clear(); PermissionDefinitions.Clear(); - + var context = new PermissionDefinitionContext(null); - + foreach (var permissionGroupRecord in permissionGroupRecords) { var permissionGroup = context.AddGroup( permissionGroupRecord.Name, - LocalizableStringSerializer.Deserialize(permissionGroupRecord.DisplayName) + permissionGroupRecord.DisplayName != null ? LocalizableStringSerializer.Deserialize(permissionGroupRecord.DisplayName) : null ); - + PermissionGroupDefinitions[permissionGroup.Name] = permissionGroup; foreach (var property in permissionGroupRecord.ExtraProperties) @@ -61,7 +61,7 @@ public class DynamicPermissionDefinitionStoreInMemoryCache : var permissionRecordsInThisGroup = permissionRecords .Where(p => p.GroupName == permissionGroup.Name); - + foreach (var permissionRecord in permissionRecordsInThisGroup.Where(x => x.ParentName == null)) { AddPermissionRecursively(permissionGroup, permissionRecord, permissionRecords); @@ -92,11 +92,11 @@ public class DynamicPermissionDefinitionStoreInMemoryCache : { var permission = permissionContainer.AddPermission( permissionRecord.Name, - LocalizableStringSerializer.Deserialize(permissionRecord.DisplayName), + permissionRecord.DisplayName != null ? LocalizableStringSerializer.Deserialize(permissionRecord.DisplayName) : null, permissionRecord.MultiTenancySide, permissionRecord.IsEnabled ); - + PermissionDefinitions[permission.Name] = permission; if (!permissionRecord.Providers.IsNullOrWhiteSpace()) @@ -124,4 +124,4 @@ public class DynamicPermissionDefinitionStoreInMemoryCache : AddPermissionRecursively(permission, subPermission, allPermissionRecords); } } -} \ No newline at end of file +} diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionDataSeeder.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionDataSeeder.cs index 4227819fa6..1e8a4aab7b 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionDataSeeder.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain/Volo/Abp/PermissionManagement/PermissionDataSeeder.cs @@ -35,19 +35,12 @@ public class PermissionDataSeeder : IPermissionDataSeeder, ITransientDependency { var names = grantedPermissions.ToArray(); var existsPermissionGrants = (await PermissionGrantRepository.GetListAsync(names, providerName, providerKey)).Select(x => x.Name).ToList(); - - foreach (var permissionName in names.Except(existsPermissionGrants)) + var permissions = names.Except(existsPermissionGrants).Select(permissionName => new PermissionGrant(GuidGenerator.Create(), permissionName, providerName, providerKey, tenantId)).ToList(); + if (!permissions.Any()) { - await PermissionGrantRepository.InsertAsync( - new PermissionGrant( - GuidGenerator.Create(), - permissionName, - providerName, - providerKey, - tenantId - ) - ); + return; } + await PermissionGrantRepository.InsertManyAsync(permissions); } } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js index 3723eda932..9f97800cbc 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/permission-management-modal.js @@ -291,6 +291,7 @@ var abp = abp || {}; $permissionSearchInput.keyup(throttle(function() { var searchTerm = $permissionSearchInput.val().toLowerCase(); filterTabs(searchTerm); + setFirstVisibleTabActive(); }, 300)); function filterTabs(searchTerm) { @@ -304,7 +305,7 @@ var abp = abp || {}; return; } - var tabName = $tabItem.find('small').text().toLowerCase(); + var tabName = $tabItem.text().toLowerCase(); var tabContentFilters = $($tabItem.attr('href')).find('[data-filter-text]'); let includedInTabContent = false; @@ -324,6 +325,18 @@ var abp = abp || {}; }); } + function setFirstVisibleTabActive() { + $('#PermissionsTabsContent .tab-pane').removeClass('active show'); + + var $tabs = $('#PermissionsTabs .nav-link'); + var $firstVisibleTab = $tabs.filter(':visible').first(); + $tabs.removeClass('active'); + $firstVisibleTab.addClass('active'); + + var $firstVisibleTabContent = $($firstVisibleTab.attr('href')); + $firstVisibleTabContent.addClass('active show'); + } + function throttle(mainFunction, delay) { let timerFlag = null; // Variable to keep track of the timer diff --git a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/package.json b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/package.json index b5bd592951..35f62891f2 100644 --- a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/package.json +++ b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/package.json @@ -3,6 +3,6 @@ "name": "demo-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/yarn.lock b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/yarn.lock index a8f2acc272..9e01130758 100644 --- a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/yarn.lock +++ b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/yarn.lock @@ -2,194 +2,194 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/package.json b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/package.json index fd190bf49c..a208eb337f 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/package.json +++ b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1", - "@abp/virtual-file-explorer": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0", + "@abp/virtual-file-explorer": "~9.0.0" } } diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/yarn.lock b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/yarn.lock index 5131eb3b96..c7af13ba41 100644 --- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/yarn.lock +++ b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/yarn.lock @@ -2,221 +2,221 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0-rc.1.tgz#3ad8c6bb5bea597aa56879dfe2d3e04caf648330" - integrity sha512-h/xoRcAYPh+QXSimH7x+NP8DoAHHLdHWf5Tq1qtY4pcnjV7f3NkZ8vZuxqeFJD47b5/IIcT6PSxjzUSixOukrA== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0-rc.1.tgz#bdf869811b475822c55bf0c856c1c5a7e0a50613" - integrity sha512-trRUDMenoQOSShznPwacx+cdfvsbDHmz24Oil7dBEFtkQLKdF4XD/PzCIDFHoQF1GsL5TGbrbrYIGOn4Hs/p5g== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.0.0-rc.1" - "@abp/bootstrap" "~9.0.0-rc.1" - "@abp/bootstrap-datepicker" "~9.0.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.0.0-rc.1" - "@abp/datatables.net-bs5" "~9.0.0-rc.1" - "@abp/font-awesome" "~9.0.0-rc.1" - "@abp/jquery-form" "~9.0.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.0.0-rc.1" - "@abp/lodash" "~9.0.0-rc.1" - "@abp/luxon" "~9.0.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.0.0-rc.1" - "@abp/moment" "~9.0.0-rc.1" - "@abp/select2" "~9.0.0-rc.1" - "@abp/sweetalert2" "~9.0.0-rc.1" - "@abp/timeago" "~9.0.0-rc.1" - "@abp/toastr" "~9.0.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0-rc.1.tgz#78cdbfacc5d5dd81f54428908d500d7bf12b2832" - integrity sha512-8CYyNCj82Z7aO73D8GxxuzHa9UyhqynzrPOj/aUlQzEo+TOuh+p4mEAF6CK+0aHJUEkTcnjYrHq1gD7z1TAhwg== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.0.0.tgz#e4b05d63446c24b612275e3949881e176d32527f" + integrity sha512-GHEt26xESe/TCg1q6ZjeUbxniqdxaiB1OPTZ9md7ONql6bEp8t9iUPeSlkyAZtQ7qBzwgkiLpkRFT+J21DftaQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.0.0" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.0.0.tgz#a77b4b70fa6217146afd6a57211f57e2360564f2" + integrity sha512-QmZrSp+rfqfnC9W4QZ+nNdAq0rOALzRn1rsDpGDHhIHwyXB03QPdjzIWaEvldUYHzqg84cEP0LcqW4y57Xr1iw== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.0.0" + "@abp/bootstrap" "~9.0.0" + "@abp/bootstrap-datepicker" "~9.0.0" + "@abp/bootstrap-daterangepicker" "~9.0.0" + "@abp/datatables.net-bs5" "~9.0.0" + "@abp/font-awesome" "~9.0.0" + "@abp/jquery-form" "~9.0.0" + "@abp/jquery-validation-unobtrusive" "~9.0.0" + "@abp/lodash" "~9.0.0" + "@abp/luxon" "~9.0.0" + "@abp/malihu-custom-scrollbar-plugin" "~9.0.0" + "@abp/moment" "~9.0.0" + "@abp/select2" "~9.0.0" + "@abp/sweetalert2" "~9.0.0" + "@abp/timeago" "~9.0.0" + "@abp/toastr" "~9.0.0" + +"@abp/aspnetcore.mvc.ui@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.0.0.tgz#93004dd056c130386c7b40c458f3a793d8c9e051" + integrity sha512-pvO5bh9baFcSbfW0s7tpMpbe6DKSC16jeyeluZLlvYxC0n2gkrv7H/hB5aMuBKIlh89aGY9DQIcMFC8iczL3Bg== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0-rc.1.tgz#af99754953f5333b8e092e72d4131e278f3965a4" - integrity sha512-rxJjeH29rzXXl5w9GbfzmUNelYIIcJMHC4ql4BMQJfZY0pEN8YJBwD35LDo2hemJo3YxcU/SnRXzVoI/FowQDA== +"@abp/bootstrap-datepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.0.0.tgz#d6609e50568aac6a013abfcaa07817998e1eaa99" + integrity sha512-wxAeVsOVOJpidDn0g3FlJvpOsn5SVY5IpEG+FtUxSAKuWYJQWF6g5CaghrfS+FNDK9IHhxrgSMPMVBK9YlDSzw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0-rc.1.tgz#1e1fde8f08e780320c7a310672ed8ecc33ad677a" - integrity sha512-mc45h2ESfrc2m0N9sBY4MzqyiQP8m2eWvq+owuIrrMX59W08xrquIrJlZrkXOOOlTDU0h/rlWRd5U7fWda9mYA== +"@abp/bootstrap-daterangepicker@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.0.0.tgz#fc2871e7d886accd8e4748cb763b695e10701c00" + integrity sha512-qS6SQR6X7wMCVLcuXatJ2+m1GNlpN71p7VDritxfwAMHa7WBRAAi8apX2WItwBAuLQ2s1uSA0Wp1KstHG3VPLA== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0-rc.1.tgz#15a0dde70565b56a97d8924e7bf24331fa3dd763" - integrity sha512-JObeca5jE+cHMDz4/oX7hzbkVgxBkQgNIxZW9I8VFqs3pNbqitDmGwp5mDWe2SmmTnLfy7bkuQWe5rcLbc72lA== +"@abp/bootstrap@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.0.0.tgz#5ab292e95ba7eef129cbaa1dc5f5d5c0af8530d7" + integrity sha512-jEr6su8BfoNxYvze/UlddE3DlezyPvQeiNhff8SDPqtRQ6XvjZ48O/JwtY01hK2njEDLOZINY5zJRGmO2OiOUw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" bootstrap "^5.3.3" -"@abp/clipboard@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0-rc.1.tgz#6997a792bbad262ccb9351913ec668e73cae5dc0" - integrity sha512-zQ6XIAehIfPBENs8intL3ekZhl1Sgh6EOn9QgkIzgLsyrnUrXgFdOHz96TGo5ttYOIEx8L5zoR29iCSLYBjDpg== +"@abp/clipboard@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.0.0.tgz#21ae924dfef6ccf3c8a3913bb81caf22b57404e4" + integrity sha512-W6S7pihpQ6Wfj48Clk7hYgDvUtnRwkNIsk5t8s9+LxoAdJQGQFxh7SAW1QNavUv8QqsClNE1VtSU87c7rSoAbA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" clipboard "^2.0.11" -"@abp/core@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0-rc.1.tgz#861e8b7f5dadb67dc40352ede0e639382d5b9125" - integrity sha512-ohOMk1ydTpnKdL2HnnbNhBfVDYiIxmQtvSBLeRI77KRpwMyf9Pgz3OH8c8kNgotBsJicZXrnOip20bwOHSivUA== +"@abp/core@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.0.0.tgz#dc5ea9139957e307f73ac1f40b179f991e3c2168" + integrity sha512-vzQyTpqVDx63pOI9e2QLUMWZCrSojHsRnzLlvl+/cKFi7jE1q/uSP66FPR2bwkD+DNLI/tn6is1Jx3skKA1FvA== dependencies: - "@abp/utils" "~9.0.0-rc.1" + "@abp/utils" "~9.0.0" -"@abp/datatables.net-bs5@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0-rc.1.tgz#32bf57f6905ba5400c07aec318a9a436476d37c2" - integrity sha512-30uST/rRuhpfiKZp1n0OamRnkQz8yh8OYMEXJJMwb8ZAfYk235FiGV8pZQKDoi773LJpjH7oljO6EohVZI6kwg== +"@abp/datatables.net-bs5@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.0.0.tgz#4daee90bdb6446e854ce65f2a3afabb2a13e49ae" + integrity sha512-ln10tcRwxcB0nuSgqJ/66strHsqMHDC03c0ktxEplAN34yP7KInjFf/U9Svo74K0nKlkJdMCgmqmT4CnBJZlIg== dependencies: - "@abp/datatables.net" "~9.0.0-rc.1" + "@abp/datatables.net" "~9.0.0" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0-rc.1.tgz#8004227f0f32bc67faac256a0d9a0a6d787192d3" - integrity sha512-VzAEAqAYjNp0Mgg7SYtt20+jJU5b+YW5q/TxMdV0X/56jS3C7CBN/rHtCZ3jMzDA7cEKffb/s12oezIAUTgb8Q== +"@abp/datatables.net@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.0.0.tgz#82b28518293c9091ec72d5defae2f5d2903d8bbc" + integrity sha512-QhuX3bGZOckM/fhIIGj/StMJIX2BBtNbLzjTR7WnKMMxDkv0+oDvjw6OqqpYKSvj/q3vY6sRWuCNdEzNi0Fk6A== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" datatables.net "^2.1.8" -"@abp/font-awesome@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0-rc.1.tgz#b0eeb3ca306f425e98747a94c9aec62967f8c7c3" - integrity sha512-bi0KkoTMCFO+cWAyYi2qRmE6XJh/4P4Y33XSFh3AMTAar5WDmIBxOitMVgWB6oZbKyU/qGImFph5pCb4TiRVDw== +"@abp/font-awesome@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.0.0.tgz#51cce18434a51d050ebb0d822a8c193b7e32f73d" + integrity sha512-bEHRVzOk0V2kFMAvB/YXFYaDKWRFO0+ScO7jrEFtFgdHXBcqy+dk1aM/N69WalyNmjRRpnh03GhH1LRpwL4/xA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0-rc.1.tgz#d54972c589856d07291f7182aae7c82f33b6ba74" - integrity sha512-k+vaJcP27x6lkCxiTFXyIaRz9kOwnU87qD2R1uNe7obUAqFqgMf6G+4YsOEyZbyeo34Q+9WGg5yfmarAkdavqQ== +"@abp/jquery-form@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.0.0.tgz#6518eb117ee35c6bc57543fd1fccb0a8cf8e22f4" + integrity sha512-6qpfPGHrjADmm7Ne3zcXBGPuLngG8ldAn5fk9k2taftpyX0iR67/nZxiQ0ujaQGgaai5Wb3imNXMG96XLnubkQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0-rc.1.tgz#1f6cf6986692959b9dec5e072d3e794b5173e708" - integrity sha512-gDNXLsnCDv8bE0mZi7720PyfLLlENws0lPcDD/jXWQebCloLdJuzYhEfc4BdSXYHOu9RZyAJRbtSet5YKda8dQ== +"@abp/jquery-validation-unobtrusive@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.0.0.tgz#8ee87dbdec5e92ab04ae9642a49af1598af31c1a" + integrity sha512-KlRQ1htyFmAIMS9xbHvHIcdhAgtPFe/u7c87MiWlk/CdhDrI3J+n5biLvQUzxCC+YWlwx27zBtPKx2vLeMRH6Q== dependencies: - "@abp/jquery-validation" "~9.0.0-rc.1" + "@abp/jquery-validation" "~9.0.0" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0-rc.1.tgz#17b806f253d591b0515207ab9673c83306c0b112" - integrity sha512-AMtkP0mRuKdITXcdlLv1fLcfAANRO2Ni67J/ltjFMx07IKgSB3Scle4+ohCNNebvx6oTYrQrFHRGXXL5SNGr1Q== +"@abp/jquery-validation@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.0.0.tgz#681d8037c57b3875bd51c927e350ffce65d7c5d2" + integrity sha512-XgCUBFWbhTDcGepD/xkwA/1Hl4TyYitRttauDJk3tuyXhNtykvdugCCOPY4j2s6VoT1Sb/TFFvOcgEvlBwkKiw== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" jquery-validation "^1.21.0" -"@abp/jquery@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0-rc.1.tgz#d92aa3464abe04fc77190d7f021303902c1b9fd7" - integrity sha512-26CprILmP2YE8GCLkLR2eH/M0PYgwRqC4qUsOXLKEn9Ujmmp1eSJk52K/3Cxo1iLe7yI7KKpElyAMqZbWcsxog== +"@abp/jquery@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.0.0.tgz#6c67a9f927be598ab6201f8888e8a3cb8bba0686" + integrity sha512-cUXA7v6F1HqAc/w8fQGxHIfA/6BqO+4uHXDnSsJZtrI26DTLOgw5kBNnAz2W4xggGPCY7SKFHNRZuOW/QfVRPg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" jquery "~3.7.1" -"@abp/lodash@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0-rc.1.tgz#f5118f38ace9fb5820786a43dde2512e9927fc21" - integrity sha512-vSxrXTXNR8uoWJRtUMCwY8EkuHDFm/yjYiHSoQVRtVgw8t05vVoUr7ZUIoRaBdrDTwGHkGHAbcwdidIWodFyow== +"@abp/lodash@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.0.0.tgz#a4d42b2dfeb37859ff9f0079c7a8a6cabc982efe" + integrity sha512-xoAsOkkgnQdPH2OyFTgF6OlCLVbyGF4u8CrFcZWCZmuIFT9cg0+ZEiq//Vog1pg3Lf//N37ceGpOag1LwMe6cQ== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" lodash "^4.17.21" -"@abp/luxon@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0-rc.1.tgz#9ccd4c78a4f6f438bc2542a5b4be720d9b5b0460" - integrity sha512-6RlJY87XlXpKCf1qX1xOik/6Vs1jVG9e0cEQCfXzvHgwlBzvjXXwHslimE623h2riVBOeO+zR5gfySivw24jig== +"@abp/luxon@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.0.0.tgz#a54dda13cbbd362481994d20d2e07c669c6ce109" + integrity sha512-aPejQnoVPfm60LnjwhfUkIsB+poNWusrBE0IHllxhvOVE+01nfa1Lvpp5AUWzV+XchPGOCSf+a29ds4EQWfNbg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0-rc.1.tgz#48c5d69d3fc925b5b2590e4eb870302acab803c9" - integrity sha512-iZkawrdTnKPaHw3PD0jwx6rwjJHoMjdanhD/Sf7/7ZoDT5tUxBwUXZf2eT6vLofCgou/SlZ5UngguVODzakX7A== +"@abp/malihu-custom-scrollbar-plugin@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.0.0.tgz#b8a49202d531c711874a2bcdae5081ae0ed34c3f" + integrity sha512-iSZ9lKMnv5F2SplR+A4blhFEDq79lKbvBQuS7h/Di3KEHFOdJY4pA8NP8OR+PXOF3JfAezGyjqy7ydn/JNPRwA== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0-rc.1.tgz#138c0295140e13e706533b1ed6d90a294d5a78c1" - integrity sha512-iwwApTQgOLoJYCgzM9U9oC4aJfEQEWw4+7HnLPjNbqYlIMwazEuvAxi4kCe6MjiUMr45KNEWRDdtVo+Q/0fmUw== +"@abp/moment@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.0.0.tgz#9583e97472ddf608a9a5a6b8a37fee602b419900" + integrity sha512-wgyJSKmBmHLXZJN3dy3zK4i2JvWGgqnvdtrKURy/raEurxlymv8JF5JA971kTv6Kz2OA/OSYttpVJkDGUpPAhA== dependencies: moment "^2.30.1" -"@abp/prismjs@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0-rc.1.tgz#be4f23d69f780a693d65a1eacefb2aef51c5d205" - integrity sha512-tgTo+GlBzGH1qwbzdAd+MHgf6BIbGraCQwaeuKu13EXMt1vi4vB9i14YzaZClgaQ0cxEN3+6qheejPjkWU623A== +"@abp/prismjs@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.0.0.tgz#2ac4a5ddc0c8e0462af027a4dd97a177a3d6f7a5" + integrity sha512-+evmBq5qV+Ix/TNqO2ljJn0jygW2rEgKNtABcBGmrZC8xiI7+2hjKmSE0e43qb+RDib8aJjwH8ya8wF7p68ZFw== dependencies: - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/core" "~9.0.0-rc.1" + "@abp/clipboard" "~9.0.0" + "@abp/core" "~9.0.0" prismjs "^1.29.0" -"@abp/select2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0-rc.1.tgz#e4d5a4013b652147bc84434acd34829c136db2d6" - integrity sha512-oOON+upZ7jlbhNeGDG+nT4XXZYbEZIOwo10yrxTUiGGghSL2nI7z9LtL2eeI0QyD+fhTylSM+UvTxuNn6xyieA== +"@abp/select2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.0.0.tgz#71503eebb746f40a0e565dba1efa05d6ae937b77" + integrity sha512-l+Hz2Qmc7AcyaTJOyuDaV99RbBWYxYxbeyVEc4xKbRFbJxYBUxT/DFlyozEaoz+OU1fl4szO3UCthJ2yZvxCdg== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" select2 "^4.0.13" -"@abp/sweetalert2@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0-rc.1.tgz#d4047255c5f0a8dc25489e94d0959006c053069e" - integrity sha512-pXu3MuzHJQ8Clj4I4JoiJ6L4Ax59vy9zOD9FT4lfHUbtIqbWi1/OGoqU6QWK7565u3n1UtPvSvnCXIBMrwVjaA== +"@abp/sweetalert2@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.0.0.tgz#71e511117c18b515e5c658e9cc0667770af65d91" + integrity sha512-wxDqoA6RUhkbcN27Kzslu/m2ai5T9AkJRtgs7pV55LvPv1ohuCPEUeTVVh8S/5Pgmr7aPFAPxaaCO32aPcImPw== dependencies: - "@abp/core" "~9.0.0-rc.1" + "@abp/core" "~9.0.0" sweetalert2 "^11.14.1" -"@abp/timeago@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0-rc.1.tgz#bdd6a55d99952cac9aba505696bb47f4dbd04bac" - integrity sha512-8djCLc74THSAqBtBOqRVCtSzZFNW3Y0y2cO5eUak5NxTqMOEw9hebAwO5CCbqSpSz3xJHQOIVU7eiXFyozo/IA== +"@abp/timeago@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.0.0.tgz#8f262ba2a74e1c133d0c129f8a0bc55c29441e1a" + integrity sha512-eaNdIUEtDXnuYqS5O7EGRV+j6XOLAsxz7gd5BIKR9lDujd8pEjSJkXKO+/0KxLTkUSy3JudIO37K1h2wTpbYZA== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" timeago "^1.6.7" -"@abp/toastr@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0-rc.1.tgz#9a17a5b366208d58a6f6f7e950de25331fbdda85" - integrity sha512-hdfYVgorl5wkn0vovk2IXYU5//b4AfYq07Y/fSjk+NeSwRp/9a4T+H3vLDGq4E76yVkD7ipEP84XRh9zAWBLBA== +"@abp/toastr@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/toastr/-/toastr-9.0.0.tgz#74d74ecb3e7f2d63b2ff7735c89a40deb3dc3a13" + integrity sha512-n9uJvw8l2HoxeowPO4diEMxwchGh6puefhyRljFAAstzK77Mhn0u2J7kPynNv94rLSYTYoCxUeJ4TTN+/TVDGQ== dependencies: - "@abp/jquery" "~9.0.0-rc.1" + "@abp/jquery" "~9.0.0" toastr "^2.1.4" -"@abp/utils@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0-rc.1.tgz#22e4dbd66a245823d0ab02a326bf256e4f4e560d" - integrity sha512-OOeJ+ajOKLrI4gzL81xnziWNt4HfTEdRkQ6ftepTtGRZWo60oR88btXwOGydYKPLKfHMwc82mVyYKLa3uhuemQ== +"@abp/utils@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.0.0.tgz#2264fd83105b061860edd98dbe0efdfe55803ed5" + integrity sha512-/SB4VYk3Av+ltXv6ovkFHG4iWiECLLitaYWcEHxVAO80ufNjrNnWpHFpXHP8u/RpXIp/CoNiHLr6j5TkZUTZjw== dependencies: just-compare "^2.3.0" -"@abp/virtual-file-explorer@~9.0.0-rc.1": - version "9.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/virtual-file-explorer/-/virtual-file-explorer-9.0.0-rc.1.tgz#fe6225351ecaa66def8c526e990db6e7606b2a34" - integrity sha512-6lJa3YGfUGICDI0pU341VXKAA4/WsnaFe2VS+ya5SlN5ZCTPExpZuJ9aIp6/PoEuVluq/MuNdIUu3zq0BZVhjw== +"@abp/virtual-file-explorer@~9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@abp/virtual-file-explorer/-/virtual-file-explorer-9.0.0.tgz#d3216774bd8f04550ae410f49e574dca6680ac0e" + integrity sha512-3w44RM0VxgpYLf7i163r4rj4DGm7UXEviQgRrmSMUx/EkVMFkDtHoisDymDEdBAx74ZYiT7B9GASpTlSHI+gWw== dependencies: - "@abp/clipboard" "~9.0.0-rc.1" - "@abp/prismjs" "~9.0.0-rc.1" + "@abp/clipboard" "~9.0.0" + "@abp/prismjs" "~9.0.0" "@fortawesome/fontawesome-free@^6.6.0": version "6.6.0" diff --git a/npm/lerna.json b/npm/lerna.json index 06feaff6f5..dfc1ca5399 100644 --- a/npm/lerna.json +++ b/npm/lerna.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "packages": [ "packs/*" ], diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index 4ed0b70a49..62c900f069 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -44,8 +44,8 @@ }, "private": true, "devDependencies": { - "@abp/ng.theme.lepton-x": "~4.0.0-rc.1", - "@abp/utils": "~9.0.0-rc.1", + "@abp/ng.theme.lepton-x": "~4.0.0", + "@abp/utils": "~9.0.0", "@angular-devkit/build-angular": "~18.1.0", "@angular-devkit/core": "~18.1.0", "@angular-devkit/schematics": "~18.1.0", diff --git a/npm/ng-packs/packages/account-core/package.json b/npm/ng-packs/packages/account-core/package.json index 8b1bb13457..f5c50b88bb 100644 --- a/npm/ng-packs/packages/account-core/package.json +++ b/npm/ng-packs/packages/account-core/package.json @@ -1,14 +1,14 @@ { "name": "@abp/ng.account.core", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.core": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.core": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/account/package.json b/npm/ng-packs/packages/account/package.json index 1dccab2972..8dd0183733 100644 --- a/npm/ng-packs/packages/account/package.json +++ b/npm/ng-packs/packages/account/package.json @@ -1,14 +1,14 @@ { "name": "@abp/ng.account", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.account.core": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.account.core": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/account/src/lib/guards/extensions.guard.ts b/npm/ng-packs/packages/account/src/lib/guards/extensions.guard.ts index a67db6c7b9..7e0254d7b4 100644 --- a/npm/ng-packs/packages/account/src/lib/guards/extensions.guard.ts +++ b/npm/ng-packs/packages/account/src/lib/guards/extensions.guard.ts @@ -1,7 +1,7 @@ -import { Injectable, inject } from '@angular/core'; +import { Injectable, Injector, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { tap, map } from 'rxjs/operators'; -import { ConfigStateService, IAbpGuard, PermissionService } from '@abp/ng.core'; +import { IAbpGuard } from '@abp/ng.core'; import { ExtensionsService, getObjectExtensionEntitiesFromStore, @@ -20,8 +20,7 @@ import { eAccountComponents } from '../enums/components'; */ @Injectable() export class AccountExtensionsGuard implements IAbpGuard { - protected readonly configState = inject(ConfigStateService); - protected readonly permmission = inject(PermissionService); + protected readonly injector = inject(Injector); protected readonly extensions = inject(ExtensionsService); canActivate(): Observable { @@ -29,11 +28,11 @@ export class AccountExtensionsGuard implements IAbpGuard { const editFormContributors = inject(ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS, config) || {}; - return getObjectExtensionEntitiesFromStore(this.configState, 'Identity').pipe( + return getObjectExtensionEntitiesFromStore(this.injector, 'Identity').pipe( map(entities => ({ [eAccountComponents.PersonalSettings]: entities.User, })), - mapEntitiesToContributors(this.configState, this.permmission, 'AbpIdentity'), + mapEntitiesToContributors(this.injector, 'AbpIdentity'), tap(objectExtensionContributors => { mergeWithDefaultProps( this.extensions.editFormProps, diff --git a/npm/ng-packs/packages/account/src/lib/resolvers/extensions.resolver.ts b/npm/ng-packs/packages/account/src/lib/resolvers/extensions.resolver.ts index e744e98442..623de9f49c 100644 --- a/npm/ng-packs/packages/account/src/lib/resolvers/extensions.resolver.ts +++ b/npm/ng-packs/packages/account/src/lib/resolvers/extensions.resolver.ts @@ -1,7 +1,6 @@ -import { inject } from '@angular/core'; +import { inject, Injector } from '@angular/core'; import { ResolveFn } from '@angular/router'; import { map, tap } from 'rxjs'; -import { ConfigStateService, PermissionService } from '@abp/ng.core'; import { ExtensionsService, getObjectExtensionEntitiesFromStore, @@ -12,19 +11,18 @@ import { eAccountComponents } from '../enums'; import { ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS, DEFAULT_ACCOUNT_FORM_PROPS } from '../tokens'; export const accountExtensionsResolver: ResolveFn = () => { - const configState = inject(ConfigStateService); - const permission = inject(PermissionService); + const injector = inject(Injector); const extensions = inject(ExtensionsService); const config = { optional: true }; const editFormContributors = inject(ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS, config) || {}; - return getObjectExtensionEntitiesFromStore(configState, 'Identity').pipe( + return getObjectExtensionEntitiesFromStore(injector, 'Identity').pipe( map(entities => ({ [eAccountComponents.PersonalSettings]: entities.User, })), - mapEntitiesToContributors(configState, permission, 'AbpIdentity'), + mapEntitiesToContributors(injector, 'AbpIdentity'), tap(objectExtensionContributors => { mergeWithDefaultProps( extensions.editFormProps, diff --git a/npm/ng-packs/packages/components/extensible/src/lib/utils/props.util.ts b/npm/ng-packs/packages/components/extensible/src/lib/utils/props.util.ts index 7f06a9b1de..084f33db90 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/utils/props.util.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/utils/props.util.ts @@ -1,4 +1,5 @@ import { ConfigStateService, PermissionService } from '@abp/ng.core'; +import { Injector } from '@angular/core'; import { Observable, of } from 'rxjs'; import { EXTRA_PROPERTIES_KEY } from '../constants/extra-properties'; import { @@ -52,20 +53,21 @@ export function mergeWithDefaultProps>( } export function checkPolicies( + injector: Injector, properties: ObjectExtensions.EntityExtensionProperties, - configState: ConfigStateService, - permissionService: PermissionService, ) { + const configState = injector.get(ConfigStateService); + const permission = injector.get(PermissionService); const props = Object.entries(properties); const checkPolicy = (policy: Policy): boolean => { - const { permissions, globalFeatures, features } = policy; + const { permissions, globalFeatures, features } = policy || {}; const checks = [ { items: permissions?.permissionNames, requiresAll: permissions?.requiresAll, - check: (item: string) => permissionService.getGrantedPolicy(item), + check: (item: string) => permission.getGrantedPolicy(item), }, { items: globalFeatures?.features, diff --git a/npm/ng-packs/packages/components/extensible/src/lib/utils/state.util.ts b/npm/ng-packs/packages/components/extensible/src/lib/utils/state.util.ts index 68a97e844c..cb72dabd18 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/utils/state.util.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/utils/state.util.ts @@ -5,8 +5,8 @@ import { ExtensionEnumDto, ExtensionPropertyUiLookupDto, ObjectExtensionsDto, - PermissionService, } from '@abp/ng.core'; +import { Injector } from '@angular/core'; import { Observable, pipe, zip } from 'rxjs'; import { filter, map, switchMap, take } from 'rxjs/operators'; import { ePropType } from '../enums/props.enum'; @@ -56,10 +56,8 @@ function selectEnums( ); } -export function getObjectExtensionEntitiesFromStore( - configState: ConfigStateService, - moduleKey: string, -) { +export function getObjectExtensionEntitiesFromStore(injector: Injector, moduleKey: string) { + const configState = injector.get(ConfigStateService); return selectObjectExtensions(configState).pipe( map(extensions => { if (!extensions) return null; @@ -73,11 +71,8 @@ export function getObjectExtensionEntitiesFromStore( ); } -export function mapEntitiesToContributors( - configState: ConfigStateService, - permissionService: PermissionService, - resource: string, -) { +export function mapEntitiesToContributors(injector: Injector, resource: string) { + const configState = injector.get(ConfigStateService); return pipe( switchMap((entities: any) => zip(selectLocalization(configState), selectEnums(configState)).pipe( @@ -100,7 +95,7 @@ export function mapEntitiesToContributors( return acc; } - checkPolicies(properties, configState, permissionService); + checkPolicies(injector, properties); const mapPropertiesToContributors = createPropertiesToContributorsMapper( generateDisplayName, diff --git a/npm/ng-packs/packages/components/extensible/src/tests/form-props.util.spec.ts b/npm/ng-packs/packages/components/extensible/src/tests/form-props.util.spec.ts index 123912cb9a..ae3698757d 100644 --- a/npm/ng-packs/packages/components/extensible/src/tests/form-props.util.spec.ts +++ b/npm/ng-packs/packages/components/extensible/src/tests/form-props.util.spec.ts @@ -107,7 +107,7 @@ describe('Form Prop Utils', () => { extraProperties: { bool: true, date: '03/30/2002', - dateTime: '2002-03-30 13:30:59Z', + dateTime: '2002-03-30 13:30:59', time: '13:30:59', }, }); @@ -117,8 +117,8 @@ describe('Form Prop Utils', () => { expect(extraPropertiesGroup.value).toEqual({ bool: true, date: '2002-03-30', - dateTime: '2002-03-30T13:30:59.000Z', - time: '13:30', + dateTime: '2002-03-30T13:30:59.000', + time: '13:30:59', }); }); }); diff --git a/npm/ng-packs/packages/components/extensible/src/tests/props.util.spec.ts b/npm/ng-packs/packages/components/extensible/src/tests/props.util.spec.ts index fc2b9a3282..ce9a439133 100644 --- a/npm/ng-packs/packages/components/extensible/src/tests/props.util.spec.ts +++ b/npm/ng-packs/packages/components/extensible/src/tests/props.util.spec.ts @@ -1,3 +1,11 @@ +import { ConfigStateService, PermissionService } from '@abp/ng.core'; +import { Injector } from '@angular/core'; +import { + checkPolicies, + createExtraPropertyValueResolver, + mergeWithDefaultProps, +} from '../lib/utils/props.util'; +import { ObjectExtensions } from '../lib/models/object-extensions'; import { EntityProp, EntityPropContributorCallbacks, @@ -5,7 +13,6 @@ import { EntityPropsFactory, } from '../lib/models/entity-props'; import { PropData } from '../lib/models/props'; -import { createExtraPropertyValueResolver, mergeWithDefaultProps } from '../lib/utils/props.util'; class MockPropData extends PropData { getInjected: PropData['getInjected']; @@ -69,4 +76,194 @@ describe('Entity Prop Utils', () => { expect(entityProps.get('y').props.toString()).toBe('3 <-> 2'); }); }); + + describe('#checkPolicies', () => { + let injector: Injector; + let configState: ConfigStateService; + let permissionService: PermissionService; + + beforeEach(() => { + jest.clearAllMocks(); + + configState = { + getGlobalFeatureIsEnabled: jest.fn().mockReturnValue(false), + getFeatureIsEnabled: jest.fn().mockReturnValue(false), + } as any; + + permissionService = { + getGrantedPolicy: jest.fn().mockReturnValue(false), + } as any; + + injector = { + get: jest.fn().mockImplementation(service => { + if (service === ConfigStateService) { + return configState; + } + if (service === PermissionService) { + return permissionService; + } + return null; + }), + } as any; + }); + + it('should keep property when all permissions and features are satisfied', () => { + (permissionService.getGrantedPolicy as jest.Mock).mockReturnValue(true); + (configState.getGlobalFeatureIsEnabled as jest.Mock).mockReturnValue(true); + (configState.getFeatureIsEnabled as jest.Mock).mockReturnValue(true); + + const properties: ObjectExtensions.EntityExtensionProperties = { + property1: { + policy: { + permissions: { permissionNames: ['Permission1', 'Permission2'], requiresAll: true }, + globalFeatures: { features: ['GlobalFeature1'], requiresAll: true }, + features: { features: ['Feature1'], requiresAll: true }, + }, + displayName: undefined, + api: undefined, + ui: undefined, + attributes: [], + configuration: undefined, + defaultValue: undefined, + }, + }; + + checkPolicies(injector, properties); + + expect(properties.property1).toBeDefined(); + expect(permissionService.getGrantedPolicy).toHaveBeenCalledWith('Permission1'); + expect(permissionService.getGrantedPolicy).toHaveBeenCalledWith('Permission2'); + expect(configState.getGlobalFeatureIsEnabled).toHaveBeenCalledWith('GlobalFeature1'); + expect(configState.getFeatureIsEnabled).toHaveBeenCalledWith('Feature1'); + }); + + it('should keep property when no permissions and features are satisfied', () => { + (permissionService.getGrantedPolicy as jest.Mock).mockReturnValue(false); + (configState.getGlobalFeatureIsEnabled as jest.Mock).mockReturnValue(false); + (configState.getFeatureIsEnabled as jest.Mock).mockReturnValue(false); + + const properties: ObjectExtensions.EntityExtensionProperties = { + property1: { + policy: { + permissions: { permissionNames: ['Permission1', 'Permission2'], requiresAll: true }, + globalFeatures: { features: ['GlobalFeature1'], requiresAll: true }, + features: { features: ['Feature1'], requiresAll: true }, + }, + displayName: undefined, + api: undefined, + ui: undefined, + attributes: [], + configuration: undefined, + defaultValue: undefined, + }, + }; + + checkPolicies(injector, properties); + + expect(properties.property1).toBeUndefined(); + expect(permissionService.getGrantedPolicy).toHaveBeenCalledWith('Permission1'); + expect(permissionService.getGrantedPolicy).not.toHaveBeenCalledWith('Permission2'); + expect(configState.getGlobalFeatureIsEnabled).not.toHaveBeenCalledWith('GlobalFeature1'); + expect(configState.getFeatureIsEnabled).not.toHaveBeenCalledWith('Feature1'); + }); + + it('should delete property when only some permissions are granted', () => { + (permissionService.getGrantedPolicy as jest.Mock).mockImplementation( + permission => permission === 'Permission1', + ); + (configState.getGlobalFeatureIsEnabled as jest.Mock).mockReturnValue(true); + (configState.getFeatureIsEnabled as jest.Mock).mockReturnValue(true); + + const properties: ObjectExtensions.EntityExtensionProperties = { + property1: { + policy: { + permissions: { permissionNames: ['Permission1', 'Permission2'], requiresAll: true }, + globalFeatures: { features: ['GlobalFeature1'], requiresAll: true }, + features: { features: ['Feature1'], requiresAll: true }, + }, + displayName: undefined, + api: undefined, + ui: undefined, + attributes: [], + configuration: undefined, + defaultValue: undefined, + }, + }; + + checkPolicies(injector, properties); + + expect(properties.property1).toBeUndefined(); + expect(permissionService.getGrantedPolicy).toHaveBeenCalledWith('Permission1'); + expect(permissionService.getGrantedPolicy).toHaveBeenCalledWith('Permission2'); + }); + + it('should delete property when some global features are disabled', () => { + (permissionService.getGrantedPolicy as jest.Mock).mockReturnValue(true); + (configState.getGlobalFeatureIsEnabled as jest.Mock).mockImplementation(feature => + feature === 'GlobalFeature2' ? false : true, + ); + (configState.getFeatureIsEnabled as jest.Mock).mockReturnValue(true); + + const properties: ObjectExtensions.EntityExtensionProperties = { + property1: { + policy: { + permissions: { permissionNames: ['Permission1'], requiresAll: true }, + globalFeatures: { features: ['GlobalFeature1', 'GlobalFeature2'], requiresAll: true }, + features: { features: ['Feature1'], requiresAll: true }, + }, + displayName: undefined, + api: undefined, + ui: undefined, + attributes: [], + configuration: undefined, + defaultValue: undefined, + }, + }; + + checkPolicies(injector, properties); + + expect(properties.property1).toBeUndefined(); + expect(configState.getGlobalFeatureIsEnabled).toHaveBeenCalledWith('GlobalFeature1'); + expect(configState.getGlobalFeatureIsEnabled).toHaveBeenCalledWith('GlobalFeature2'); + }); + + it('should keep property when all permissions are granted but only some features are required', () => { + (permissionService.getGrantedPolicy as jest.Mock).mockImplementation( + permission => permission === 'Permission1' || permission === 'Permission2', + ); + (configState.getFeatureIsEnabled as jest.Mock).mockImplementation( + feature => feature === 'Feature1', + ); + (configState.getGlobalFeatureIsEnabled as jest.Mock).mockReturnValue(true); + + const properties: ObjectExtensions.EntityExtensionProperties = { + property1: { + policy: { + permissions: { permissionNames: ['Permission1', 'Permission2'], requiresAll: false }, + features: { + features: ['Feature1', 'Feature2', 'Feature3'], + requiresAll: false, + }, + globalFeatures: { features: ['GlobalFeature1'], requiresAll: true }, + }, + displayName: undefined, + api: undefined, + ui: undefined, + attributes: [], + configuration: undefined, + defaultValue: undefined, + }, + }; + + checkPolicies(injector, properties); + + expect(properties.property1).toBeDefined(); + + expect(configState.getFeatureIsEnabled).toHaveBeenCalledWith('Feature1'); + expect(configState.getFeatureIsEnabled).not.toHaveBeenCalledWith('Feature2'); + expect(configState.getFeatureIsEnabled).not.toHaveBeenCalledWith('Feature3'); + + expect(configState.getGlobalFeatureIsEnabled).toHaveBeenCalledWith('GlobalFeature1'); + }); + }); }); diff --git a/npm/ng-packs/packages/components/extensible/src/tests/state.util.spec.ts b/npm/ng-packs/packages/components/extensible/src/tests/state.util.spec.ts index 006ea1101e..de6e5d73c6 100644 --- a/npm/ng-packs/packages/components/extensible/src/tests/state.util.spec.ts +++ b/npm/ng-packs/packages/components/extensible/src/tests/state.util.spec.ts @@ -1,4 +1,4 @@ -import { ConfigStateService, PermissionService } from '@abp/ng.core'; +import { ConfigStateService } from '@abp/ng.core'; import { firstValueFrom, lastValueFrom, of } from 'rxjs'; import { take } from 'rxjs/operators'; import { ePropType } from '../lib/enums/props.enum'; @@ -9,18 +9,25 @@ import { getObjectExtensionEntitiesFromStore, mapEntitiesToContributors, } from '../lib/utils/state.util'; +import { Injector } from '@angular/core'; const fakeAppConfigService = { get: () => of(createMockState()) } as any; const fakeLocalizationService = { get: () => of(createMockState()) } as any; const configState = new ConfigStateService(fakeAppConfigService, fakeLocalizationService, false); configState.refreshAppState(); -const permissionService = new PermissionService(configState); describe('State Utils', () => { + let injector: Injector; + beforeEach(() => { + injector = { + get: jest.fn().mockReturnValue(configState), + }; + }); + describe('#getObjectExtensionEntitiesFromStore', () => { it('should return observable entities of an existing module', async () => { const objectExtensionEntitiesFromStore$ = getObjectExtensionEntitiesFromStore( - configState, + injector, 'Identity', ); @@ -29,7 +36,7 @@ describe('State Utils', () => { }); it('should return observable empty object if module does not exist', async () => { - const entities = await getObjectExtensionEntitiesFromStore(configState, 'Saas').toPromise(); + const entities = await getObjectExtensionEntitiesFromStore(injector, 'Saas').toPromise(); expect(entities).toEqual({}); }); @@ -37,7 +44,11 @@ describe('State Utils', () => { const emptyConfigState = new ConfigStateService(null, null, false); const emit = jest.fn(); - getObjectExtensionEntitiesFromStore(emptyConfigState, 'Identity').subscribe(emit); + injector = { + get: jest.fn().mockReturnValue(emptyConfigState), + }; + + getObjectExtensionEntitiesFromStore(injector, 'Identity').subscribe(emit); setTimeout(() => { expect(emit).not.toHaveBeenCalled(); @@ -49,10 +60,7 @@ describe('State Utils', () => { describe('#mapEntitiesToContributors', () => { it('should return contributors from given entities', async () => { const contributors = await lastValueFrom( - of(createMockEntities()).pipe( - mapEntitiesToContributors(configState, permissionService, 'AbpIdentity'), - take(1), - ), + of(createMockEntities()).pipe(mapEntitiesToContributors(injector, 'AbpIdentity'), take(1)), ); const propList = new EntityPropList(); diff --git a/npm/ng-packs/packages/components/package.json b/npm/ng-packs/packages/components/package.json index d86b47c29f..71b46443f9 100644 --- a/npm/ng-packs/packages/components/package.json +++ b/npm/ng-packs/packages/components/package.json @@ -1,14 +1,14 @@ { "name": "@abp/ng.components", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "peerDependencies": { - "@abp/ng.core": ">=9.0.0-rc.1", - "@abp/ng.theme.shared": ">=9.0.0-rc.1" + "@abp/ng.core": ">=9.0.0", + "@abp/ng.theme.shared": ">=9.0.0" }, "dependencies": { "chart.js": "^3.5.1", diff --git a/npm/ng-packs/packages/components/page/src/page.component.ts b/npm/ng-packs/packages/components/page/src/page.component.ts index d0a48b145c..06a8e3af6d 100644 --- a/npm/ng-packs/packages/components/page/src/page.component.ts +++ b/npm/ng-packs/packages/components/page/src/page.component.ts @@ -45,7 +45,8 @@ export class PageComponent { this.breadcrumb || this.customTitle || this.customBreadcrumb || - this.customToolbar + this.customToolbar || + this.pageParts ); } } diff --git a/npm/ng-packs/packages/core/package.json b/npm/ng-packs/packages/core/package.json index f436246ad6..ffa8294cde 100644 --- a/npm/ng-packs/packages/core/package.json +++ b/npm/ng-packs/packages/core/package.json @@ -1,13 +1,13 @@ { "name": "@abp/ng.core", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/utils": "~9.0.0-rc.1", + "@abp/utils": "~9.0.0", "just-clone": "^6.0.0", "just-compare": "^2.0.0", "ts-toolbelt": "^9.0.0", diff --git a/npm/ng-packs/packages/feature-management/package.json b/npm/ng-packs/packages/feature-management/package.json index 00f28ed22c..76bda5d6ba 100644 --- a/npm/ng-packs/packages/feature-management/package.json +++ b/npm/ng-packs/packages/feature-management/package.json @@ -1,13 +1,13 @@ { "name": "@abp/ng.feature-management", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html index 0575d0cdc4..9f071e44a0 100644 --- a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html +++ b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.html @@ -31,7 +31,7 @@
    @switch (feature.valueType?.name) { @case (valueTypes.ToggleStringValueType) { -
    +
    } @case (valueTypes.FreeTextStringValueType) { -
    +
    @@ -74,7 +74,7 @@ } @case (valueTypes.SelectionStringValueType) { @if (feature.valueType.itemSource?.items?.length) { -
    +
    diff --git a/npm/ng-packs/packages/generators/package.json b/npm/ng-packs/packages/generators/package.json index c8e807f9e9..e20ce16306 100644 --- a/npm/ng-packs/packages/generators/package.json +++ b/npm/ng-packs/packages/generators/package.json @@ -1,6 +1,6 @@ { "name": "@abp/nx.generators", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "generators": "./generators.json", "type": "commonjs", diff --git a/npm/ng-packs/packages/identity/package.json b/npm/ng-packs/packages/identity/package.json index 2a59260e6e..8d12037ac4 100644 --- a/npm/ng-packs/packages/identity/package.json +++ b/npm/ng-packs/packages/identity/package.json @@ -1,15 +1,15 @@ { "name": "@abp/ng.identity", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.components": "~9.0.0-rc.1", - "@abp/ng.permission-management": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.components": "~9.0.0", + "@abp/ng.permission-management": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/identity/src/lib/guards/extensions.guard.ts b/npm/ng-packs/packages/identity/src/lib/guards/extensions.guard.ts index 5d78bba9fb..5b18b126d5 100644 --- a/npm/ng-packs/packages/identity/src/lib/guards/extensions.guard.ts +++ b/npm/ng-packs/packages/identity/src/lib/guards/extensions.guard.ts @@ -5,8 +5,8 @@ import { mergeWithDefaultActions, mergeWithDefaultProps, } from '@abp/ng.components/extensible'; -import { ConfigStateService, IAbpGuard, PermissionService } from '@abp/ng.core'; -import { Injectable, inject } from '@angular/core'; +import { IAbpGuard } from '@abp/ng.core'; +import { Injectable, Injector, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; @@ -30,8 +30,7 @@ import { */ @Injectable() export class IdentityExtensionsGuard implements IAbpGuard { - protected readonly configState = inject(ConfigStateService); - protected readonly permission = inject(PermissionService); + protected readonly injector = inject(Injector); protected readonly extensions = inject(ExtensionsService); canActivate(): Observable { @@ -43,12 +42,12 @@ export class IdentityExtensionsGuard implements IAbpGuard { const createFormContributors = inject(IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS, config) || {}; const editFormContributors = inject(IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS, config) || {}; - return getObjectExtensionEntitiesFromStore(this.configState, 'Identity').pipe( + return getObjectExtensionEntitiesFromStore(this.injector, 'Identity').pipe( map(entities => ({ [eIdentityComponents.Roles]: entities.Role, [eIdentityComponents.Users]: entities.User, })), - mapEntitiesToContributors(this.configState, this.permission, 'AbpIdentity'), + mapEntitiesToContributors(this.injector, 'AbpIdentity'), tap(objectExtensionContributors => { mergeWithDefaultActions( this.extensions.entityActions, diff --git a/npm/ng-packs/packages/identity/src/lib/resolvers/extensions.resolver.ts b/npm/ng-packs/packages/identity/src/lib/resolvers/extensions.resolver.ts index 812a63d3f7..7dac7979cb 100644 --- a/npm/ng-packs/packages/identity/src/lib/resolvers/extensions.resolver.ts +++ b/npm/ng-packs/packages/identity/src/lib/resolvers/extensions.resolver.ts @@ -5,8 +5,7 @@ import { mergeWithDefaultActions, mergeWithDefaultProps, } from '@abp/ng.components/extensible'; -import { ConfigStateService, PermissionService } from '@abp/ng.core'; -import { inject } from '@angular/core'; +import { inject, Injector } from '@angular/core'; import { ResolveFn } from '@angular/router'; import { map, tap } from 'rxjs'; import { eIdentityComponents } from '../enums'; @@ -24,8 +23,6 @@ import { } from '../tokens'; export const identityExtensionsResolver: ResolveFn = () => { - const configState = inject(ConfigStateService); - const permission = inject(PermissionService); const extensions = inject(ExtensionsService); const config = { optional: true }; @@ -36,12 +33,13 @@ export const identityExtensionsResolver: ResolveFn = () => { const createFormContributors = inject(IDENTITY_CREATE_FORM_PROP_CONTRIBUTORS, config) || {}; const editFormContributors = inject(IDENTITY_EDIT_FORM_PROP_CONTRIBUTORS, config) || {}; - return getObjectExtensionEntitiesFromStore(configState, 'Identity').pipe( + const injector = inject(Injector); + return getObjectExtensionEntitiesFromStore(injector, 'Identity').pipe( map(entities => ({ [eIdentityComponents.Roles]: entities.Role, [eIdentityComponents.Users]: entities.User, })), - mapEntitiesToContributors(configState, permission, 'AbpIdentity'), + mapEntitiesToContributors(injector, 'AbpIdentity'), tap(objectExtensionContributors => { mergeWithDefaultActions( extensions.entityActions, diff --git a/npm/ng-packs/packages/oauth/package.json b/npm/ng-packs/packages/oauth/package.json index ea60d47d00..84b3d60e43 100644 --- a/npm/ng-packs/packages/oauth/package.json +++ b/npm/ng-packs/packages/oauth/package.json @@ -1,14 +1,14 @@ { "name": "@abp/ng.oauth", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.core": "~9.0.0-rc.1", - "@abp/utils": "~9.0.0-rc.1", + "@abp/ng.core": "~9.0.0", + "@abp/utils": "~9.0.0", "angular-oauth2-oidc": "^17.0.0", "just-clone": "^6.0.0", "just-compare": "^2.0.0", diff --git a/npm/ng-packs/packages/permission-management/package.json b/npm/ng-packs/packages/permission-management/package.json index 2d5e69d49e..6466d2ffd2 100644 --- a/npm/ng-packs/packages/permission-management/package.json +++ b/npm/ng-packs/packages/permission-management/package.json @@ -1,13 +1,13 @@ { "name": "@abp/ng.permission-management", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/schematics/package.json b/npm/ng-packs/packages/schematics/package.json index 2e162436d2..292b57c82d 100644 --- a/npm/ng-packs/packages/schematics/package.json +++ b/npm/ng-packs/packages/schematics/package.json @@ -1,6 +1,6 @@ { "name": "@abp/ng.schematics", - "version": "9.0.0-rc.1", + "version": "9.0.0", "author": "", "schematics": "./collection.json", "dependencies": { diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts index f922288f31..de0c75c2ef 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts @@ -15,6 +15,7 @@ import { import { ThemeOptionsEnum } from './theme-options.enum'; import { addImportToModule, + addProviderToModule, findNodes, getDecoratorMetadata, getMetadataField, @@ -49,8 +50,7 @@ function updateProjectStyle( throw new SchematicsException('The target project does not selected'); } - const isProjectLibrary = isLibrary(project); - if (isProjectLibrary) { + if (isLibrary(project)) { throw new SchematicsException('The library project does not supported'); } @@ -73,7 +73,9 @@ function updateAppModule(selectedProject: string, targetThemeName: ThemeOptionsE return chain([ removeImportPath(appModulePath, targetThemeName), removeImportFromNgModuleMetadata(appModulePath, targetThemeName), + removeProviderFromNgModuleMetadata(appModulePath, targetThemeName), insertImports(appModulePath, targetThemeName), + insertProviders(appModulePath, targetThemeName), ]); }; } @@ -151,6 +153,45 @@ export function removeImportFromNgModuleMetadata( }; } +export function removeProviderFromNgModuleMetadata( + appModulePath: string, + selectedTheme: ThemeOptionsEnum, +): Rule { + return (host: Tree) => { + const recorder = host.beginUpdate(appModulePath); + const source = createSourceFile(host, appModulePath); + const impMap = getImportPaths(selectedTheme, true); + + const node = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0] || {}; + if (!node) { + throw new SchematicsException('The app module does not found'); + } + + const matchingProperties = getMetadataField(node as ts.ObjectLiteralExpression, 'providers'); + const assignment = matchingProperties[0] as ts.PropertyAssignment; + const assignmentInit = assignment.initializer as ts.ArrayLiteralExpression; + + const elements = assignmentInit.elements; + if (!elements || elements.length < 1) { + throw new SchematicsException(`Elements could not found: ${elements}`); + } + + const filteredElements = elements.filter(f => + impMap.filter(f => !!f.provider).some(s => f.getText().match(s.provider!)), + ); + + if (!filteredElements || filteredElements.length < 1) { + return; + } + + filteredElements.map(willRemoveModule => { + recorder.remove(willRemoveModule.getStart(), willRemoveModule.getWidth()); + }); + host.commitUpdate(recorder); + return host; + }; +} + export function insertImports(appModulePath: string, selectedTheme: ThemeOptionsEnum): Rule { return (host: Tree) => { const recorder = host.beginUpdate(appModulePath); @@ -170,7 +211,7 @@ export function insertImports(appModulePath: string, selectedTheme: ThemeOptions if (changes.length > 0) { for (const change of changes) { if (change instanceof InsertChange) { - recorder.insertLeft(change.pos, change.toAdd); + recorder.insertLeft(change.order, change.toAdd); } } } @@ -179,6 +220,35 @@ export function insertImports(appModulePath: string, selectedTheme: ThemeOptions }; } +export function insertProviders(appModulePath: string, selectedTheme: ThemeOptionsEnum): Rule { + return (host: Tree) => { + const recorder = host.beginUpdate(appModulePath); + const source = createSourceFile(host, appModulePath); + const selected = importMap.get(selectedTheme); + + if (!selected) { + return host; + } + + const changes: Change[] = []; + + selected.map(({ path, provider }) => { + if (provider) { + changes.push(...addProviderToModule(source, appModulePath, provider + '()', path)); + } + }); + + for (const change of changes) { + if (change instanceof InsertChange) { + recorder.insertLeft(change.order, change.toAdd); + } + } + + host.commitUpdate(recorder); + return host; + }; +} + export function createSourceFile(host: Tree, appModulePath: string): ts.SourceFile { const buffer = host.read(appModulePath); if (!buffer || buffer.length === 0) { diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts index 4bf4300a2b..7dc9bf8053 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/style-map.ts @@ -11,6 +11,7 @@ export type StyleDefinition = export type ImportDefinition = { path: string; importName: string; + provider?: string; }; export const styleMap = new Map(); @@ -267,14 +268,16 @@ export const importMap = new Map(); importMap.set(ThemeOptionsEnum.Basic, [ { path: '@abp/ng.theme.basic', - importName: 'ThemeBasicModule.forRoot()', + importName: 'ThemeBasicModule', + provider: 'provideThemeBasicConfig', }, ]); importMap.set(ThemeOptionsEnum.Lepton, [ { path: '@volo/abp.ng.theme.lepton', - importName: 'ThemeLeptonModule.forRoot()', + importName: 'ThemeLeptonModule', + provider: 'provideThemeLepton', }, ]); diff --git a/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts b/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts index 55477b41d3..d435b90c85 100644 --- a/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts +++ b/npm/ng-packs/packages/schematics/src/utils/angular/ast-utils.ts @@ -399,7 +399,12 @@ export function addSymbolToNgModuleMetadata( if (importPath !== null) { return [ new InsertChange(ngModulePath, position, toInsert), - insertImport(source, ngModulePath, symbolName.replace(/\..*$/, ''), importPath), + insertImport( + source, + ngModulePath, + symbolName.replace(/\..*$/, '').replace(/\(\)/, ''), + importPath, + ), ]; } else { return [new InsertChange(ngModulePath, position, toInsert)]; @@ -449,7 +454,12 @@ export function addSymbolToNgModuleMetadata( if (importPath !== null) { return [ new InsertChange(ngModulePath, position, toInsert), - insertImport(source, ngModulePath, symbolName.replace(/\..*$/, ''), importPath), + insertImport( + source, + ngModulePath, + symbolName.replace(/\..*$/, '').replace(/\(\)/, ''), + importPath, + ), ]; } diff --git a/npm/ng-packs/packages/setting-management/package.json b/npm/ng-packs/packages/setting-management/package.json index ff46eb5b32..fcf551be40 100644 --- a/npm/ng-packs/packages/setting-management/package.json +++ b/npm/ng-packs/packages/setting-management/package.json @@ -1,14 +1,14 @@ { "name": "@abp/ng.setting-management", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.components": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.components": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/tenant-management/package.json b/npm/ng-packs/packages/tenant-management/package.json index 5cbe47bc43..c40c85a2a2 100644 --- a/npm/ng-packs/packages/tenant-management/package.json +++ b/npm/ng-packs/packages/tenant-management/package.json @@ -1,14 +1,14 @@ { "name": "@abp/ng.tenant-management", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.feature-management": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.feature-management": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/tenant-management/src/lib/guards/extensions.guard.ts b/npm/ng-packs/packages/tenant-management/src/lib/guards/extensions.guard.ts index 0b140f8de8..5d61aa01ae 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/guards/extensions.guard.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/guards/extensions.guard.ts @@ -5,8 +5,8 @@ import { mergeWithDefaultActions, mergeWithDefaultProps, } from '@abp/ng.components/extensible'; -import { ConfigStateService, IAbpGuard, PermissionService } from '@abp/ng.core'; -import { Injectable, inject } from '@angular/core'; +import { IAbpGuard } from '@abp/ng.core'; +import { Injectable, Injector, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; @@ -30,8 +30,7 @@ import { */ @Injectable() export class TenantManagementExtensionsGuard implements IAbpGuard { - protected readonly configState = inject(ConfigStateService); - protected readonly permission = inject(PermissionService); + protected readonly injector = inject(Injector); protected readonly extensions = inject(ExtensionsService); canActivate(): Observable { @@ -45,11 +44,11 @@ export class TenantManagementExtensionsGuard implements IAbpGuard { const editFormContributors = inject(TENANT_MANAGEMENT_EDIT_FORM_PROP_CONTRIBUTORS, config) || {}; - return getObjectExtensionEntitiesFromStore(this.configState, 'TenantManagement').pipe( + return getObjectExtensionEntitiesFromStore(this.injector, 'TenantManagement').pipe( map(entities => ({ [eTenantManagementComponents.Tenants]: entities.Tenant, })), - mapEntitiesToContributors(this.configState, this.permission, 'TenantManagement'), + mapEntitiesToContributors(this.injector, 'TenantManagement'), tap(objectExtensionContributors => { mergeWithDefaultActions( this.extensions.entityActions, diff --git a/npm/ng-packs/packages/tenant-management/src/lib/resolvers/extensions.resolver.ts b/npm/ng-packs/packages/tenant-management/src/lib/resolvers/extensions.resolver.ts index 98e3f34aa6..0f4fc190a3 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/resolvers/extensions.resolver.ts +++ b/npm/ng-packs/packages/tenant-management/src/lib/resolvers/extensions.resolver.ts @@ -5,8 +5,7 @@ import { mergeWithDefaultActions, mergeWithDefaultProps, } from '@abp/ng.components/extensible'; -import { ConfigStateService, PermissionService } from '@abp/ng.core'; -import { inject } from '@angular/core'; +import { inject, Injector } from '@angular/core'; import { ResolveFn } from '@angular/router'; import { map, tap } from 'rxjs'; import { eTenantManagementComponents } from '../enums'; @@ -24,8 +23,7 @@ import { } from '../tokens'; export const tenantManagementExtensionsResolver: ResolveFn = () => { - const configState = inject(ConfigStateService); - const permission = inject(PermissionService); + const injector = inject(Injector); const extensions = inject(ExtensionsService); const config = { optional: true }; @@ -37,11 +35,11 @@ export const tenantManagementExtensionsResolver: ResolveFn = () => { inject(TENANT_MANAGEMENT_CREATE_FORM_PROP_CONTRIBUTORS, config) || {}; const editFormContributors = inject(TENANT_MANAGEMENT_EDIT_FORM_PROP_CONTRIBUTORS, config) || {}; - return getObjectExtensionEntitiesFromStore(configState, 'TenantManagement').pipe( + return getObjectExtensionEntitiesFromStore(injector, 'TenantManagement').pipe( map(entities => ({ [eTenantManagementComponents.Tenants]: entities.Tenant, })), - mapEntitiesToContributors(configState, permission, 'TenantManagement'), + mapEntitiesToContributors(injector, 'TenantManagement'), tap(objectExtensionContributors => { mergeWithDefaultActions( extensions.entityActions, diff --git a/npm/ng-packs/packages/theme-basic/package.json b/npm/ng-packs/packages/theme-basic/package.json index 349b5e5f10..70db94483b 100644 --- a/npm/ng-packs/packages/theme-basic/package.json +++ b/npm/ng-packs/packages/theme-basic/package.json @@ -1,14 +1,14 @@ { "name": "@abp/ng.theme.basic", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.account.core": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.account.core": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/theme-shared/package.json b/npm/ng-packs/packages/theme-shared/package.json index f43248196b..af2e36dc45 100644 --- a/npm/ng-packs/packages/theme-shared/package.json +++ b/npm/ng-packs/packages/theme-shared/package.json @@ -1,13 +1,13 @@ { "name": "@abp/ng.theme.shared", - "version": "9.0.0-rc.1", + "version": "9.0.0", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.core": "~9.0.0-rc.1", + "@abp/ng.core": "~9.0.0", "@fortawesome/fontawesome-free": "^5.15.4", "@ng-bootstrap/ng-bootstrap": "~16.0.0", "@ngx-validate/core": "^0.2.0", diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/abstract-menu.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/abstract-menu.service.ts index 4c3137b332..1af504f0ee 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/services/abstract-menu.service.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/abstract-menu.service.ts @@ -1,12 +1,12 @@ import { BehaviorSubject, Observable } from 'rxjs'; import { NavItem } from '../models/nav-item'; import { inject, Type } from '@angular/core'; -import { SORT_COMPARE_FUNC } from '@abp/ng.core'; +import { SORT_COMPARE_FUNC, SortableItem } from '@abp/ng.core'; export abstract class AbstractMenuService { protected abstract baseClass: Type; - protected readonly sortFn = inject(SORT_COMPARE_FUNC); + protected readonly sortFn: (a: SortableItem, b: SortableItem) => number; protected _items$ = new BehaviorSubject([]); @@ -18,6 +18,10 @@ export abstract class AbstractMenuService { return this._items$.asObservable(); } + constructor() { + this.sortFn = inject(SORT_COMPARE_FUNC); + } + addItems(newItems: T[]) { const items = [...this.items]; newItems.forEach(item => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts b/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts index 9b45be4d1b..7b5496d879 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/services/toaster.service.ts @@ -4,7 +4,7 @@ import { PROJECTION_STRATEGY, Strict, } from '@abp/ng.core'; -import { ComponentRef, Injectable } from '@angular/core'; +import { ComponentRef, inject, Injectable } from '@angular/core'; import { ReplaySubject } from 'rxjs'; import { ToastContainerComponent } from '../components/toast-container/toast-container.component'; import { Toaster } from '../models'; @@ -20,8 +20,7 @@ export class ToasterService implements ToasterContract { private toasts = [] as Toaster.Toast[]; private containerComponentRef!: ComponentRef; - - constructor(private contentProjectionService: ContentProjectionService) {} + private contentProjectionService: ContentProjectionService; private setContainer() { this.containerComponentRef = this.contentProjectionService.projectContent( @@ -34,6 +33,10 @@ export class ToasterService implements ToasterContract { this.containerComponentRef.changeDetectorRef.detectChanges(); } + constructor() { + this.contentProjectionService = inject(ContentProjectionService); + } + /** * Creates an info toast with given parameters. * @param message Content of the toast diff --git a/npm/packs/anchor-js/package.json b/npm/packs/anchor-js/package.json index 87f62574a2..17c46b37e4 100644 --- a/npm/packs/anchor-js/package.json +++ b/npm/packs/anchor-js/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/anchor-js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "anchor-js": "^5.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/aspnetcore.components.server.basictheme/package.json b/npm/packs/aspnetcore.components.server.basictheme/package.json index e0ae4c9789..de6fd1c68c 100644 --- a/npm/packs/aspnetcore.components.server.basictheme/package.json +++ b/npm/packs/aspnetcore.components.server.basictheme/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/aspnetcore.components.server.basictheme", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/aspnetcore.components.server.theming": "~9.0.0-rc.1" + "@abp/aspnetcore.components.server.theming": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/aspnetcore.components.server.theming/package.json b/npm/packs/aspnetcore.components.server.theming/package.json index a52a9dd4c0..79bc143b01 100644 --- a/npm/packs/aspnetcore.components.server.theming/package.json +++ b/npm/packs/aspnetcore.components.server.theming/package.json @@ -1,12 +1,12 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/aspnetcore.components.server.theming", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/bootstrap": "~9.0.0-rc.1", - "@abp/font-awesome": "~9.0.0-rc.1" + "@abp/bootstrap": "~9.0.0", + "@abp/font-awesome": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json b/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json index 78c2e95062..87f07a509a 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/aspnetcore.mvc.ui.theme.basic", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json index b19d2a9c2f..f3d727c426 100644 --- a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json +++ b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/aspnetcore.mvc.ui.theme.shared", "repository": { "type": "git", @@ -10,22 +10,22 @@ "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui": "~9.0.0-rc.1", - "@abp/bootstrap": "~9.0.0-rc.1", - "@abp/bootstrap-datepicker": "~9.0.0-rc.1", - "@abp/bootstrap-daterangepicker": "~9.0.0-rc.1", - "@abp/datatables.net-bs5": "~9.0.0-rc.1", - "@abp/font-awesome": "~9.0.0-rc.1", - "@abp/jquery-form": "~9.0.0-rc.1", - "@abp/jquery-validation-unobtrusive": "~9.0.0-rc.1", - "@abp/lodash": "~9.0.0-rc.1", - "@abp/luxon": "~9.0.0-rc.1", - "@abp/malihu-custom-scrollbar-plugin": "~9.0.0-rc.1", - "@abp/moment": "~9.0.0-rc.1", - "@abp/select2": "~9.0.0-rc.1", - "@abp/sweetalert2": "~9.0.0-rc.1", - "@abp/timeago": "~9.0.0-rc.1", - "@abp/toastr": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui": "~9.0.0", + "@abp/bootstrap": "~9.0.0", + "@abp/bootstrap-datepicker": "~9.0.0", + "@abp/bootstrap-daterangepicker": "~9.0.0", + "@abp/datatables.net-bs5": "~9.0.0", + "@abp/font-awesome": "~9.0.0", + "@abp/jquery-form": "~9.0.0", + "@abp/jquery-validation-unobtrusive": "~9.0.0", + "@abp/lodash": "~9.0.0", + "@abp/luxon": "~9.0.0", + "@abp/malihu-custom-scrollbar-plugin": "~9.0.0", + "@abp/moment": "~9.0.0", + "@abp/select2": "~9.0.0", + "@abp/sweetalert2": "~9.0.0", + "@abp/timeago": "~9.0.0", + "@abp/toastr": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/aspnetcore.mvc.ui/package-lock.json b/npm/packs/aspnetcore.mvc.ui/package-lock.json index e373f690bf..fc6a374e4f 100644 --- a/npm/packs/aspnetcore.mvc.ui/package-lock.json +++ b/npm/packs/aspnetcore.mvc.ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "@abp/aspnetcore.mvc.ui", - "version": "9.0.0-rc.1", + "version": "9.0.0", "lockfileVersion": 1, "requires": true, "packages": { diff --git a/npm/packs/aspnetcore.mvc.ui/package.json b/npm/packs/aspnetcore.mvc.ui/package.json index fb63d591de..c37b1762ea 100644 --- a/npm/packs/aspnetcore.mvc.ui/package.json +++ b/npm/packs/aspnetcore.mvc.ui/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/aspnetcore.mvc.ui", "repository": { "type": "git", diff --git a/npm/packs/blogging/package.json b/npm/packs/blogging/package.json index 224e42120f..c691ce6082 100644 --- a/npm/packs/blogging/package.json +++ b/npm/packs/blogging/package.json @@ -1,14 +1,14 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/blogging", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "~9.0.0-rc.1", - "@abp/owl.carousel": "~9.0.0-rc.1", - "@abp/prismjs": "~9.0.0-rc.1", - "@abp/tui-editor": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared": "~9.0.0", + "@abp/owl.carousel": "~9.0.0", + "@abp/prismjs": "~9.0.0", + "@abp/tui-editor": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/bootstrap-datepicker/package.json b/npm/packs/bootstrap-datepicker/package.json index 36bda039af..0d42e13dce 100644 --- a/npm/packs/bootstrap-datepicker/package.json +++ b/npm/packs/bootstrap-datepicker/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/bootstrap-datepicker", "repository": { "type": "git", diff --git a/npm/packs/bootstrap-daterangepicker/package.json b/npm/packs/bootstrap-daterangepicker/package.json index e0c2cf2785..26400f316d 100644 --- a/npm/packs/bootstrap-daterangepicker/package.json +++ b/npm/packs/bootstrap-daterangepicker/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/bootstrap-daterangepicker", "repository": { "type": "git", diff --git a/npm/packs/bootstrap/package.json b/npm/packs/bootstrap/package.json index a38f749c57..cbd2520d2b 100644 --- a/npm/packs/bootstrap/package.json +++ b/npm/packs/bootstrap/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/bootstrap", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "bootstrap": "^5.3.3" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/chart.js/package.json b/npm/packs/chart.js/package.json index b952391a6a..6fecb8a392 100644 --- a/npm/packs/chart.js/package.json +++ b/npm/packs/chart.js/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/chart.js", "publishConfig": { "access": "public" diff --git a/npm/packs/clipboard/package.json b/npm/packs/clipboard/package.json index 885c91b87b..4d375265a3 100644 --- a/npm/packs/clipboard/package.json +++ b/npm/packs/clipboard/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/clipboard", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "clipboard": "^2.0.11" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/cms-kit.admin/package.json b/npm/packs/cms-kit.admin/package.json index 6857eba7f2..d851350dd0 100644 --- a/npm/packs/cms-kit.admin/package.json +++ b/npm/packs/cms-kit.admin/package.json @@ -1,16 +1,16 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/cms-kit.admin", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/codemirror": "~9.0.0-rc.1", - "@abp/jstree": "~9.0.0-rc.1", - "@abp/markdown-it": "~9.0.0-rc.1", - "@abp/slugify": "~9.0.0-rc.1", - "@abp/tui-editor": "~9.0.0-rc.1", - "@abp/uppy": "~9.0.0-rc.1" + "@abp/codemirror": "~9.0.0", + "@abp/jstree": "~9.0.0", + "@abp/markdown-it": "~9.0.0", + "@abp/slugify": "~9.0.0", + "@abp/tui-editor": "~9.0.0", + "@abp/uppy": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/cms-kit.public/package.json b/npm/packs/cms-kit.public/package.json index 42efa46fb4..7d54b784dc 100644 --- a/npm/packs/cms-kit.public/package.json +++ b/npm/packs/cms-kit.public/package.json @@ -1,12 +1,12 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/cms-kit.public", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/highlight.js": "~9.0.0-rc.1", - "@abp/star-rating-svg": "~9.0.0-rc.1" + "@abp/highlight.js": "~9.0.0", + "@abp/star-rating-svg": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/cms-kit/package.json b/npm/packs/cms-kit/package.json index 109969042c..1f02ba49d0 100644 --- a/npm/packs/cms-kit/package.json +++ b/npm/packs/cms-kit/package.json @@ -1,12 +1,12 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/cms-kit", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/cms-kit.admin": "~9.0.0-rc.1", - "@abp/cms-kit.public": "~9.0.0-rc.1" + "@abp/cms-kit.admin": "~9.0.0", + "@abp/cms-kit.public": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/codemirror/package.json b/npm/packs/codemirror/package.json index 1a66292008..2577d0e374 100644 --- a/npm/packs/codemirror/package.json +++ b/npm/packs/codemirror/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/codemirror", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "codemirror": "^5.65.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/core/package.json b/npm/packs/core/package.json index 48113d39d7..ac9bb8d4be 100644 --- a/npm/packs/core/package.json +++ b/npm/packs/core/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/core", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/utils": "~9.0.0-rc.1" + "@abp/utils": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/cropperjs/package.json b/npm/packs/cropperjs/package.json index 1d74a56f16..cd501fa378 100644 --- a/npm/packs/cropperjs/package.json +++ b/npm/packs/cropperjs/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/cropperjs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "cropperjs": "^1.6.2" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/datatables.net-bs4/package.json b/npm/packs/datatables.net-bs4/package.json index 22039fb59b..fe6719d8d9 100644 --- a/npm/packs/datatables.net-bs4/package.json +++ b/npm/packs/datatables.net-bs4/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/datatables.net-bs4", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/datatables.net": "~9.0.0-rc.1", + "@abp/datatables.net": "~9.0.0", "datatables.net-bs4": "^2.1.8" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/datatables.net-bs5/package.json b/npm/packs/datatables.net-bs5/package.json index b013817337..8f401bbb2c 100644 --- a/npm/packs/datatables.net-bs5/package.json +++ b/npm/packs/datatables.net-bs5/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/datatables.net-bs5", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/datatables.net": "~9.0.0-rc.1", + "@abp/datatables.net": "~9.0.0", "datatables.net-bs5": "^2.1.8" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/datatables.net/package.json b/npm/packs/datatables.net/package.json index fa9936771f..ac51ee774e 100644 --- a/npm/packs/datatables.net/package.json +++ b/npm/packs/datatables.net/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/datatables.net", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", + "@abp/jquery": "~9.0.0", "datatables.net": "^2.1.8" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/docs/package.json b/npm/packs/docs/package.json index 791d7d895f..a394a04dea 100644 --- a/npm/packs/docs/package.json +++ b/npm/packs/docs/package.json @@ -1,15 +1,15 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/docs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/anchor-js": "~9.0.0-rc.1", - "@abp/clipboard": "~9.0.0-rc.1", - "@abp/malihu-custom-scrollbar-plugin": "~9.0.0-rc.1", - "@abp/popper.js": "~9.0.0-rc.1", - "@abp/prismjs": "~9.0.0-rc.1" + "@abp/anchor-js": "~9.0.0", + "@abp/clipboard": "~9.0.0", + "@abp/malihu-custom-scrollbar-plugin": "~9.0.0", + "@abp/popper.js": "~9.0.0", + "@abp/prismjs": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/flag-icon-css/package.json b/npm/packs/flag-icon-css/package.json index 3ea7cc7b72..d452d190f1 100644 --- a/npm/packs/flag-icon-css/package.json +++ b/npm/packs/flag-icon-css/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/flag-icon-css", "publishConfig": { "access": "public" diff --git a/npm/packs/flag-icons/package.json b/npm/packs/flag-icons/package.json index 3c6bb69c92..226df434e8 100644 --- a/npm/packs/flag-icons/package.json +++ b/npm/packs/flag-icons/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/flag-icons", "publishConfig": { "access": "public" diff --git a/npm/packs/font-awesome/package.json b/npm/packs/font-awesome/package.json index 9e1eceffd9..61a5679668 100644 --- a/npm/packs/font-awesome/package.json +++ b/npm/packs/font-awesome/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/font-awesome", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "@fortawesome/fontawesome-free": "^6.6.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/highlight.js/package.json b/npm/packs/highlight.js/package.json index c29f24afed..f2a4f8bd33 100644 --- a/npm/packs/highlight.js/package.json +++ b/npm/packs/highlight.js/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/highlight.js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "@highlightjs/cdn-assets": "~11.10.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/jquery-form/package.json b/npm/packs/jquery-form/package.json index 116aeb0ff3..df7ec86ea9 100644 --- a/npm/packs/jquery-form/package.json +++ b/npm/packs/jquery-form/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/jquery-form", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", + "@abp/jquery": "~9.0.0", "jquery-form": "^4.3.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/jquery-validation-unobtrusive/package.json b/npm/packs/jquery-validation-unobtrusive/package.json index 2be6728d9c..3421260678 100644 --- a/npm/packs/jquery-validation-unobtrusive/package.json +++ b/npm/packs/jquery-validation-unobtrusive/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/jquery-validation-unobtrusive", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery-validation": "~9.0.0-rc.1", + "@abp/jquery-validation": "~9.0.0", "jquery-validation-unobtrusive": "^4.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/jquery-validation/package.json b/npm/packs/jquery-validation/package.json index 83fc1b16d0..5ba24ebcf9 100644 --- a/npm/packs/jquery-validation/package.json +++ b/npm/packs/jquery-validation/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/jquery-validation", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", + "@abp/jquery": "~9.0.0", "jquery-validation": "^1.21.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/jquery/package.json b/npm/packs/jquery/package.json index 5e4ec9ede3..b48af1af76 100644 --- a/npm/packs/jquery/package.json +++ b/npm/packs/jquery/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/jquery", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "jquery": "~3.7.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/jstree/package.json b/npm/packs/jstree/package.json index 7582c88c6b..030d09c70f 100644 --- a/npm/packs/jstree/package.json +++ b/npm/packs/jstree/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/jstree", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", + "@abp/jquery": "~9.0.0", "jstree": "^3.3.17" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/lodash/package.json b/npm/packs/lodash/package.json index 8648172c3f..7946b80bd8 100644 --- a/npm/packs/lodash/package.json +++ b/npm/packs/lodash/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/lodash", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "lodash": "^4.17.21" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/luxon/package.json b/npm/packs/luxon/package.json index d7da6cd910..5c47894cb1 100644 --- a/npm/packs/luxon/package.json +++ b/npm/packs/luxon/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/luxon", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "luxon": "^3.5.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/malihu-custom-scrollbar-plugin/package.json b/npm/packs/malihu-custom-scrollbar-plugin/package.json index 8a6c361ac2..5a61f2bb9e 100644 --- a/npm/packs/malihu-custom-scrollbar-plugin/package.json +++ b/npm/packs/malihu-custom-scrollbar-plugin/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/malihu-custom-scrollbar-plugin", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "malihu-custom-scrollbar-plugin": "^3.1.5" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/markdown-it/package.json b/npm/packs/markdown-it/package.json index baa1a107c8..6587836f8c 100644 --- a/npm/packs/markdown-it/package.json +++ b/npm/packs/markdown-it/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/markdown-it", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "markdown-it": "^14.1.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/moment/package.json b/npm/packs/moment/package.json index 7737bc1c2f..dff5f73832 100644 --- a/npm/packs/moment/package.json +++ b/npm/packs/moment/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/moment", "repository": { "type": "git", diff --git a/npm/packs/owl.carousel/package.json b/npm/packs/owl.carousel/package.json index 4841627527..16226df141 100644 --- a/npm/packs/owl.carousel/package.json +++ b/npm/packs/owl.carousel/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/owl.carousel", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "owl.carousel": "^2.3.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/popper.js/package.json b/npm/packs/popper.js/package.json index 8b5aa4b46e..ce2b69da9d 100644 --- a/npm/packs/popper.js/package.json +++ b/npm/packs/popper.js/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/popper.js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "@popperjs/core": "^2.11.8" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/prismjs/package.json b/npm/packs/prismjs/package.json index b99f164849..dbfd25d880 100644 --- a/npm/packs/prismjs/package.json +++ b/npm/packs/prismjs/package.json @@ -1,12 +1,12 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/prismjs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/clipboard": "~9.0.0-rc.1", - "@abp/core": "~9.0.0-rc.1", + "@abp/clipboard": "~9.0.0", + "@abp/core": "~9.0.0", "prismjs": "^1.29.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/qrcode/package.json b/npm/packs/qrcode/package.json index c16c190023..e323e7ee19 100644 --- a/npm/packs/qrcode/package.json +++ b/npm/packs/qrcode/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/qrcode", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1" + "@abp/core": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/select2/package.json b/npm/packs/select2/package.json index dac11ff6b4..cfb3a2218c 100644 --- a/npm/packs/select2/package.json +++ b/npm/packs/select2/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/select2", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "select2": "^4.0.13" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/signalr/package.json b/npm/packs/signalr/package.json index 68ee3da565..1b85ffd415 100644 --- a/npm/packs/signalr/package.json +++ b/npm/packs/signalr/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/signalr", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "@microsoft/signalr": "~8.0.7" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/slugify/package.json b/npm/packs/slugify/package.json index ae92543db4..3cee1c61b4 100644 --- a/npm/packs/slugify/package.json +++ b/npm/packs/slugify/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/slugify", "publishConfig": { "access": "public" diff --git a/npm/packs/star-rating-svg/package.json b/npm/packs/star-rating-svg/package.json index 2adb918b8c..5b4249f53b 100644 --- a/npm/packs/star-rating-svg/package.json +++ b/npm/packs/star-rating-svg/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/star-rating-svg", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", + "@abp/jquery": "~9.0.0", "star-rating-svg": "^3.5.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/sweetalert2/package.json b/npm/packs/sweetalert2/package.json index 2253a00bdc..2a4fdeef6d 100644 --- a/npm/packs/sweetalert2/package.json +++ b/npm/packs/sweetalert2/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/sweetalert2", "publishConfig": { "access": "public" @@ -10,7 +10,7 @@ "directory": "npm/packs/sweetalert2" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "sweetalert2": "^11.14.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/timeago/package.json b/npm/packs/timeago/package.json index f91fdc6449..e5fcde7ae9 100644 --- a/npm/packs/timeago/package.json +++ b/npm/packs/timeago/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/timeago", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", + "@abp/jquery": "~9.0.0", "timeago": "^1.6.7" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/toastr/package.json b/npm/packs/toastr/package.json index 32f12cc386..50fabf6edf 100644 --- a/npm/packs/toastr/package.json +++ b/npm/packs/toastr/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/toastr", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", + "@abp/jquery": "~9.0.0", "toastr": "^2.1.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/tui-editor/package.json b/npm/packs/tui-editor/package.json index ca10d218d2..95cb135223 100644 --- a/npm/packs/tui-editor/package.json +++ b/npm/packs/tui-editor/package.json @@ -1,12 +1,12 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/tui-editor", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "~9.0.0-rc.1", - "@abp/prismjs": "~9.0.0-rc.1" + "@abp/jquery": "~9.0.0", + "@abp/prismjs": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/uppy/package.json b/npm/packs/uppy/package.json index eaa5a5c3aa..3448e17b1a 100644 --- a/npm/packs/uppy/package.json +++ b/npm/packs/uppy/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/uppy", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "uppy": "^4.4.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/utils/package.json b/npm/packs/utils/package.json index 6e4541151e..b677cfeae1 100644 --- a/npm/packs/utils/package.json +++ b/npm/packs/utils/package.json @@ -1,6 +1,6 @@ { "name": "@abp/utils", - "version": "9.0.0-rc.1", + "version": "9.0.0", "scripts": { "prepublishOnly": "yarn install --ignore-scripts && node prepublish.js", "ng": "ng", diff --git a/npm/packs/vee-validate/package.json b/npm/packs/vee-validate/package.json index 87ca8a3511..d1bf13bcbb 100644 --- a/npm/packs/vee-validate/package.json +++ b/npm/packs/vee-validate/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/vee-validate", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/vue": "~9.0.0-rc.1", + "@abp/vue": "~9.0.0", "vee-validate": "~3.4.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/virtual-file-explorer/package.json b/npm/packs/virtual-file-explorer/package.json index 84bb8b3839..534fce1701 100644 --- a/npm/packs/virtual-file-explorer/package.json +++ b/npm/packs/virtual-file-explorer/package.json @@ -1,12 +1,12 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/virtual-file-explorer", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/clipboard": "~9.0.0-rc.1", - "@abp/prismjs": "~9.0.0-rc.1" + "@abp/clipboard": "~9.0.0", + "@abp/prismjs": "~9.0.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/vue/package.json b/npm/packs/vue/package.json index de4e19bb93..c43d4b2e23 100644 --- a/npm/packs/vue/package.json +++ b/npm/packs/vue/package.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/vue", "publishConfig": { "access": "public" diff --git a/npm/packs/zxcvbn/package.json b/npm/packs/zxcvbn/package.json index e03b960319..eecc6af51e 100644 --- a/npm/packs/zxcvbn/package.json +++ b/npm/packs/zxcvbn/package.json @@ -1,11 +1,11 @@ { - "version": "9.0.0-rc.1", + "version": "9.0.0", "name": "@abp/zxcvbn", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.0.0-rc.1", + "@abp/core": "~9.0.0", "zxcvbn": "^4.4.2" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip b/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip index fd976ffd28..7f5f7706e4 100644 Binary files a/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip and b/source-code/Volo.Abp.Account.SourceCode/Volo.Abp.Account.SourceCode.zip differ diff --git a/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip b/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip index 3544a4563b..51a2b2c2af 100644 Binary files a/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip and b/source-code/Volo.Abp.AuditLogging.SourceCode/Volo.Abp.AuditLogging.SourceCode.zip differ diff --git a/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip b/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip index 286ff20442..2bce0b40bf 100644 Binary files a/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip and b/source-code/Volo.Abp.BackgroundJobs.SourceCode/Volo.Abp.BackgroundJobs.SourceCode.zip differ diff --git a/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip b/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip index 7de45b66c4..a053c74d56 100644 Binary files a/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip and b/source-code/Volo.Abp.BasicTheme.SourceCode/Volo.Abp.BasicTheme.SourceCode.zip differ diff --git a/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip b/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip index 64f5840eea..5bf0990216 100644 Binary files a/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip and b/source-code/Volo.Abp.BlobStoring.Database.SourceCode/Volo.Abp.BlobStoring.Database.SourceCode.zip differ diff --git a/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip b/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip index fe2a051ecb..59c9f3a72f 100644 Binary files a/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip and b/source-code/Volo.Abp.FeatureManagement.SourceCode/Volo.Abp.FeatureManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip b/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip index 647fa1ad2e..f25d630510 100644 Binary files a/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip and b/source-code/Volo.Abp.Identity.SourceCode/Volo.Abp.Identity.SourceCode.zip differ diff --git a/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip b/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip index df001356f9..6eb9a02099 100644 Binary files a/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip and b/source-code/Volo.Abp.IdentityServer.SourceCode/Volo.Abp.IdentityServer.SourceCode.zip differ diff --git a/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip b/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip index 8c26bc2069..834bea98b0 100644 Binary files a/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip and b/source-code/Volo.Abp.OpenIddict.SourceCode/Volo.Abp.OpenIddict.SourceCode.zip differ diff --git a/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip b/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip index ef226e0b8a..84706bf906 100644 Binary files a/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip and b/source-code/Volo.Abp.PermissionManagement.SourceCode/Volo.Abp.PermissionManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip b/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip index 1f941ee1f1..b92e04343b 100644 Binary files a/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip and b/source-code/Volo.Abp.SettingManagement.SourceCode/Volo.Abp.SettingManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip b/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip index a829e68106..b160e3233d 100644 Binary files a/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip and b/source-code/Volo.Abp.TenantManagement.SourceCode/Volo.Abp.TenantManagement.SourceCode.zip differ diff --git a/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip b/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip index 1bc0ab573d..71c4edbef9 100644 Binary files a/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip and b/source-code/Volo.Abp.Users.SourceCode/Volo.Abp.Users.SourceCode.zip differ diff --git a/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip b/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip index 9ce1030a91..e171ac938d 100644 Binary files a/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip and b/source-code/Volo.Abp.VirtualFileExplorer.SourceCode/Volo.Abp.VirtualFileExplorer.SourceCode.zip differ diff --git a/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip b/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip index 99298aa4ed..fd461b2368 100644 Binary files a/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip and b/source-code/Volo.Blogging.SourceCode/Volo.Blogging.SourceCode.zip differ diff --git a/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip b/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip index b50dd1b26a..14778e7cdc 100644 Binary files a/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip and b/source-code/Volo.ClientSimulation.SourceCode/Volo.ClientSimulation.SourceCode.zip differ diff --git a/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip b/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip index cc6711dea8..a2da5f97ed 100644 Binary files a/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip and b/source-code/Volo.CmsKit.SourceCode/Volo.CmsKit.SourceCode.zip differ diff --git a/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip b/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip index 808d096a21..9a99d49ee5 100644 Binary files a/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip and b/source-code/Volo.Docs.SourceCode/Volo.Docs.SourceCode.zip differ diff --git a/templates/app-nolayers/angular/package.json b/templates/app-nolayers/angular/package.json index d4b6aaeeb0..cbe3db28a1 100644 --- a/templates/app-nolayers/angular/package.json +++ b/templates/app-nolayers/angular/package.json @@ -12,15 +12,15 @@ }, "private": true, "dependencies": { - "@abp/ng.account": "~9.0.0-rc.1", - "@abp/ng.components": "~9.0.0-rc.1", - "@abp/ng.core": "~9.0.0-rc.1", - "@abp/ng.identity": "~9.0.0-rc.1", - "@abp/ng.oauth": "~9.0.0-rc.1", - "@abp/ng.setting-management": "~9.0.0-rc.1", - "@abp/ng.tenant-management": "~9.0.0-rc.1", - "@abp/ng.theme.lepton-x": "~4.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.account": "~9.0.0", + "@abp/ng.components": "~9.0.0", + "@abp/ng.core": "~9.0.0", + "@abp/ng.identity": "~9.0.0", + "@abp/ng.oauth": "~9.0.0", + "@abp/ng.setting-management": "~9.0.0", + "@abp/ng.tenant-management": "~9.0.0", + "@abp/ng.theme.lepton-x": "~4.0.0", + "@abp/ng.theme.shared": "~9.0.0", "@angular/animations": "~18.1.0", "@angular/common": "~18.1.0", "@angular/compiler": "~18.1.0", @@ -36,7 +36,7 @@ "zone.js": "~0.14.0" }, "devDependencies": { - "@abp/ng.schematics": "~9.0.0-rc.1", + "@abp/ng.schematics": "~9.0.0", "@angular-devkit/build-angular": "~18.1.0", "@angular-eslint/builder": "~18.1.0", "@angular-eslint/eslint-plugin": "~18.1.0", diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj index 13783128bb..d06be197e5 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj @@ -8,8 +8,8 @@ - - + + @@ -82,7 +82,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/package.json index c4103c3ac6..97f66ff625 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0-rc.1", - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0", + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj index f5312b02e3..76b7b565d2 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj @@ -8,8 +8,8 @@ - - + + @@ -83,11 +83,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/package.json index d253a0c68b..ad9e67c4e4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0" } } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj index 39693e2e07..df0c02e3db 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Client/MyCompanyName.MyProjectName.Blazor.WebAssembly.Client.csproj @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj index 883e0a90be..b8bcbff275 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.Mongo.csproj @@ -8,7 +8,7 @@ - + @@ -78,7 +78,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj index 52de29eb90..dc71a76a65 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyCompanyName.MyProjectName.Blazor.WebAssembly.Server.csproj @@ -8,7 +8,7 @@ - + @@ -79,11 +79,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj index 2318234a65..3e42efdfac 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Shared/MyCompanyName.MyProjectName.Blazor.WebAssembly.Shared.csproj @@ -29,7 +29,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj index 6148538dcd..c460a81865 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj @@ -74,7 +74,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj index dc6cb1f92e..5f329d6920 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj @@ -75,11 +75,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj index a242bf36d4..f09966edc7 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj @@ -77,7 +77,7 @@ - + diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj index c8bd48c7d7..61c386a63a 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj @@ -78,11 +78,11 @@ - + - + runtime; build; native; contentfiles; analyzers compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/package.json b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/package.json +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app/angular/package.json b/templates/app/angular/package.json index d4b6aaeeb0..cbe3db28a1 100644 --- a/templates/app/angular/package.json +++ b/templates/app/angular/package.json @@ -12,15 +12,15 @@ }, "private": true, "dependencies": { - "@abp/ng.account": "~9.0.0-rc.1", - "@abp/ng.components": "~9.0.0-rc.1", - "@abp/ng.core": "~9.0.0-rc.1", - "@abp/ng.identity": "~9.0.0-rc.1", - "@abp/ng.oauth": "~9.0.0-rc.1", - "@abp/ng.setting-management": "~9.0.0-rc.1", - "@abp/ng.tenant-management": "~9.0.0-rc.1", - "@abp/ng.theme.lepton-x": "~4.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.account": "~9.0.0", + "@abp/ng.components": "~9.0.0", + "@abp/ng.core": "~9.0.0", + "@abp/ng.identity": "~9.0.0", + "@abp/ng.oauth": "~9.0.0", + "@abp/ng.setting-management": "~9.0.0", + "@abp/ng.tenant-management": "~9.0.0", + "@abp/ng.theme.lepton-x": "~4.0.0", + "@abp/ng.theme.shared": "~9.0.0", "@angular/animations": "~18.1.0", "@angular/common": "~18.1.0", "@angular/compiler": "~18.1.0", @@ -36,7 +36,7 @@ "zone.js": "~0.14.0" }, "devDependencies": { - "@abp/ng.schematics": "~9.0.0-rc.1", + "@abp/ng.schematics": "~9.0.0", "@angular-devkit/build-angular": "~18.1.0", "@angular-eslint/builder": "~18.1.0", "@angular-eslint/eslint-plugin": "~18.1.0", diff --git a/templates/app/angular/src/app/home/home.component.html b/templates/app/angular/src/app/home/home.component.html index c80dd1724e..e3e73e48ae 100644 --- a/templates/app/angular/src/app/home/home.component.html +++ b/templates/app/angular/src/app/home/home.component.html @@ -21,7 +21,7 @@ $implicit: { description: 'Learn how to create and run a new web application using the application startup template.', - href: 'https://docs.abp.io/en/commercial/latest/getting-started', + href: 'https://abp.io/docs/latest/get-started', label: 'Getting Started' } } @@ -36,7 +36,7 @@ $implicit: { description: 'Learn how to build an ABP based web application named Acme.BookStore.', - href: 'https://docs.abp.io/en/commercial/latest/tutorials/book-store/part-1?UI=MVC&DB=EF', + href: 'https://abp.io/docs/latest/tutorials/book-store/part-01?UI=NG&DB=EF', label: 'Explore Tutorial' } } @@ -46,7 +46,7 @@

    Customize Lepton Theme

    Learn how to customize LeptonX Theme as you wish.

    Customize Lepton - Join ABP Community
    @@ -145,7 +145,7 @@ icon: 'bi bi-check fs-4', iconClass: 'rounded-circle me-2 flex-center bg-brand soft', title: 'Samples', - link: 'https://docs.abp.io/en/abp/latest/Samples/Index', + link: 'https://abp.io/docs/latest/Samples/Index', }, { iconType: 'icon', @@ -161,7 +161,7 @@ icon: 'bi bi-check fs-4', iconClass: 'rounded-circle me-2 flex-center bg-brand soft', title: 'FAQ', - link: 'https://commercial.abp.io/faq', + link: 'https://abp.io/faq', }, ] } @@ -219,7 +219,7 @@ iconType: 'image', icon: 'assets/images/getting-started/discord.svg', title: 'Discord', - link: 'https://community.abp.io/discord' + link: 'https://abp.io/community/discord' }, { iconType: 'image', diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj index b733c7a137..13944f80a4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj @@ -41,7 +41,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/package.json index 7a7d51d053..7ec238e365 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/package.json @@ -3,6 +3,6 @@ "name": "my-app-authserver", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj index 184599ff58..f2b0571694 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Client/MyCompanyName.MyProjectName.Blazor.Client.csproj @@ -12,10 +12,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj index 5fa6855e6d..94bd78031e 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj @@ -14,11 +14,11 @@ - - + + - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/package.json index d253a0c68b..ad9e67c4e4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj index f588b1ab1b..4fbeda375d 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj @@ -14,9 +14,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/package.json index d253a0c68b..ad9e67c4e4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj index 8a1c5283c1..1d4c799c7d 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Client.csproj @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj index c47f0bf591..7060d8b09e 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.csproj @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj index 535cfbdf46..c4bfb0d359 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.csproj @@ -15,12 +15,12 @@ - - - + + + - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/package.json index d253a0c68b..ad9e67c4e4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj index 03f2ce0003..822e05a54b 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/package.json index d253a0c68b..ad9e67c4e4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.0.0" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj index da9a63fc75..69553778ac 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj index c647364ca3..bd94f629e5 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj @@ -22,7 +22,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj index 01270570ed..0d3400a8c9 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj @@ -26,7 +26,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj index 4f18b483aa..36df4c7aec 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/MyCompanyName.MyProjectName.EntityFrameworkCore.csproj @@ -22,7 +22,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 53dfd24853..0fca8d971f 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 51a93f92b4..b42a3adb56 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -19,7 +19,7 @@ - + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/package.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/package.json index e8611a83eb..d775e0cfb4 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/package.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.0.0" } } diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj index a57edeeebe..0cf25af2a2 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj @@ -22,8 +22,8 @@ - - + + diff --git a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index 098078a1aa..9b8ffed514 100644 --- a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index fb0dc00cb5..b46b603ef3 100644 --- a/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -35,7 +35,7 @@ - + diff --git a/templates/module/angular/package.json b/templates/module/angular/package.json index 6009a62572..98beecd5ad 100644 --- a/templates/module/angular/package.json +++ b/templates/module/angular/package.json @@ -13,15 +13,15 @@ }, "private": true, "dependencies": { - "@abp/ng.account": "~9.0.0-rc.1", - "@abp/ng.components": "~9.0.0-rc.1", - "@abp/ng.core": "~9.0.0-rc.1", - "@abp/ng.identity": "~9.0.0-rc.1", - "@abp/ng.oauth": "~9.0.0-rc.1", - "@abp/ng.setting-management": "~9.0.0-rc.1", - "@abp/ng.tenant-management": "~9.0.0-rc.1", - "@abp/ng.theme.basic": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1", + "@abp/ng.account": "~9.0.0", + "@abp/ng.components": "~9.0.0", + "@abp/ng.core": "~9.0.0", + "@abp/ng.identity": "~9.0.0", + "@abp/ng.oauth": "~9.0.0", + "@abp/ng.setting-management": "~9.0.0", + "@abp/ng.tenant-management": "~9.0.0", + "@abp/ng.theme.basic": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0", "@angular/animations": "~18.1.0", "@angular/common": "~18.1.0", "@angular/compiler": "~18.1.0", @@ -36,7 +36,7 @@ "zone.js": "~0.14.0" }, "devDependencies": { - "@abp/ng.schematics": "~9.0.0-rc.1", + "@abp/ng.schematics": "~9.0.0", "@angular-devkit/build-angular": "~18.1.0", "@angular-eslint/builder": "~18.1.0", "@angular-eslint/eslint-plugin": "~18.1.0", diff --git a/templates/module/angular/projects/my-project-name/package.json b/templates/module/angular/projects/my-project-name/package.json index fe9a139eec..bd1357bf6a 100644 --- a/templates/module/angular/projects/my-project-name/package.json +++ b/templates/module/angular/projects/my-project-name/package.json @@ -4,8 +4,8 @@ "peerDependencies": { "@angular/common": "~18.1.0", "@angular/core": "~18.1.0", - "@abp/ng.core": "~9.0.0-rc.1", - "@abp/ng.theme.shared": "~9.0.0-rc.1" + "@abp/ng.core": "~9.0.0", + "@abp/ng.theme.shared": "~9.0.0" }, "dependencies": { "tslib": "^2.1.0" diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj index 216ceabcfc..7a5bb53c43 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj @@ -13,8 +13,8 @@ - - + + all runtime; build; native; contentfiles; analyzers diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/package.json b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/package.json index f3b4dcaeca..f9dcad0338 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/package.json +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/package.json @@ -3,6 +3,6 @@ "name": "my-app-authserver", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj index 7d0293f4e4..8b37d3a75f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host.Client/MyCompanyName.MyProjectName.Blazor.Host.Client.csproj @@ -10,10 +10,10 @@ - - - - + + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj index a6c80f859f..107716d86b 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj @@ -8,7 +8,7 @@ - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj index 1a8f494d1f..4af0b61407 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj @@ -13,11 +13,11 @@ - - + + - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/package.json b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/package.json index 82898815cc..0c034306bf 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/package.json +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1", - "@abp/aspnetcore.components.server.basictheme": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0", + "@abp/aspnetcore.components.server.basictheme": "~9.0.0" } } diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 86af04110e..a4b9ad63a1 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -14,9 +14,9 @@ - - - + + + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj index 84a009aaf2..96163e2d58 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyCompanyName.MyProjectName.Web.Host.csproj @@ -13,7 +13,7 @@ - + diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/package.json b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/package.json index 57114aba35..8b5210b25f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/package.json +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj index 0fbb65a2a8..b94e77f3d9 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyCompanyName.MyProjectName.Web.Unified.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/package.json b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/package.json index 57114aba35..8b5210b25f 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/package.json +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/package.json @@ -3,6 +3,6 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.0.0" } } diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj index 23af865b55..bc4acfc86d 100644 --- a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj +++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/MyCompanyName.MyProjectName.Domain.Shared.csproj @@ -15,7 +15,7 @@ - + diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index 268d8a7af9..5bcf00b1b1 100644 --- a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -22,7 +22,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj index 2fb6a5234f..b8adaa1a7e 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj index c3e150d6b9..077ac1ced3 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp/MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp.csproj @@ -23,7 +23,7 @@ - + diff --git a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index 5a0717a760..64e7affb94 100644 --- a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -14,7 +14,7 @@ - +