diff --git a/.github/workflows/angular.yml b/.github/workflows/angular.yml index ee66fbcf2c..cd48c0448a 100644 --- a/.github/workflows/angular.yml +++ b/.github/workflows/angular.yml @@ -27,12 +27,12 @@ jobs: with: fetch-depth: 0 - - uses: actions/cache@v2 + - uses: actions/cache@v4 with: path: 'npm/ng-packs/node_modules' key: ${{ runner.os }}-${{ hashFiles('npm/ng-packs/yarn.lock') }} - - uses: actions/cache@v2 + - uses: actions/cache@v4 with: path: 'templates/app/angular/node_modules' key: ${{ runner.os }}-${{ hashFiles('templates/app/angular/yarn.lock') }} diff --git a/Directory.Packages.props b/Directory.Packages.props index 193cccefae..7263869bdf 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,187 +3,186 @@ true - + - - + + - + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - + + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + - - - + + + - - - - + + + + - + - + - - - - - - + + + + + + - - - - + + + + - + - + \ No newline at end of file diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 1ea52ff5f5..d056e70b09 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -690,6 +690,33 @@ "Permission:Campaigns": "Campaigns", "Permission:Licenses": "License Settings", "BlockUserPolicy": "User Block Policies", - "Permission:BlockUserPolicy": "User Block Policy" + "Permission:BlockUserPolicy": "User Block Policy", + "ManageImages" : "Manage Image", + "ModuleMainImage": "Module Main Image", + "ModuleImageInfo1": "Accepted file types : JPEG, JPG, PNG, SVG ", + "ModuleImageInfo2": "Max file size : 1 MB ", + "ModuleImageInfo3": "Image Proportion : 1:1 ", + "ModuleImageInfo4": " Download a sample cover image ", + "AreYouSureToDeleteImage": "Are you sure you want to delete this image?", + "CompactPercentage": "Compact Percentage", + "CompactPercentageDescription": "Percentage of cache entries to remove during compaction (1-100)", + "Settings": "Settings", + "MaxSizeOfInMemoryCache": "Max Size Of In Memory Cache", + "MaxSizeOfInMemoryCacheInfo": "Gets or sets the maximum size of the memory cache.", + "SizeOfTriggerAutoCompact": "Size Of Trigger Auto Compact", + "SizeOfTriggerAutoCompactInfo": "Gets or sets the size threshold that triggers auto-compaction. When the cache size exceeds this value, auto-compaction will be performed", + "AutoCompactPercentage": "Auto Compact Percentage", + "AutoCompactPercentageInfo": "Gets or sets the percentage of items to remove when auto-compaction is triggered (1-100)", + "ClearCaches": "This clears all NuGet content cache", + "CacheLatestVersions": "Cache Latest Versions", + "VersionCount": "Version Count", + "VersionCountInfo": "Gets or sets the number of versions to cache", + "IncludeLeptonX": "Include LeptonX", + "IncludeLeptonXInfo": "Gets or sets whether to include LeptonX in the cache", + "IncludePrerelease": "Include Prerelease", + "IncludePrereleaseInfo": "Gets or sets whether to include prerelease versions in the cache", + "CacheVersionCount": "Cache Version Count", + "CacheVersionCountInfo": "Gets or sets the number of versions to cache", + "CacheLatestVersionsInfo": "This caches the latest versions of the NuGet packages" } } diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index b81733d247..456e8ebd05 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -987,7 +987,7 @@ "Summary": "Summary", "TrainingPack": "Training pack", "TrainingPackDiscount": "Training pack discount", - "Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. Learn more ", + "Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. Learn more ", "Purchase_Save": "{0}% Save {1}", "RemoveBasket": "Remove from basket", "WhyABPIOPlatform?": "Why ABP.IO Platform?", diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index adfe16e6c5..7ea0fb6708 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -66,7 +66,7 @@ "AuditLogging": "Audit Logging", "Caching": "Caching", "Multitenancy": "Multitenancy", - "DataFiltering": "Data filtering", + "DataFiltering": "Data Filtering", "ConventionOverConfiguration": "Convention Over Configuration", "ConventionOverConfigurationExplanation": "ABP implements common application conventions by default with minimal or zero configuration.", "ConventionOverConfigurationExplanationList1": "Auto registers known services to dependency injection.", @@ -1887,6 +1887,9 @@ "FaqIyzicoPaymentIssuesExplanation6": "Digital Wallets: PayPal, AliPay, WebMoney", "FaqIyzicoPaymentIssuesExplanation7": "Alternatively, you can send the license amount directly via bank wire transfer. For our bank account details, please visit: Bank Account Information (use USD currency).", "FaqIyzicoPaymentIssuesExplanation8": "ABP website doesn't save or process your credit card. We use payment gateways for this and the entire transaction is handled by payment gateways. We have no authority to interfere with the payment process or fix the payment steps. If you have further questions or need additional support, feel free to contact us at abp.io/contact.", - "BiographyContainsUrlValidationMessage": "Biography cannot contain URL." + "BiographyContainsUrlValidationMessage": "Biography cannot contain URL.", + "CreatePostSEOTitleInfo": "SEO URL is a clean, readable, keyword-rich URL that helps both users and search engines understand what this post is about. Keep it short with 60 characters. SEO titles over 60 characters will be truncated. Use hyphens (-) to separate words (not underscores). Include target keywords near the start. Lowercase only. No stop words unless needed (e.g: \"and\", \"or\", \"the\").", + "SEOTitle": "SEO URL", + "InvalidYouTubeUrl": "The URL you entered is not a valid YouTube video link. Please make sure it points to a specific video and try again." } } diff --git a/docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md b/docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md index b78e3235a2..b0b44b9e45 100644 --- a/docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md +++ b/docs/en/Blog-Posts/2022-03-08 v5_2_Preview/POST.md @@ -187,7 +187,7 @@ We organized the 3rd live [ABP Community Talks](https://community.abp.io/events) * [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) has also created [an article](https://community.abp.io/posts/using-autofilterer-with-abp-framework-uuqv81jm) to demonstrate how to use his own open source [AutoFilterer](https://github.com/enisn/AutoFilterer) library with the ABP Framework. * [Jonathan Potts](https://github.com/jonathanpotts) has created his first ABP Community article that shows how to use Bootswatch themes with the ABP Framework. [See it here](https://community.abp.io/posts/customizing-the-abp-basic-theme-with-bootswatch-4luoqzr0). -Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/submit +Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/create ## Conclusion diff --git a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md index 24f55474ad..70cb53c75e 100644 --- a/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md +++ b/docs/en/Blog-Posts/2024-02-16 v8_1_Preview/POST.md @@ -230,7 +230,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [A Best Practice for Designing Interfaces in .NET C#](https://community.abp.io/posts/a-best-practice-for-designing-interfaces-in-.net-c-9xqc4h8d) * [Invariance, Covariance, and Contravariance in .NET C#](https://community.abp.io/posts/invariance-covariance-and-contravariance-in-.net-c-9blmuhme) -Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community. +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Blog-Posts/2024-05-21 v8_2_Release/POST.md b/docs/en/Blog-Posts/2024-05-21 v8_2_Release/POST.md index 23260950d4..aadaae1c6f 100644 --- a/docs/en/Blog-Posts/2024-05-21 v8_2_Release/POST.md +++ b/docs/en/Blog-Posts/2024-05-21 v8_2_Release/POST.md @@ -260,7 +260,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [Using FluentValidation with ABP Framework](https://community.abp.io/posts/using-fluentvalidation-with-abp-framework-2cxuwl70) by [Enes Döner](https://community.abp.io/members/Enes) * [Using Blob Storage with ABP](https://community.abp.io/posts/using-blob-storage-with-abp-framework-jygtmhn4) by [Emre Kendirli](https://community.abp.io/members/emrekenderli) -Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community. +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Blog-Posts/2024-07-31 v8_3_Preview/post.md b/docs/en/Blog-Posts/2024-07-31 v8_3_Preview/post.md index 2d8a767568..fc3590b0d5 100644 --- a/docs/en/Blog-Posts/2024-07-31 v8_3_Preview/post.md +++ b/docs/en/Blog-Posts/2024-07-31 v8_3_Preview/post.md @@ -168,7 +168,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [How to use .NET Aspire with ABP framework](https://abp.io/community/articles/how-to-use-.net-aspire-with-abp-framework-h29km4kk) by [Berkan Şaşmaz](https://twitter.com/berkansasmazz) * [Exciting New Feature in ABP.IO CMS Kit: Marked Item System](https://abp.io/community/articles/exciting-new-feature-in-abp.io-cms-kit-marked-item-system.-2hvpq0me) by [Suhaib Mousa](https://abp.io/community/members/suhaibmousa032@gmail.com) -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. +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/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md index e69fbb86ea..3ac9de075a 100644 --- a/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md +++ b/docs/en/Blog-Posts/2024-09-06 v8_3_Release_Stable/POST.md @@ -70,7 +70,7 @@ As always, exciting articles have been contributed by the ABP community. I will * [Introducing the Google Cloud Storage BLOB Provider](https://abp.io/community/articles/introducing-the-google-cloud-storage-blob-provider-yrt6azc0) by [Engincan Veske](https://twitter.com/EngincanVeske) * [Switching Between Organization Units](https://abp.io/community/articles/switching-between-organization-units-i5tokpzt) by [Liming Ma](https://github.com/maliming) -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. +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/create) to the ABP Community. ## About the Next Version diff --git a/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/POST.md b/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/POST.md index f06648e586..db52eed7d5 100644 --- a/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/POST.md +++ b/docs/en/Blog-Posts/2024-10-23 v9_0_Preview/POST.md @@ -214,7 +214,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [ABP-Powered Web App with Inertia.js, React, and Vite](https://abp.io/community/articles/abppowered-web-app-with-inertia.js-react-and-vite-j7cccvad) by [Anto Subash](https://antosubash.com/) * [Multi-Tenancy Support in Angular Apps with ABP.IO](https://abp.io/community/articles/multitenancy-support-in-angular-apps-with-abp.io-lw9l36c5) by [HeadChannel Team](https://headchannel.co.uk/) -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. +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/create) to the ABP Community. ## Conclusion 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 index 26850bc57f..9c96351d96 100644 --- 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 @@ -78,7 +78,7 @@ In addition to [the articles to highlight .NET 9.0 features written by our team] * [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. +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/create) to the ABP Community. ### ABP Community Talks 2024.7: What’s New with .NET 9 & ABP 9? diff --git a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md index bb8bfdf4c7..bbcc69c727 100644 --- a/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md +++ b/docs/en/Blog-Posts/2025-01-21 v9_1_Preview/POST.md @@ -138,7 +138,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [The new Unit Test structure in ABP application](https://abp.io/community/articles/the-new-unit-test-structure-in-abp-application-4vvvp2oy) by [Liming Ma](https://github.com/maliming) * [How to Use OpenAI API with ABP Framework](https://abp.io/community/articles/how-to-use-openai-api-with-abp-framework-rsfvihla) by [Berkan Şaşmaz](https://github.com/berkansasmaz) -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. +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/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md index 96096807f1..2e6764e9b7 100644 --- a/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md +++ b/docs/en/Blog-Posts/2025-03-07 v9_1_Release_Stable/POST.md @@ -67,7 +67,7 @@ As always, exciting articles have been contributed by the ABP community. I will * [Containerization: Blazor WASM + JWT Web API => Docker](https://abp.io/community/articles/containerization-blazor-wasm-jwt-web-api-docker-i3eirlsf) by [Bart Van Hoey](https://abp.io/community/members/bartvanhoey) * [Configuring Post-Logout Redirect URI in ABP Based Blazor Applications with OpenIddict](https://abp.io/community/articles/configuring-postlogout-redirect-uri-in-abp-based-blazor-applications-with-openiddict-1t84suxg) by [Engincan Veske](https://github.com/EngincanV) -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. +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/create) to the ABP Community. ### ABP Community Talks 2025.2: Real World Problems and Solutions with AI diff --git a/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md index 8ddcf07cac..e59e75f44a 100644 --- a/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md +++ b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md @@ -25,6 +25,7 @@ Here is a brief list of titles explained in the next sections: * Docs Module: Added "Alternative Words" to Filter Items * Introducing the Bunny BLOB Storage Provider * Upgraded `MongoDB.Driver` to v3.1.0 +* Using Timezone Settings to Display Datetime * Identity Pro Module: Require Email Verification to Register * Switching users during OAuth login @@ -114,6 +115,49 @@ The upgrade provides: We have prepared a [migration guide](https://abp.io/docs/9.2/release-info/migration-guides/MongoDB-Driver-2-to-3) for this upgrade. Please refer to it to learn more about the changes and how to migrate your application. +### Using Timezone Settings to Display Datetime + +A significant enhancement in ABP v9.2 is the ability to use timezone settings to display `DateTime` values according to the user's or application's configured timezone. Introduced in `v9.2.0-rc.2`, this feature addresses the common challenge of ensuring users see accurate time information, regardless of their geographical location. + +Previously, `DateTime` values were often shown in the server's timezone or in UTC, which could cause confusion for users in different timezones. With this new feature, ABP applications can now respect the configured timezone and automatically convert and display datetime values accordingly. + +**Before setting the timezone:** + +Consider a scenario where you have a list of books, and the `CreationTime` property is displayed without any timezone consideration. It may appear in the server's default timezone: + +![before.png](before.png) +*(Screenshot of a Books page showing the CreationTime in a default timezone.)* + +**Setting the timezone:** + +To set the timezone, start by configuring the `AbpClockOptions` in your module's `ConfigureServices` method: + +```csharp +Configure(options => +{ + options.Kind = DateTimeKind.Utc; +}); +``` + +> By setting the `Kind` property of `AbpClockOptions` to `DateTimeKind.Utc`, ABP will normalize all datetime values. Times stored in the database and returned to the frontend will be in UTC. Additionally, the `SupportsMultipleTimezone` property of the `IClock` service will be **true**, and you’ll be able to configure the timezone from the UI under the _Settings_ page. + +After setting the `Kind` property, you can run your application and configure the timezone from the UI under the _Settings_ page. For example, set the timezone to "Asia/Tokyo (+09:00)": + +![configure-timezone.png](configure-timezone.png) +*(Screenshot showing the configuration setting for Abp.Timing.TimeZone, set to "Asia/Tokyo (+09:00)".)* + +> ABP provides the `Abp.Timing.TimeZone` setting, which allows you to configure the desired timezone at the application, tenant, or user level and this setting can be configured in the UI under the _Settings_ page, inside of the _Time Zone_ tab. + +**After setting the timezone:** + +Once the timezone is configured, ABP automatically handles the conversion and display of `DateTime` values. The `CreationTime` on the _Books_ page will now be shown in the **"Asia/Tokyo"** timezone. + +![after.png](after.png) +*(Screenshot of the _Books_ page after setting the timezone, showing the `CreationTime` adjusted to the "Asia/Tokyo" timezone.)* + +This feature utilizes the `IClock` service, which provides methods like `ConvertToUserTime` and `ConvertToUtc` to facilitate timezone conversions. By configuring the `Abp.Timing.TimeZone` setting, developers can ensure a consistent and user-friendly experience across applications with a global user base. +> For a more detailed guide on implementing and using this feature, refer to the article: [Developing a Multi-Timezone Application Using the ABP Framework](https://abp.io/community/articles/developing-a-multitimezone-application-using-the-abp-framework-zk7fnrdq). It offers step-by-step instructions and examples for handling multi-timezone scenarios in ABP applications. + ### Identity Pro Module: Require Email Verification to Register [ABP Identity Pro module](https://abp.io/docs/9.2/modules/identity-pro) has been enhanced with a new feature that allows administrators to require email verification during the registration process. This security improvement ensures that users must verify their email addresses before their registration is considered complete. Enabling this feature is especially important for applications that want to prevent spam registrations. @@ -142,7 +186,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [How to Change the CurrentUser in ABP?](https://abp.io/community/articles/how-to-change-the-currentuser-in-abp-i3uu1m7g) by [Engincan Veske](https://github.com/EngincanV) -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. +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/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/after.png b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/after.png new file mode 100644 index 0000000000..f9f72302a5 Binary files /dev/null and b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/after.png differ diff --git a/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/before.png b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/before.png new file mode 100644 index 0000000000..14340f91ee Binary files /dev/null and b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/before.png differ diff --git a/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/configure-timezone.png b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/configure-timezone.png new file mode 100644 index 0000000000..d383eee6f6 Binary files /dev/null and b/docs/en/Blog-Posts/2025-03-27 v9_2_Preview/configure-timezone.png differ diff --git a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md index 03caff8007..98685933ba 100644 --- a/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md +++ b/docs/en/Community-Articles/2020-09-09-Replacing-Email-Template-and-Sending-Emails/POST.md @@ -470,6 +470,12 @@ namespace TemplateReplace * I highly recommend you to [check it out](https://commercial.abp.io/modules/Volo.TextTemplateManagement). +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## References * [Text Templating](https://docs.abp.io/en/abp/latest/Text-Templating) diff --git a/docs/en/Community-Articles/2020-12-10-How-to-Integrate-the-Telerik-Blazor-Component/POST.md b/docs/en/Community-Articles/2020-12-10-How-to-Integrate-the-Telerik-Blazor-Component/POST.md index 6445d83e85..f946db23b9 100644 --- a/docs/en/Community-Articles/2020-12-10-How-to-Integrate-the-Telerik-Blazor-Component/POST.md +++ b/docs/en/Community-Articles/2020-12-10-How-to-Integrate-the-Telerik-Blazor-Component/POST.md @@ -4,6 +4,12 @@ Hi, in this step by step article, we will see how we can integrate the Telerik Blazor Components to our Blazor UI. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Creating the Solution > ABP Framework offers startup templates to get into business faster. @@ -532,6 +538,12 @@ namespace TelerikComponents.Blazor.Pages ![final-result](./final-result.jpg) +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion In this article, I've tried to explain how we can integrate [Telerik Blazor Component](https://www.telerik.com/blazor-ui) to our Blazor UI. ABP Framework designed as modular, so that it can work with any UI library/framework. \ No newline at end of file diff --git a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md index 0ec86d40c4..2f5cde6d2d 100644 --- a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md +++ b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md @@ -1,11 +1,19 @@ # Using Elsa Workflow with ABP Framework +> **UPDATE:** There is a newer version of this article, which covers Elsa 3 with ABP Framework. You can check it at https://abp.io/community/articles/using-elsa-3-workflow-with-abp-framework-usqk8afg + **Elsa Core** is an open-source workflows library that can be used in any kind of .NET Core application. Using such a workflow library can be useful to implement business rules visually or programmatically. ![elsa-overview](./elsa-overview.gif) This article shows how we can use this workflow library within our ABP-based application. We will start with a couple of examples and then we will integrate the **Elsa Dashboard** (you can see it in the above gif) into our application to be able to design our workflows visually. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Source Code You can find the source of the example solution used in this article [here](https://github.com/abpframework/abp-samples/tree/master/ElsaDemo). @@ -453,4 +461,10 @@ namespace ElsaDemo.Web.Menus * Now we can click the "Workflow" menu item, display the Elsa Dashboard and designing workflows. -![elsa-demo-result](./elsa-demo-result.gif) \ No newline at end of file +![elsa-demo-result](./elsa-demo-result.gif) + +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- diff --git a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md index ae688d6981..81c0b6ea34 100644 --- a/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md +++ b/docs/en/Community-Articles/2021-10-31-Many-to-Many-Relationship-with-ABP-and-EF-Core/POST.md @@ -10,6 +10,12 @@ You can see the ER Diagram of our application below. This diagram will be helpfu When we've examined the ER Diagram, we can see the one-to-many relationship between the **Author** and the **Book** tables. Also, the many-to-many relationship (**BookCategory** table) between the **Book** and the **Category** tables. (There can be more than one category on each book and vice-versa in our scenario). +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ### Source Code You can find the source code of the application at https://github.com/EngincanV/ABP-Many-to-Many-Relationship-Demo . @@ -1664,6 +1670,12 @@ namespace BookStore.Web.Pages.Books ![Edit Book Modal](./book-update-modal.png) +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ### Conclusion In this article, I've tried to explain how to create a many-to-many relationship by using the ABP framework. (by following DDD principles) diff --git a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md index 4095c62092..2953c552d3 100644 --- a/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md +++ b/docs/en/Community-Articles/2021-12-13-Integrating-the-Syncfusion-MVC-Components-to-the-ABP-MVC-UI/POST.md @@ -4,6 +4,12 @@ In this article we will see how we can integrate the Syncfusion MVC Components into our ABP application. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Source Code You can find the source code of the application at https://github.com/EngincanV/ABP-Syncfusion-Components-Demo. @@ -314,6 +320,12 @@ After injecting the Syncfusion style and script into our application, our config ![](./calendar-component.png) +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ### Conclusion In this article, we've explained how to integrate the **Syncfusion Components** into our applications. After following this article, you can use the Syncfusion components in your application. diff --git a/docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md b/docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md index a6ad7596d4..d4102d8256 100644 --- a/docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md +++ b/docs/en/Community-Articles/2022-02-06-How-to-Hide-ABP-Related-Endpoints-on-Swagger-UI/POST.md @@ -8,6 +8,12 @@ In the issue, there are helpful comments about hiding the ABP related endpoints I thought it would be better to enable/disable showing endpoints on runtime by simply selecting a checkbox on the Setting Management page and in this article I wanted to show you how, so let's dive in. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Source Code You can find the source code of the application at https://github.com/EngincanV/ABP-Hide-Swagger-Endpoint-Demo. @@ -445,6 +451,10 @@ services.AddAbpSwaggerGen( > For more info, please see the [Swagger Integration](https://docs.abp.io/en/abp/latest/API/Swagger-Integration#hide-abp-endpoints-on-swagger-ui) docs. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv --- Thanks for reading. \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md index be89ccb092..e43ba9a529 100644 --- a/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md +++ b/docs/en/Community-Articles/2022-03-09-abpio-platform-52-rc-has-been-published/post.md @@ -186,7 +186,7 @@ We organized the 3rd live [ABP Community Talks](https://community.abp.io/events) * [Enis Necipoğlu](https://twitter.com/EnisNecipoglu) has also created [an article](https://community.abp.io/posts/using-autofilterer-with-abp-framework-uuqv81jm) to demonstrate how to use his own open source [AutoFilterer](https://github.com/enisn/AutoFilterer) library with the ABP Framework. * [Jonathan Potts](https://github.com/jonathanpotts) has created his first ABP Community article that shows how to use Bootswatch themes with the ABP Framework. [See it here](https://community.abp.io/posts/customizing-the-abp-basic-theme-with-bootswatch-4luoqzr0). -Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/submit +Thanks to all the contributors. It is appreciated if you want to submit your post and share your knowledge with the ABP community: https://community.abp.io/posts/create ## Conclusion diff --git a/docs/en/Community-Articles/2022-04-06-Concurrency-Check-in-ABP-Based-Applications/POST.md b/docs/en/Community-Articles/2022-04-06-Concurrency-Check-in-ABP-Based-Applications/POST.md index b16d6bd9f1..cf8c3c122a 100644 --- a/docs/en/Community-Articles/2022-04-06-Concurrency-Check-in-ABP-Based-Applications/POST.md +++ b/docs/en/Community-Articles/2022-04-06-Concurrency-Check-in-ABP-Based-Applications/POST.md @@ -2,6 +2,12 @@ In this article, we'll create a basic application to demonstrate how "Concurrency Check/Control" can be implemented in an ABP project. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Creating the Solution For this article, we will create a simple BookStore application and add CRUD functionality to the pages. Hence we deal with the concurrency situation. @@ -546,3 +552,9 @@ Then we can run the application, navigate to the **/Books** endpoint and see the * After the first user updated the record, the second user tries to update the same record without getting the last state of the record. And therefore `AbpDbConcurrencyException` is thrown because **ConcurrencyStamp** values are different from each other. * The second user should close and re-open the model to get the last state of the record and then they can make changes to the current record. + +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- \ No newline at end of file diff --git a/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md index 9663ac1f83..e0f1f38aa9 100644 --- a/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md +++ b/docs/en/Community-Articles/2022-11-22-gRPC-JSON-Transcoding/POST.md @@ -4,6 +4,12 @@ In this article, I'll show you one of the new features that came with .NET 7: ** > I've created a community article to highlight some interesting features (briefly) that are now available with the release of .NET 7. You can check it from [here](https://community.abp.io/posts/whats-new-with-.net-7-tlq2g43w). +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## What is gRPC? What are the pros and cons? [gRPC](https://grpc.io/) is a high-performance RPC framework and uses HTTP/2 and Protobuf (protocol buffers). @@ -189,6 +195,12 @@ In this article, I've briefly introduced the JSON Transcoding feature that was s > See the [gRPC JSON transcoding in ASP.NET Core gRPC apps](https://learn.microsoft.com/en-us/aspnet/core/grpc/json-transcoding?view=aspnetcore-7.0) documentation for more information. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## References * https://devblogs.microsoft.com/dotnet/announcing-grpc-json-transcoding-for-dotnet/ diff --git a/docs/en/Community-Articles/2022-18-11-whats-new-with-net7/POST.md b/docs/en/Community-Articles/2022-18-11-whats-new-with-net7/POST.md index fb964fa730..671592d63e 100644 --- a/docs/en/Community-Articles/2022-18-11-whats-new-with-net7/POST.md +++ b/docs/en/Community-Articles/2022-18-11-whats-new-with-net7/POST.md @@ -6,6 +6,12 @@ In this article, I will highlight a few interesting features that are now availa There are many new features coming with this release. We are going to examine new features within 4 sub-sections: ASP.NET Core, C#11, EF 7 and MAUI. Let's start with ASP.NET Core. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## ASP.NET Core We will see the following features in this section: @@ -290,6 +296,12 @@ In this article, I've highlighted some features that were shipped with .NET 7. Thanks for reading the article and I hope you find it helpful. See you in the next one! +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## References * https://devblogs.microsoft.com/dotnet/announcing-dotnet-7/ diff --git a/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md index 9023417b20..1a1aa55f97 100644 --- a/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md +++ b/docs/en/Community-Articles/2023-07-03-Image-Compression-And-Resize/POST.md @@ -8,6 +8,12 @@ ABP Framework provides services to compress and resize images and implements the > Refer to the documentation for more info: [Image Manipulation](https://docs.abp.io/en/abp/7.3/Image-Manipulation) +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ### Source Code You can find the source code of the application at [https://github.com/abpframework/abp-samples/tree/master/ImageManipulation](https://github.com/abpframework/abp-samples/tree/master/ImageManipulation). Don't hesitate to check the source code, if you are stuck on any point. @@ -281,6 +287,12 @@ The results are impressive for the example above: * The original image was 12 KB and now the compressed & resized image has been reduced to 8 KB. * The original image was 225x225 and now resized as 200x200. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion In this article, I have shown you how to compress and/or resize images with ABP Framework's Image Manipulation System by just defining some attributes to the top of the controller actions. diff --git a/docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md b/docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md index 38cfab67e9..3d62f38886 100644 --- a/docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md +++ b/docs/en/Community-Articles/2023-08-12-ABP-Commercial-GDPR-Module-Overview/POST.md @@ -2,6 +2,12 @@ In this article, I will highlight ABP Commercial's [GDPR Module](https://commercial.abp.io/modules/Volo.Gdpr) and show you how to provide personal data to the GDPR Module that is collected by your application and make it aligned with personal data download results. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## GDPR Module [GDPR Module](https://docs.abp.io/en/commercial/latest/modules/gdpr) allows users to download and delete the data collected by the application. It's used for Personal Data Management obligating by the GDPR regulation and provides the following features: @@ -143,6 +149,12 @@ Then, when we clicked the download button, a zip file will be downloaded. We can {"City":"Istanbul","Postcode":"..."} ``` +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion In this article, I've explained the GDPR Module's data collection system and given you a brief overview of the module. GDPR Module allows you to request to download personal data, delete/anonymize your own personal data and delete your account permanently. It's pre-installed in the Application and Application(single layer) Pro Startup templates, but you can easily configure it to your existing application. diff --git a/docs/en/Community-Articles/2023-10-30-NET-8-ASP-NET-Core-Metrics/POST.md b/docs/en/Community-Articles/2023-10-30-NET-8-ASP-NET-Core-Metrics/POST.md index 9142a36be9..9586b51cf5 100644 --- a/docs/en/Community-Articles/2023-10-30-NET-8-ASP-NET-Core-Metrics/POST.md +++ b/docs/en/Community-Articles/2023-10-30-NET-8-ASP-NET-Core-Metrics/POST.md @@ -2,6 +2,12 @@ In this article, I'll show you the new built-in metrics of .NET 8, which are basically numerical measurements reported over time in your application and can be used to monitor the health of your application and generate reports according to those numerical values. We will see what the metrics are, why to use them, and how to use them in detail. So, let's dive in. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## What are Metrics? Metrics are numerical measurements reported over time. These measurements are crucial for monitoring the health of an application and generating alerts when necessary. In the context of a web service, various metrics can be tracked, such as: @@ -185,6 +191,12 @@ If you want to build a dashboard, you can see [this documentation from Microsoft Also, you can check [this video](https://www.youtube.com/watch?v=A2pKhNQoQUU) if you want to see it in action. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion In this article, I've shown you the new built-in metrics of .NET8, described what metrics are, which pre-built metrics are provided by ASP.NET Core, how to use & view these pre-built metrics and finally, I have shown you how to create custom metrics and view them in a dashboard. If you want to learn more about the **Metrics System of .NET**, you can check out the references that I have shared below. diff --git a/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md b/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md index 3ed34680c1..c247f1e3e9 100644 --- a/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md +++ b/docs/en/Community-Articles/2023-11-16-Upgrading-Your-Existing-Projects-to-NET8/POST.md @@ -4,6 +4,12 @@ A new .NET version was released on November 14, 2023 and ABP 8.0 RC.1 shipped ba Despite all the related dependency upgrades and changes made on the ABP Framework and ABP Commercial sides, we still need to make some changes. Let's see the required actions that need to be taken in the following sections. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Installing the .NET 8.0 SDK To get started with ASP.NET Core in .NET 8.0, you need to install the .NET 8 SDK. You can install it at [https://dotnet.microsoft.com/en-us/download/dotnet/8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0). @@ -99,3 +105,9 @@ After that, you need to check the migration guide documents, listed below: That's it! These were all the related steps that need to be taken to upgrade your application to .NET 8 and ABP 8.0. Now, you can enjoy the .NET 8 & ABP 8.0 and benefit from the performance improvements and new features. Happy Coding 🤗 + +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- \ No newline at end of file diff --git a/docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md b/docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md index d100838b1a..aeefc03c0c 100644 --- a/docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md +++ b/docs/en/Community-Articles/2024-01-18-ABP-Now-Supports-Keyed-Services/POST.md @@ -2,6 +2,12 @@ In this post, I describe the new **"keyed service"** support for the dependency injection container, which came with .NET 8.0. Then, I'll show you an example of usage within the ABP Framework. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## What Are Keyed Services? ASP.NET Core ships with a built-in dependency injection container, which is a pretty basic DI container that supports minimal features a dependency injection container is supposed to have. For that reason, most of the .NET users use third-party containers like [Autofac](https://autofac.org/), or Ninject. @@ -203,6 +209,12 @@ public class TaxCalculator: ICalculator, ITaxCalculator, ICanCalculate, ITransie Please refer to the [Dependency Injection document](https://abp.io/docs/latest/framework/fundamentals/dependency-injection#exposekeyedservice-attribute) for further info. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Summary In this post, I described the new **"keyed service"** support added to the built-in dependency injection container that was released in .NET 8, and wanted to announce it's being supported from v8.0.2 for ABP Framework. It's a really good addition to the built-in dependency injection container and can be pretty useful for certain use-cases. diff --git a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md index 569e566af7..fbe2c2cbad 100644 --- a/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md +++ b/docs/en/Community-Articles/2024-02-19-abpio-platform-81-rc-has-been-published/post.md @@ -228,7 +228,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [A Best Practice for Designing Interfaces in .NET C#](https://community.abp.io/posts/a-best-practice-for-designing-interfaces-in-.net-c-9xqc4h8d) * [Invariance, Covariance, and Contravariance in .NET C#](https://community.abp.io/posts/invariance-covariance-and-contravariance-in-.net-c-9blmuhme) -Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community. +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md b/docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md index e4f763f279..5eb4a5bd98 100644 --- a/docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md +++ b/docs/en/Community-Articles/2024-04-19-Performing-Case-Insensitive-Search-In-Postgresql/POST.md @@ -120,6 +120,12 @@ After these configurations, you should create a migration and apply it to your d However, this solution comes with some problems, for example, by using non-deterministic collations, it's not yet possible to use pattern-matching operators such as `LIKE` on columns. This is a huge problem because it makes it hard to use LINQ. For example, you can't use the `.EndsWith` or `.StartsWith` methods, because they are [translated to `LIKE` command on the SQL level](https://www.npgsql.org/efcore/mapping/translations.html). +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion In PostgreSQL, you can perform case-insensitive searches by using the `citext` data type or by utilizing collation settings. Nevertheless, if you have an ABP-based PostgreSQL application or a plain .NET application with PostgreSQL as the database option, to make a decision to pick one of these options, you can follow the following points: diff --git a/docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md b/docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md index e6417b70ce..deb162bcba 100644 --- a/docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md +++ b/docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md @@ -4,6 +4,12 @@ In this article, first I will briefly explain what sentiment analysis is and the We will use ML.NET Framework, which is an open-source machine learning framework created by the dotnet team and also we will create a layered ABP Solution by using the application template and finally we will use CMS Kit's Comment Feature and extend its behavior by adding spam detection while creating or updating a comment, at that point we will make sentiment analysis. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Sentiment Analysis [Sentiment Analysis (or opinion mining)](https://en.wikipedia.org/wiki/Sentiment_analysis) refers to determining the emotion from the given input. The primary goal of sentiment analysis is to identify, extract, and categorize (positive, negative, or neutral) the sentiments expressed in textual data. @@ -333,6 +339,12 @@ Then, finally, we can run the application to see the final results: Once the model is trained and evaluated, we can save the trained model and use it directly for further use. In this way, you don’t have to retrain the model every time when you want to make predictions. It’s essential to save the trained model for future use and a must for the production-ready code. I created a separate article dedicated to that topic, and if you are interested, you can read it from [here](https://engincanv.github.io/machine-learning/sentiment-analysis/best-practises/2024/05/16/reusing-and-optimizing-machine-learning-models-in-dotnet.html). +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion In this article, I briefly explain what sentiment analysis is, created a sample ABP-based application, integrated the CMS Kit Module and finally, applied sentiment analysis to make spam checks whenever a new comment has been submitted or updated. You can get the source code of the demo from [https://github.com/EngincanV/SentimentAnalysisDemo](https://github.com/EngincanV/SentimentAnalysisDemo) diff --git a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md index 6574012f24..c3eadb6419 100644 --- a/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md +++ b/docs/en/Community-Articles/2024-05-24-abpio-platform-82-rc-has-been-published/post.md @@ -259,7 +259,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [Using FluentValidation with ABP Framework](https://community.abp.io/posts/using-fluentvalidation-with-abp-framework-2cxuwl70) by [Enes Döner](https://community.abp.io/members/Enes) * [Using Blob Storage with ABP](https://community.abp.io/posts/using-blob-storage-with-abp-framework-jygtmhn4) by [Emre Kendirli](https://community.abp.io/members/emrekenderli) -Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/submit) to the ABP Community. +Thanks to the ABP Community for all the content they have published. You can also [post your ABP-related (text or video) content](https://community.abp.io/posts/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md index 05c18fde03..4ddd247a63 100644 --- a/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md +++ b/docs/en/Community-Articles/2024-08-01-abpio-platform-83-rc-has-been-published/post.md @@ -165,7 +165,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [How to use .NET Aspire with ABP framework](https://abp.io/community/articles/how-to-use-.net-aspire-with-abp-framework-h29km4kk) by [Berkan Şaşmaz](https://twitter.com/berkansasmazz) * [Exciting New Feature in ABP.IO CMS Kit: Marked Item System](https://abp.io/community/articles/exciting-new-feature-in-abp.io-cms-kit-marked-item-system.-2hvpq0me) by [Suhaib Mousa](https://abp.io/community/members/suhaibmousa032@gmail.com) -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. +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/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md index 55f7b80294..de27f8cdbd 100644 --- a/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md +++ b/docs/en/Community-Articles/2024-09-12-abpio-platform-83-final-has-been-released/post.md @@ -70,7 +70,7 @@ As always, exciting articles have been contributed by the ABP community. I will * [Introducing the Google Cloud Storage BLOB Provider](https://abp.io/community/articles/introducing-the-google-cloud-storage-blob-provider-yrt6azc0) by [Engincan Veske](https://twitter.com/EngincanVeske) * [Switching Between Organization Units](https://abp.io/community/articles/switching-between-organization-units-i5tokpzt) by [Liming Ma](https://github.com/maliming) -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. +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/create) to the ABP Community. ## About the Next Version diff --git a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md index 9e22660332..a7dfa896bd 100644 --- a/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md +++ b/docs/en/Community-Articles/2024-10-23-abpio-platform-90-rc-has-been-published/post.md @@ -210,7 +210,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [ABP-Powered Web App with Inertia.js, React, and Vite](https://abp.io/community/articles/abppowered-web-app-with-inertia.js-react-and-vite-j7cccvad) by [Anto Subash](https://antosubash.com/) * [Multi-Tenancy Support in Angular Apps with ABP.IO](https://abp.io/community/articles/multitenancy-support-in-angular-apps-with-abp.io-lw9l36c5) by [HeadChannel Team](https://headchannel.co.uk/) -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. +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/create) to the ABP Community. ## Conclusion 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 index 3cd4bdc706..a9b869a822 100644 --- 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 @@ -6,6 +6,12 @@ It offers a flexible caching solution that combines the best aspects of local an 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. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## 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: @@ -109,6 +115,12 @@ As you can see from the figure, it only set the cache item to the **LocalCache** **Note:** If you configure distributed caching options, `HybridCache` service uses the distributed cache and sets the **BackendCache**. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion The **HybridCache** library in .NET 9 provides a powerful tool for applications needing both high-speed caching and consistency in distributed environments. diff --git a/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md index 30ff978de6..931379eac0 100644 --- a/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md +++ b/docs/en/Community-Articles/2024-11-21-abpio-platform-90-has-been-released-based-on-net-90/post.md @@ -80,7 +80,7 @@ In addition to [the articles to highlight .NET 9.0 features written by our team] * [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. +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/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md index 2c3a98ac49..615457a7ff 100644 --- a/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md +++ b/docs/en/Community-Articles/2025-01-21-abp-platform-91-rc-has-been-released/post.md @@ -136,7 +136,7 @@ There are exciting articles contributed by the ABP community as always. I will h * [The new Unit Test structure in ABP application](https://abp.io/community/articles/the-new-unit-test-structure-in-abp-application-4vvvp2oy) by [Liming Ma](https://github.com/maliming) * [How to Use OpenAI API with ABP Framework](https://abp.io/community/articles/how-to-use-openai-api-with-abp-framework-rsfvihla) by [Berkan Şaşmaz](https://github.com/berkansasmaz) -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. +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/create) to the ABP Community. ## Conclusion diff --git a/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md index f5602650ae..e8b8c9a1b3 100644 --- a/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md +++ b/docs/en/Community-Articles/2025-02-04-OpenIddict-Custom-Logic/POST.md @@ -6,6 +6,12 @@ OpenIddict provides an event-driven model ([event models](https://documentation. In this article, we will explore OpenIddict event models, their key use cases, and how to implement them effectively. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Understanding OpenIddict Event Model OpenIddict events are primarily used within the OpenIddict server component. These events provide hooks into the OpenID Connect flow, allowing developers to modify behavior at different stages of authentication & authorization processes. @@ -101,6 +107,12 @@ That's it! After these steps, your `SignOutEventHandler.HandleAsync()` method sh Each event provides access to the relevant context, allowing you to access and modify the authentication flow's behavior. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion ABP Framework integrates OpenIddict as its authentication and authorization module. OpenIddict provides an event-driven model that allows developers to customize authentication and authorization processes within their ABP applications. It's pre-installed & pre-configured in the ABP's startup templates. diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list-utc1.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list-utc1.png new file mode 100644 index 0000000000..9adbd41062 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list-utc1.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list-utc3.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list-utc3.png new file mode 100644 index 0000000000..51256b2d62 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list-utc3.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list.png new file mode 100644 index 0000000000..cc0a92b591 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/auth-list.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/berlin.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/berlin.png new file mode 100644 index 0000000000..07715caabd Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/berlin.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-create.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-create.png new file mode 100644 index 0000000000..5385c14167 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-create.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-edit.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-edit.png new file mode 100644 index 0000000000..95c0357171 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-edit.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-list.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-list.png new file mode 100644 index 0000000000..181983492c Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/blazor-list.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-create.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-create.png new file mode 100644 index 0000000000..827e8911d7 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-create.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-edit.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-edit.png new file mode 100644 index 0000000000..a3cc8a6a0c Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-edit.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list-utc1.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list-utc1.png new file mode 100644 index 0000000000..9904c56df5 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list-utc1.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list-utc3.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list-utc3.png new file mode 100644 index 0000000000..7d472296fb Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list-utc3.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list.png new file mode 100644 index 0000000000..282f288855 Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-list.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-post.png b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-post.png new file mode 100644 index 0000000000..35bff4aded Binary files /dev/null and b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/mvc-post.png differ diff --git a/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md new file mode 100644 index 0000000000..09d7f917bb --- /dev/null +++ b/docs/en/Community-Articles/2025-03-11-Developing-A-Multi-Timezone-Application-Using-The-ABP-Framework/post.md @@ -0,0 +1,781 @@ +# Developing a Multi-Timezone Application Using the ABP Framework + +When developing multi-timezone applications, we need to handle users from different time zones and make sure they see the correct time. The system also needs to support users changing their timezone (like when traveling or moving) and make sure all time displays update correctly to show accurate time information. + +All these scenarios require us to handle timezone conversions correctly in our application. The ABP framework provides a complete solution for these challenges. + +In this article, we'll show you step by step how to handle multi-timezone in the ABP framework. + +> The content mentioned in this article will be available after the ABP 9.2 version + +## Timezone Settings + +The ABP framework provides a setting called `Abp.Timing.TimeZone` for setting and getting the timezone of users, tenants, or applications. The default value is empty, which means the application will use the server's time zone. Check out the [Timing documentation](https://abp.io/docs/latest/framework/infrastructure/timing) for more information. + +## ISO 8601 Date Time Format + +Different countries and regions may use different time formats: + +* Year-Month-Day (YYYY-MM-DD): Mainly used in China, Japan, Korea, Canada (official standard), Germany (ISO standard), ISO 8601 international standard, etc. Example: 2025-03-11 +* Day-Month-Year (DD-MM-YYYY): Mainly used in UK, India, Australia, New Zealand, most European countries (like France, Germany, Italy, Spain), some South American countries, etc. Example: 11-03-2025 or 11/03/2025 +* Month-Day-Year (MM-DD-YYYY): Mainly used in USA, Philippines, some parts of Canada, etc. Example: 03-11-2025 or 03/11/2025 +* Day.Month.Year (DD.MM.YYYY): Mainly used in Germany, Russia, Switzerland, Hungary, Czech Republic, etc. Example: 11.03.2025 + +Also, different countries/regions might use different separators (like slash /, hyphen -, dot .), and some countries use different month abbreviations or full names (like March 11, 2025). + +ISO 8601 uses a standard format to avoid confusion between different date formats and ensure global compatibility. + +It has 4 parts: + +* Date part: `YYYY-MM-DD` +* `T` as a separator +* Time part: `HH:MM:SS` +* Timezone part: `Z` or `+/-HH:MM` + +You'll usually see formats like: `YYYY-MM-DDTHH:MM:SSZ` or `YYYY-MM-DDTHH:MM:SS+/-HH:MM`, for example: `2025-03-11T10:30:00Z` or `2025-03-11T22:30:00+03:00` + +When our application needs to handle multiple timezones, we usually use ISO 8601 to represent time. + +## Enabling Multi-Timezone Support + +When we set the `Kind` of `AbpClockOptions` to `DateTimeKind.Utc`, the ABP framework will normalize all times. Times written to the database and returned to the frontend will be in `UTC`. the `SupportsMultipleTimezone` property will be `true` in the `IClock` service. + +```csharp +Configure(options => +{ + options.Kind = DateTimeKind.Utc; +}); +``` + +### Using DateTime to Store Time + +Assuming the `DateTime` stored in the database is `2025-03-01 10:30:00`, then the time returned to the front end will be `2025-03-01T10:30:00Z`. This is a time in ISO 8601 format. Because `DateTime` does not have timezone information, the framework will assume it is `UTC` time. + +### Using DateTimeOffset to Store Time + +If you use `DateTimeOffset` to store time, the ABP framework will not normalize `DateTimeOffset`, but will return it directly to the front end. + +Assuming the `DateTimeOffset` stored in the database is `2025-03-01 13:30:00 +03:00`, then the time returned to the front end will be `2025-03-01T13:30:00+03:00`. This is also a time in ISO 8601 format. + +We recommend using `DateTimeOffset` to store time because it has timezone information. + +## Timezone Conversion + +### Converting UTC Time to User Time + +The `IClock` service has 2 methods to convert a given `UTC` time to the user time: + +```csharp +DateTime ConvertToUserTime(utcDateTime dateTime) +DateTimeOffset ConvertToUserTime(DateTimeOffset dateTimeOffset) +``` + +> If `SupportsMultipleTimezone` is `false` or `dateTime.Kind` is not `Utc` or no timezone is set, it will return the given `DateTime` or `DateTimeOffset` without any changes. + +**Example:** + +If the user's timezone is `Europe/Istanbul` + +```csharp +// 2025-03-01T05:30:00Z +var utcTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc); + +var userTime = Clock.ConvertToUserTime(utcTime); + +// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours later. +userTime.Kind.ShouldBe(DateTimeKind.Unspecified); +userTime.ToString("O").ShouldBe("2025-03-01T08:30:00"); +``` + +```csharp +// 2025-03-01T05:30:00Z +var utcTime = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc), TimeSpan.Zero); + +var userTime = Clock.ConvertToUserTime(utcTime); + +// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours later. +userTime.Offset.ShouldBe(TimeSpan.FromHours(3)); +userTime.ToString("O").ShouldBe("2025-03-01T08:30:00.0000000+03:00"); +``` + +### Converting User Time to UTC + +The `IClock` service has 1 method to convert a given user time to UTC. + +```csharp +DateTime ConvertToUtc(DateTime dateTime) +``` + +> If `SupportsMultipleTimezone` is `false` or `dateTime.Kind` is `Utc` or no timezone is set, it will return the given `DateTime` without any changes. + +**Example:** + +If the user's timezone is `Europe/Istanbul` + +```csharp +// 2025-03-01T05:30:00 +var userTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified); //Same as Local + +var utcTime = Clock.ConvertToUtc(userTime); + +// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours earlier. +utcTime.Kind.ShouldBe(DateTimeKind.Utc); +utcTime.ToString("O").ShouldBe("2025-03-01T02:30:00.0000000Z"); +``` + +## Handling Timezone in Different UIs + +We'll use the `TimeZoneApp` project to demonstrate handling timezone in different UIs. It has a `Meeting` entity, with several time properties. + +```csharp +public class Meeting : AggregateRoot +{ + public string Subject { get; set; } + + public DateTime StartTime { get; set; } + + public DateTime EndTime { get; set; } + + public DateTime ActualStartTime { get; set; } + + public DateTime? CanceledTime { get; set; } + + public DateTimeOffset ReminderTime { get; set; } + + public DateTimeOffset? FollowUpTime { get; set; } + + public string Description { get; set; } +} +``` + +`TimeZoneApp` project is an ABP layered architecture project, it sets a global `Europe/Istanbul` timezone, it contains 4 websites + +* `API.Host`: API website, it does not have UI, it returns data in JSON format +* `AuthServer`: Authentication server, it uses Razor Pages as UI +* `Web`: Razor Pages website, it uses JavaScript to manage Meeting creation and editing and display +* `Blazor`: Blazor Server website, it uses Blazor to manage Meeting creation and editing and display + +All 4 applications are enabled for multi-timezone support, and use the `UseAbpTimeZone` middleware. + +> Blazor WASM and Angular do not need to use the `UseAbpTimeZone` middleware + + +### DateTime in API Response + +In the API response, we usually use the ISO 8601 format time, as you can see, after enabling multi-timezone support, the API returns time to the front end as UTC time. + +`2025-03-01T09:30:00Z` and `2025-03-01T12:30:00+00:00` are ISO 8601 format time. + +```json +[ + { + "subject": "ABP Developer Guide", + "startTime": "2025-03-01T09:30:00Z", + "endTime": "2025-03-01T10:30:00Z", + "actualStartTime": "2025-03-01T11:30:00Z", + "canceledTime": null, + "reminderTime": "2025-03-01T12:30:00+00:00", + "followUpTime": "2025-03-01T13:30:00+00:00", + "description": "We will discuss the ABP developer guide.", + "id": "2af0abd3-be06-ecff-5d4c-3a1895ac7950" + }, + { + "subject": "ABP Training", + "startTime": "2025-03-01T09:30:00Z", + "endTime": "2025-03-01T10:30:00Z", + "actualStartTime": "2025-03-01T11:30:00Z", + "canceledTime": "2025-03-01T12:00:00Z", + "reminderTime": "2025-03-01T12:30:00+00:00", + "followUpTime": "2025-03-01T13:30:00+00:00", + "description": "ABP training for the new developers.", + "id": "290b0cb6-3e50-6324-1e79-3a1895ac795f" + } +] +``` + +### Handling Timezone in MVC/Razor Pages + +In the `AuthServer` project, we handle time conversion in a simple way: +1. First, we get the `Meeting` entities from the database using `IRepository`. At this point, all `DateTime` values are in UTC. +2. Then, when displaying the times in the view, we use `Clock.ConvertToUserTime` to show them in the user's timezone. + +> Note: The `ConvertToUserTime` method will only convert times if multi-timezone support is enabled in the application. + +```csharp +public class IndexModel : AbpPageModel +{ + public List? Meetings { get; set; } + + protected IRepository MeetingRepository { get; } + + public IndexModel(IRepository meetingRepository) + { + MeetingRepository = meetingRepository; + } + + public async Task OnGetAsync() + { + Meetings = await MeetingRepository.GetListAsync(); + } +} +``` + +```html +
+ +
+ + + + + + + + + + + + + + @foreach (var meeting in Model.Meetings) + { + + + + + + + + + + } + +
@L["Subject"]@L["StartTime"] / @L["EndTime"]@L["ActualStartTime"]@L["CanceledTime"]@L["ReminderTime"]@L["FollowUpTime"]@L["Description"]
@meeting.Subject@Clock.ConvertToUserTime(meeting.StartTime) ➡️ @Clock.ConvertToUserTime(meeting.EndTime)@Clock.ConvertToUserTime(meeting.ActualStartTime)@(meeting.CanceledTime.HasValue ? Clock.ConvertToUserTime(meeting.CanceledTime.Value) : "N/A")@Clock.ConvertToUserTime(meeting.ReminderTime).DateTime@(meeting.FollowUpTime.HasValue ? Clock.ConvertToUserTime(meeting.FollowUpTime.Value).DateTime : "N/A")@meeting.Description
+
+
+
+``` + +![](auth-list.png) + +### Handling Timezone in JavaScript + +In the `Web` project, we use JavaScript to handle timezone. + +#### Displaying Time in UI + +* `timeZoneApp.meetings.meeting.getList` gets all `Meeting` entities and displays them in `DataTables` +* `abp.clock.normalizeToLocaleString()` is the ABP JavaScript API, it converts `UTC` time to the current user's timezone, and then calls its `toLocaleString` method to format time +* `dataFormat: "datetime"` is the ABP DataTable extension method, it calls the `abp.clock.normalizeToLocaleString` method to convert and format time + +> If the current application is not enabled for multi-timezone support, then the `abp.clock.normalizeToLocaleString` method will not convert the time, it will just call the `Date` object's `toLocaleString` method. + +```js +var dataTable = $('#MeetingsTable').DataTable( + abp.libs.datatables.normalizeConfiguration({ + serverSide: true, + paging: true, + order: [[1, "asc"]], + searching: false, + scrollX: true, + ajax: abp.libs.datatables.createAjax(timeZoneApp.meetings.meeting.getList), + columnDefs: [ + { + title: l('Actions'), + rowAction: { + items: + [ + { + text: l('Edit'), + visible: abp.auth.isGranted('TimeZoneApp.Meetings.Edit'), + action: function (data) { + editModal.open({ id: data.record.id }); + }, + }, + { + text: l('Delete'), + visible: abp.auth.isGranted('TimeZoneApp.Meetings.Delete'), + confirmMessage: function (data) { + return l('MeetingDeletionConfirmationMessage', data.record.subject); + }, + action: function (data) { + timeZoneApp.meetings.meeting + .delete(data.record.id) + .then(function() { + abp.notify.info(l('SuccessfullyDeleted')); + dataTable.ajax.reload(); + }); + } + } + ] + } + }, + { + title: l('Subject'), + data: "subject" + }, + { + title: l('StartTime') + ' / ' + l('StartTime'), + data: "startTime", + render: function (data, type, row) { + return abp.clock.normalizeToLocaleString(row.startTime) + ' ➡️ ' + abp.clock.normalizeToLocaleString(row.endTime); + } + }, + { + title: l('ActualStartTime'), + data: "actualStartTime", + dataFormat: "datetime" + }, + { + title: l('CanceledTime'), + data: "canceledTime", + render: function (data, type, row) { + return data ? abp.clock.normalizeToLocaleString(data) : 'N/A'; + } + }, + { + title: l('ReminderTime'), + data: "reminderTime", + dataFormat: "datetime" + }, + { + title: l('FollowUpTime'), + data: "followUpTime", + render: function (data, type, row) { + return data ? abp.clock.normalizeToLocaleString(data) : 'N/A'; + } + }, + { + title: l('Description'), + data: "description" + } + ] + }) +); +``` + +Below is the screenshot of `DataTables`: + +![](mvc-list.png) + + +#### Creating and Editing Meeting + +We use `JavaScript` to create and edit `Meeting`. + +ABP's [TagHelper](https://abp.io/docs/latest/framework/ui/mvc-razor-pages/tag-helpers) can automatically create forms based on the model, it will generate corresponding HTML tags based on the attributes in the model. For `DateTime` and `DateTimeOffset` attributes, it will generate and initialize a [DateTimePicker](https://www.daterangepicker.com/) component. + +**CreateModal** and **EditModal** : + +```html + + + + + + + + + +``` + +```html + + + + + + + + + + +``` + +You can see that the time in the control has been converted to the current user's timezone. + +![](mvc-create.png) + +![](mvc-edit.png) + +When we submit the form, we need to convert the time to `UTC`. In the `JavaScript` of the `Create` and `Edit` pages, we use the `handleDatepicker` this `jQuery` extension method to handle time in the form, it internally gets the user's local time from the selector `input[type="hidden"][data-hidden-datepicker]`, and then uses the `abp.clock.normalizeToString` method to convert the date field in the form to the `ISO 8601` format `UTC` time string. + +> If the current application is not enabled for multi-timezone support, then the `abp.clock.normalizeToString` method will not convert the time, it will just convert to the ISO 8601 format time string without timezone. + +```js +var abp = abp || {}; +$(function () { + abp.modals.meetingCreate = function () { + var initModal = function (publicApi, args) { + var $form = publicApi.getForm(); + $form.find('button[type="submit"]').on('click', function (e) { + $form.handleDatepicker('input[type="hidden"][data-hidden-datepicker]'); + }); + }; + + return { + initModal: initModal + } + }; +}); +``` + +The requested data is as follows: + +```csharp +Request URL: Meetings/EditModal +Request Method: POST +Payload: + Id: 0803780b-3762-2af8-1c75-3a1895d59c89 + Meeting.Subject: ABP Developer Guide + Meeting.StartTime: 2025-03-01T09:30:00.000Z + Meeting.EndTime: 2025-03-01T10:30:00.000Z + Meeting.ActualStartTime: 2025-03-01T11:30:00.000Z + Meeting.CanceledTime: + Meeting.ReminderTime: 2025-03-01T12:30:00.000Z + Meeting.FollowUpTime: 2025-03-01T13:30:00.000Z + Meeting.Description: We will discuss the ABP developer guide. +``` + +![](mvc-post.png) + +In short, we use the `abp.clock.normalizeToLocaleString` method to display time, and use the `abp.clock.normalizeToString` method to modify the time to be submitted. If you submit data via `ajax`, please remember to use the `abp.clock.normalizeToString` method to convert time. + +### Handling Timezone in Blazor + +We cannot automatically complete some work in `Blazor UI`, we need to inject `IClock` and use the `ConvertToUserTime` and `ConvertToUtc` methods to display and create/update entities. + +Below is a complete `Meeting` page, please refer to the usage of `Clock` in it. + +```csharp +@page "/meetings" +@using Volo.Abp.Application.Dtos +@using Microsoft.Extensions.Localization +@using TimeZoneApp.Meetings +@using TimeZoneApp.Localization +@using TimeZoneApp.Permissions +@using Volo.Abp.AspNetCore.Components.Web +@inject IStringLocalizer L +@inject AbpBlazorMessageLocalizerHelper LH +@inherits AbpCrudPageBase + + + + + +

@L["Meetings"]

+
+ + @if (HasCreatePermission) + { + + } + +
+
+ + + + + + + + + + + + + + + @Clock.ConvertToUserTime(context.StartTime).ToString("yyyy-MM-dd HH:mm:ss") ➡️ @Clock.ConvertToUserTime(context.EndTime).ToString("yyyy-MM-dd HH:mm:ss") + + + + + @Clock.ConvertToUserTime(context.ActualStartTime).ToString("yyyy-MM-dd HH:mm:ss") + + + + + @(context.CanceledTime.HasValue ? Clock.ConvertToUserTime(context.CanceledTime.Value).ToString("yyyy-MM-dd HH:mm:ss") : "N/A") + + + + + @(Clock.ConvertToUserTime(context.ReminderTime).ToString("yyyy-MM-dd HH:mm:ss") ) + + + + + @(context.FollowUpTime.HasValue ? Clock.ConvertToUserTime(context.FollowUpTime.Value).ToString("yyyy-MM-dd HH:mm:ss") : "N/A") + + + + + + + +
+ + + +
+ + @L["NewMeeting"] + + + + + + + @L["Subject"] + + + + + + + + + @L["StartTime"] / @L["EndTime"] + + + + @L["ActualStartTime"] + + + + @L["CanceledTime"] + + + + @L["ReminderTime"] + + + + @L["FollowUpTime"] + + + + + @L["Description"] + + + + + + + + + + + + + +
+
+
+ + + +
+ + @EditingEntity.Subject + + + + + + + @L["Subject"] + + + + + + + + + @L["StartTime"] / @L["EndTime"] + + + + @L["ActualStartTime"] + + + + @L["CanceledTime"] + + + + @L["ReminderTime"] + + + + @L["FollowUpTime"] + + + + + @L["Description"] + + + + + + + + + + + + + +
+
+
+ + +@code { + IReadOnlyList SelectedDates; + + public Meeting() + { + CreatePolicyName = TimeZoneAppPermissions.Meetings.Create; + UpdatePolicyName = TimeZoneAppPermissions.Meetings.Edit; + DeletePolicyName = TimeZoneAppPermissions.Meetings.Delete; + } + + protected override async Task OpenCreateModalAsync() + { + await base.OpenCreateModalAsync(); + + var now = DateTime.Now; + SelectedDates = new List { now.Date.AddHours(10),now.Date.AddDays(7).AddHours(10) }; + NewEntity.ActualStartTime = now.Date.AddHours(11); + NewEntity.CanceledTime = now.Date.AddHours(12); + NewEntity.ReminderTime = now.Date.AddHours(13); + NewEntity.FollowUpTime = now.Date.AddHours(14); + } + + protected override Task OnCreatingEntityAsync() + { + if (SelectedDates.Count == 2 && SelectedDates[0].HasValue && SelectedDates[1].HasValue) + { + NewEntity.StartTime = Clock.ConvertToUtc(SelectedDates[0]!.Value); + NewEntity.EndTime = Clock.ConvertToUtc(SelectedDates[1]!.Value); + } + + NewEntity.ActualStartTime = Clock.ConvertToUtc(NewEntity.ActualStartTime); + NewEntity.CanceledTime = NewEntity.CanceledTime.HasValue ? Clock.ConvertToUtc(NewEntity.CanceledTime.Value) : null; + + NewEntity.ReminderTime = Clock.ConvertToUtc(NewEntity.ReminderTime.DateTime); + NewEntity.FollowUpTime = NewEntity.FollowUpTime.HasValue ? Clock.ConvertToUtc(NewEntity.FollowUpTime.Value.DateTime) : null; + + return Task.CompletedTask; + } + + protected override async Task OpenEditModalAsync(MeetingDto entity) + { + await base.OpenEditModalAsync(entity); + + SelectedDates = new List { Clock.ConvertToUserTime(EditingEntity.StartTime), Clock.ConvertToUserTime(EditingEntity.EndTime) }; + EditingEntity.ActualStartTime = Clock.ConvertToUserTime(EditingEntity.ActualStartTime); + EditingEntity.CanceledTime = EditingEntity.CanceledTime.HasValue ? Clock.ConvertToUserTime(EditingEntity.CanceledTime.Value) : null; + EditingEntity.ReminderTime = Clock.ConvertToUserTime(EditingEntity.ReminderTime); + EditingEntity.FollowUpTime = EditingEntity.FollowUpTime.HasValue ? Clock.ConvertToUserTime(EditingEntity.FollowUpTime.Value) : null; + } + + protected override Task OnUpdatingEntityAsync() + { + if (SelectedDates.Count == 2 && SelectedDates[0].HasValue && SelectedDates[1].HasValue) + { + EditingEntity.StartTime = Clock.ConvertToUtc(SelectedDates[0]!.Value); + EditingEntity.EndTime = Clock.ConvertToUtc(SelectedDates[1]!.Value); + } + + EditingEntity.ActualStartTime = Clock.ConvertToUtc(EditingEntity.ActualStartTime); + EditingEntity.CanceledTime = EditingEntity.CanceledTime.HasValue ? Clock.ConvertToUtc(EditingEntity.CanceledTime.Value) : null; + + return Task.CompletedTask; + } +} +``` + +![](blazor-list.png) + +![](blazor-create.png) + +![](blazor-edit.png) + +## Timezone Settings Change + +If the timezone settings change, then all times will be converted to the new timezone. For example, if the current timezone changes from `Europe/Istanbul` to `Europe/Berlin`, then all times will be converted to the `Europe/Berlin` timezone. + +![](berlin.png) + +`Europe/Istanbul`: + +![](auth-list-utc3.png) + +![](mvc-list-utc3.png) + +`Europe/Berlin`: + +![](auth-list-utc1.png) + +![](mvc-list-utc1.png) + +## Browser Timezone Detection + +When no timezone setting is configured, ABP's MVC, Blazor, and Angular applications will automatically detect the browser's timezone during initialization. The detected timezone is then stored in either the request's Cookie or Header. + +This functionality is implemented by the `UseAbpTimeZone` middleware, which follows a specific order to determine the appropriate timezone: + +1. First, it attempts to retrieve the timezone from the application/tenant/user settings +2. If no setting is found, it tries to get the timezone from the request information, including Cookie, Header, QueryString, and Form +3. Finally, if no timezone information is found, it falls back to using the server's timezone as the default + +> The timezone information is stored using the key `__timezone` + +## TimeZoneApp Source Code + +You can download and view the [TimeZoneApp source code](https://github.com/maliming/TimeZone) for detailed implementation. + +## Summary + +Through this article, we learned how to handle timezone in different types of UIs. I hope this article is helpful to you. If you have any questions, please contact me at any time. diff --git a/docs/en/Community-Articles/2025-03-24-How-to-Change-the-CurrentUser-in-ABP/POST.md b/docs/en/Community-Articles/2025-03-24-How-to-Change-the-CurrentUser-in-ABP/POST.md index b74aecdbe4..4213ad0e48 100644 --- a/docs/en/Community-Articles/2025-03-24-How-to-Change-the-CurrentUser-in-ABP/POST.md +++ b/docs/en/Community-Articles/2025-03-24-How-to-Change-the-CurrentUser-in-ABP/POST.md @@ -4,6 +4,12 @@ In this article, we'll explore the [`CurrentUser` service](https://abp.io/docs/latest/framework/infrastructure/current-user), its use cases, and how to change it when necessary. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Understanding the ICurrentUser Service The `ICurrentUser` interface is the primary service in ABP Framework for obtaining information about the logged-in user. It provides some key properties, such as `Id`, `UserName`, `TenantId`, `Roles` (roleNames), and more... @@ -108,6 +114,12 @@ Here's what the code does step by step: This pattern is particularly useful in background jobs, event handlers, or any scenario where you need to perform operations under a specific user's context, regardless of the actual authenticated user. +--- +> 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. +> 👉 Subscribe here → engincanveske.substack.com +> 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv +--- + ## Conclusion The `CurrentUser` service in ABP Framework provides a simple way to access information about the authenticated user. While it works automatically in most scenarios, there are cases where you need to explicitly change the current user identity, particularly in background processing scenarios. diff --git a/docs/en/Community-Articles/2025-04-20-IDX10204/POST.md b/docs/en/Community-Articles/2025-04-20-IDX10204/POST.md new file mode 100644 index 0000000000..5de0650d11 --- /dev/null +++ b/docs/en/Community-Articles/2025-04-20-IDX10204/POST.md @@ -0,0 +1,170 @@ +# Common Errors in JWT Bearer Authentication + +When implementing JWT Bearer authentication in an ABP(tiered) application, you might occasionally encounter errors starting with `IDX`. These errors are related to JWT Bearer Token validation and this article will help you understand and resolve them. + +## Enable JWT Bearer authentication + +Your API project usually contains the following code, which enables JWT Bearer authentication and makes it as the default authentication scheme. + +We simply configure the JWT's `Authority` and `Audience` properties, and it will work fine. + +```csharp +context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + options.Authority = "https://localhost:44301/"; //configuration["AuthServer:Authority"]; + options.Audience = "MyProjectName"; + }); +``` + +> `AddJwtBearer` and `AddAbpJwtBearer` will do the same thing, but `AddAbpJwtBearer` is recommended. + +## JWT authentication process + +Let's take a look at how the above code works. + +A JWT Token usually consists of three parts: `Header`, `Payload`, and `Signature`. + +- `Header`: Contains the type and signing algorithm of the token +- `Payload`: Contains the claims of the token, including `sub`, `aud`, `exp`, `iat`, `iss`, `jti`, `preferred_username`, `given_name`, `role`, `email`, etc. +- `Signature`: The cryptographic signature of the token used to verify its authenticity + +Here is an example of a JWT Token issued by `AuthServer(OpenIddict)`: + +The `Header` part: + +![JWT Header](header.png) + +The `Payload` part: + +![JWT Payload](payload.png) + +### TokenValidationParameters + +In the `JwtBearerOptions`, there is a `TokenValidationParameters` property, which is used to validate the JWT Token. + +The default implementation for JWT Token validation is `JsonWebTokenHandler`, which comes from the [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/) package. + +We didn't set the `TokenValidationParameters` property in the code above, so the default values below will be used: + +```csharp +//... +TokenValidationParameters.ValidateAudience = true +TokenValidationParameters.ValidAudience = "MyProjectName" +TokenValidationParameters.ValidAudiences = null + +TokenValidationParameters.ValidateIssuer = true +TokenValidationParameters.ValidIssuer = null +TokenValidationParameters.ValidIssuers = null +//... +``` + +### JWT Bearer Token Validation Process + +During JWT Bearer authentication, API website will get the token from the HTTP request and validate it. + +The `JsonWebTokenHandler` will get the `OpenID Connect` metadata from the `AuthServer`, it will be used in the validation process, the current metadata request address is: https://localhost:44301/.well-known/openid-configuration , it is a fixed address calculated from the `Authority` property. + +First, the token's Signature is verified using the public key obtained from `OpenID Connect` metadata(https://localhost:44301/.well-known/jwks). + +Then, the payload is validated. The payload is a JSON object containing essential information such as the `token type`, `expiration time`, `issuer`, and `audience` etc. + +Most of the validation problems we may encounter are payload validation failures, for example: + +#### Lifetime + +If the token in your request has expired, the validation will fail. You will see the exception information like `IDX10230` in the log. + +#### Audience + +The `ValidAudience` of `TokenValidationParameters` is `MyProjectName`, the `aud` in the payload of the token is also `MyProjectName`, if the token does not contain `aud` or the `aud` does not match, the validation will fail. You may see the exception information like `IDX10206`, `IDX10277` or `IDX10208`. + +> If the `ValidateAudience` of `TokenValidationParameters` is `false`, then the `aud` will not be validated. + +#### Issuer + +The default value of `TokenValidationParameters.ValidateIssuer` is `true`, it requires the token's payload to contain the `issuer` field, and it must match one of `TokenValidationParameters.ValidIssuer` or `TokenValidationParameters.ValidIssuers`. + +> The default value of `ValidIssuer` or `ValidIssuers` is `null`, it will use the `issuer` from the `OpenID Connect` metadata as the default value. + +1. If the token's payload does not contain the `issuer` field, you may see the error `IDX10211`. +2. If the API website cannot get the `OpenID Connect` metadata from AuthServer website, the validation will fail. You may see the error `IDX10204`, the full exception message is: `IDX10204: Unable to validate issuer. validationParameters.ValidIssuer is null or whitespace AND validationParameters.ValidIssuers is null or empty.` +3. If the `issuer` does not match, the validation will fail. You may see the error `IDX10205` in the log. + +> If the `ValidateIssuer` of `TokenValidationParameters` is `false`, then the `issuer` will not be validated. + +> Please note that `OpenIddict` will use the current HTTP request information as the value of `issuer`. If the AuthServer website is deployed behind a reverse proxy or similar deployment configurations, the `issuer` in the token may not be the value you expect. In this case, please specify it manually. + +```csharp +PreConfigure(serverBuilder => +{ + serverBuilder.SetIssuer("https://localhost:44301/"); +}); +``` + +## Troubleshooting + +To troubleshoot any `IDX` errors during JWT authentication, you can enable detailed logging by configuring the `identitymodel` logs as follows: + +```csharp +using System.Diagnostics.Tracing; +using Microsoft.IdentityModel.Logging; + +public class Program +{ + public async static Task Main(string[] args) + { + IdentityModelEventSource.ShowPII = true; + IdentityModelEventSource.Logger.LogLevel = EventLevel.Verbose; + var wilsonTextLogger = newTextWriterEventListener("Logs/identitymodel.txt"); + wilsonTextLogger.EnableEvents(IdentityModelEventSource.Logger, EventLevel.Verbose); + + //... + } +} +``` + +Additionally, you can enable `OpenIddict`'s `Verbose` logs for more detailed debugging information: + +```csharp +var loggerConfiguration = new LoggerConfiguration() + .MinimumLevel.Debug() + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + .MinimumLevel.Override("OpenIddict", LogEventLevel.Verbose) + .Enrich.FromLogContext() + .WriteTo.Async(c => c.File("Logs/logs.txt")) +``` + +## Summary + +For JWT authentication, you need to pay attention to the following key points: + +1. Ensure your API website can communicate with the AuthServer properly +2. Verify that the `aud` claim in your token matches the expected audience +3. Confirm that the `issuer` claim in your token is valid and matches the configuration + +You can customize the `JwtBearerOptions`'s `TokenValidationParameters` to modify the validation rules to meet your actual needs. + +For example, if your `issuer` needs to support multiple subdomains, you can use the [Owl.TokenWildcardIssuerValidator](https://github.com/maliming/Owl.TokenWildcardIssuerValidator) library to customize the validation. + +```csharp +services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + options.Authority = "https://abp.io"; + options.Audience = "abp_io"; + + options.TokenValidationParameters.IssuerValidator = TokenWildcardIssuerValidator.IssuerValidator; + options.TokenValidationParameters.ValidIssuers = new[] + { + "https://{0}.abp.io" + }; + }); +``` + +## References + +- [Configure JWT bearer authentication in ASP.NET Core]([https://learn.microsoft.com/en-us/aspnet/core/security/authentication/jwt-auth?view=aspnetcore-8.0](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/configure-jwt-bearer-authentication)) +- [OpenIddict](https://github.com/openiddict/openiddict-core) +- [IdentityModel](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) +- [Owl.TokenWildcardIssuerValidator](https://github.com/maliming/Owl.TokenWildcardIssuerValidator) diff --git a/docs/en/Community-Articles/2025-04-20-IDX10204/header.png b/docs/en/Community-Articles/2025-04-20-IDX10204/header.png new file mode 100644 index 0000000000..13109a4515 Binary files /dev/null and b/docs/en/Community-Articles/2025-04-20-IDX10204/header.png differ diff --git a/docs/en/Community-Articles/2025-04-20-IDX10204/payload.png b/docs/en/Community-Articles/2025-04-20-IDX10204/payload.png new file mode 100644 index 0000000000..04b927bbb2 Binary files /dev/null and b/docs/en/Community-Articles/2025-04-20-IDX10204/payload.png differ diff --git a/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/POST.md b/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/POST.md new file mode 100644 index 0000000000..f79fa21ce8 --- /dev/null +++ b/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/POST.md @@ -0,0 +1,262 @@ +# Using Microsoft AI Extensions Library and OpenAI to Summarize User Comments + +Either you are building an e-commerce application or a simple blog, **user comments** (about your products or blog posts) **can grow rapidly**, making it harder for users to get the gist of discussions at a glance. AI is a pretty good tool to solve the problem. By using AI, you can **summarize all the user comments** and show a single paragraph to your users, so they can easily understand the overall thought of users about the product or the blog post. + +In this tutorial, we’ll walk through a real-life implementation of using AI to summarize multiple user comments in an application. I will implement the solution based on ABP's **[CMS Kit](https://abp.io/docs/latest/modules/cms-kit)** library, as it already features a **[commenting system](https://abp.io/docs/latest/modules/cms-kit/comments)** and a [demo application](https://cms-kit-demo.abpdemo.com/) that displays user comments on **[gallery images](https://cms-kit-demo.abpdemo.com/image-gallery)** (it has not a comment summary feature yet, we will implement it in this tutorial). + +## A Screenshot + +Here, an example screenshot from the application with the comment summary feature: + +![comment-example](comment-example.png) + +## Cloning the Repository + +If you want to follow the development, you can clone the [CMS Kit Demo repository](https://github.com/abpframework/cms-kit-demo) to your computer and make it running by following the instructions on the [README file](https://github.com/abpframework/cms-kit-demo?tab=readme-ov-file#cms-kit-demo). + +I suggest to you to play a little with [the application](https://cms-kit-demo.abpdemo.com/) (create a new user for yourself, add some comments to the images in the gallery), so you understand how it works. + +## Preparing the Solution for AI + +I will use [Microsoft AI Extensions Library](https://learn.microsoft.com/en-us/dotnet/ai/ai-extensions) to use the AI features. It is an abstraction library that can work with multiple AI models and tools. I will use an OpenAI model in the demo. + +The first step is to add the [Microsoft.Extensions.AI.OpenAI](http://nuget.org/packages/Microsoft.Extensions.AI.OpenAI) NuGet package to the project: + +````bash +dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease +```` + +>The Microsoft AI Extensions Library was in preview at the time when I wrote this article. If it has a stable release now, you can remove the `--prerelease` parameter for the preceding command. + +We will store the OpenAI key and model name in user secrets. So, locate the root path of the CMS Kit project (`src\CmsKitDemo` folder) and execute the following commands in order in a command-line terminal: + +````bash +dotnet user-secrets init +dotnet user-secrets set OpenAIKey +dotnet user-secrets set ModelName +```` + +For this example, you need to have an [OpenAI API Key](https://platform.openai.com/). That's all. Now, we are ready to use the AI. + +## Implementing the AI Summarization + +Let's start from the most important point of this article: Comment summarization. I will create a class named `AiCommentSummarizer` to implement the summarization work. Here, the full content of that class: + +````csharp +using System.Text; +using Microsoft.Extensions.AI; +using OpenAI; +using Volo.Abp.DependencyInjection; + +namespace CmsKitDemo.Utils; + +public class AiCommentSummarizer : ITransientDependency +{ + private readonly IConfiguration _configuration; + + public AiCommentSummarizer(IConfiguration configuration) + { + _configuration = configuration; + } + + public async Task SummarizeAsync(string[] commentTexts) + { + // Get the model and key from the configuration + var aiModel = _configuration["ModelName"]; + var apiKey = _configuration["OpenAIKey"]; + + if (aiModel.IsNullOrEmpty() || apiKey.IsNullOrEmpty()) + { + return ""; + } + + // Create the IChatClient + var client = new OpenAIClient(apiKey) + .GetChatClient(aiModel) + .AsIChatClient(); + + // Create a prompt (input for AI) + var promptBuilder = new StringBuilder(); + + promptBuilder.AppendLine( + @"There are comments from different users of our website about an image. +We want to summarize the comments into a single comment. +Return a single comment with a maximum of 512 characters. Comments are separated by a newline character and given below." + ); + promptBuilder.AppendLine(); + + foreach (var commentText in commentTexts) + { + promptBuilder.AppendLine("User comment:"); + promptBuilder.AppendLine(commentText); + promptBuilder.AppendLine(); + } + + // Submit the prompt and get the response + var response = await client.GetResponseAsync( + promptBuilder.ToString(), + new ChatOptions { MaxOutputTokens = 1024 } + ); + + return response.Text; + } +} +```` + +That class is pretty simple and already decorated with comments: + +* First, we are getting the API Key and an OpenAI model name from user secrets. I used `gpt-4.1` as the model name, but you can use another available model. +* Then we are obtaining an `IChatClient` reference for OpenAI. `IChatClient` interface is an abstraction that is provided by the [Microsoft AI Extensions Library](https://learn.microsoft.com/en-us/dotnet/ai/ai-extensions) library, so we can implement rest of the code independently from OpenAI. +* Then we continue by building a proper prompt (input) for the AI operation. +* And finally we are using the AI to generate a response (the summary). + +At this point, all the AI-related work has already been done. The rest of this article explains how to integrate that summarization feature with the [CMS Kit Demo application](https://cms-kit-demo.abpdemo.com/). + +## Adding a CommentsSummary Property to the GalleryImage Entity + +The `GalleryImage` entity is used to represent an image on [the image gallery](https://cms-kit-demo.abpdemo.com/image-gallery). I add a `CommentsSummary` property to that entity: + +````csharp +public class GalleryImage : CreationAuditedAggregateRoot +{ + public string Description { get; set; } + + public Guid CoverImageMediaId { get; set; } + + public string CommentsSummary { get; set; } // The new property is here + + //... +} +```` + +Since the CMS Kit Demo application uses Entity Framework Core, I need to add a new database schema migration and update the database: + +````bash +dotnet ef migrations add Added_Summary_To_GalleryImage +dotnet ef database update +```` + +## Updating the Summary + +Great, we have a `GalleryImage.CommentsSummary` property now. But, how will it be updated when a users adds or removes a comment for an image? To implement that; + +* We will listen all the change events for user comments (when a user adds, removes or updates a comment). +* Whenever a comment is changed, we will find the related gallery image, retrieve all the user comments for this image, use the `AiCommentSummarizer` class to summarize all the comments. +* Finally, we wil set the `GalleryImage.CommentsSummary` property with the generated summary text. + +Here, the implementation: + +````csharp +using CmsKitDemo.Entities; +using CmsKitDemo.Utils; +using Microsoft.EntityFrameworkCore; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.EventBus; +using Volo.CmsKit.Comments; + +namespace CmsKitDemo.EventHandlers; + +public class GalleryImageCommentListener : + ILocalEventHandler>, + ITransientDependency +{ + private readonly IRepository _galleryImageRepository; + private readonly IRepository _commentRepository; + private readonly AiCommentSummarizer _aiCommentSummarizer; + + public GalleryImageCommentListener( + IRepository galleryImageRepository, + IRepository commentRepository, + AiCommentSummarizer aiCommentSummarizer) + { + _galleryImageRepository = galleryImageRepository; + _commentRepository = commentRepository; + _aiCommentSummarizer = aiCommentSummarizer; + } + + public async Task HandleEventAsync(EntityChangedEventData eventData) + { + var comment = eventData.Entity; + + //Here, we only interest in comments related to image gallery items + if (comment.EntityType != CmsKitDemoConsts.ImageGalleryEntityType) + { + return; + } + + if (!Guid.TryParse(comment.EntityId, out var galleryImageId)) + { + return; + } + + // Get the related image from database + var galleryImage = await _galleryImageRepository.FindAsync(galleryImageId); + if (galleryImage == null) + { + return; + } + + // Get all the comments related to the image + var queryable = await _commentRepository.GetQueryableAsync(); + var allCommentTexts = await queryable + .Where(c => c.EntityType == CmsKitDemoConsts.ImageGalleryEntityType && + c.EntityId == comment.EntityId) + .Select(c => c.Text) + .ToArrayAsync(); + + // Update the summary of comments related to the image + if (allCommentTexts.Length <= 0) + { + galleryImage.CommentsSummary = ""; + } + else + { + galleryImage.CommentsSummary = + await _aiCommentSummarizer.SummarizeAsync(allCommentTexts); + } + + // Update the image in database + await _galleryImageRepository.UpdateAsync(galleryImage); + } +} +```` + +Let's explain that class: + +* `GalleryImageCommentListener` implements the `ILocalEventHandler>` interface. In this way, it can handle an event whenever a `Comment` [entity](https://abp.io/docs/latest/framework/architecture/domain-driven-design/entities) is changed (created, updated or deleted). We are using ABP's [local event bus](https://abp.io/docs/latest/framework/infrastructure/event-bus/local) and its [pre-defined events](https://abp.io/docs/latest/framework/infrastructure/event-bus/local#pre-built-events). +* `HandleEventAsync` is called by the ABP Framework whenever a new `Comment` is created, or an existing `Comment` is deleted or updated. +* ABP's `Comment` entity is reusable and it can be associated with any kind of objects (blog posts, images, etc). So, first we are checking if this comment is related to an image gallery item. +* Then we are getting the related `GalleryImage` entity from the database. +* And getting all comments (including the new one) from the database for this image. +* Finally, using the `AiCommentSummarizer` class to generate the summary and set the `CommentsSummary` property. + +## Show the Summary Card on the UI + +Everything is ready on the backend. Now, we can show the summary text on the user interface. To do, that, I added `CommentsSummary` property also to the `GalleryImageDto` class and used it on the `/Pages/Gallery/Detail.cshtml` view: + +````csharp +@if (!Model.Image.CommentsSummary.IsNullOrEmpty()) +{ +
+
+
Summary of the User Comments
+

@Model.Image.CommentsSummary

+
+
+} +```` + +That section renders the following card on the user interface: + +![summary-card](summary-card.png) + +## Conclusion + +In this article, I demonstrated how to use [Microsoft AI Extensions Library](https://learn.microsoft.com/en-us/dotnet/ai/ai-extensions) to work with OpenAI for summarization of multiple user comments. I reused the [ABP's CMS Kit Demo application](https://github.com/abpframework/cms-kit-demo) to show it in a more real world example. + +## Source Code + +* [Source code of the CMS Kit Demo application](https://github.com/abpframework/cms-kit-demo) +* [All the changes made for this article (as a pull request)](https://github.com/abpframework/cms-kit-demo/pull/18) \ No newline at end of file diff --git a/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/comment-example.png b/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/comment-example.png new file mode 100644 index 0000000000..4ac33b60f9 Binary files /dev/null and b/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/comment-example.png differ diff --git a/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/summary-card.png b/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/summary-card.png new file mode 100644 index 0000000000..9a36f3cd35 Binary files /dev/null and b/docs/en/Community-Articles/2025-04-25-AI-Comment-Summarization/summary-card.png differ diff --git a/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/POST.md b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/POST.md new file mode 100644 index 0000000000..6007e5371f --- /dev/null +++ b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/POST.md @@ -0,0 +1,268 @@ +# Resolving Tenant from Route in ABP Framework + +The ABP Framework provides multi-tenancy support with various ways to resolve tenant information, including: Cookie, Header, Domain, Route, and more. + +This article will demonstrate how to resolve tenant information from the route. + +## Tenant Information in Routes + +In the ABP Framework, tenant information in routes is handled by the `RouteTenantResolveContributor`. + +Let's say your application is hosted at `https://abp.io` and you have a tenant named `acme`. You can add the `{__tenant}` variable to your controller or page routes like this: + +```csharp +[Route("{__tenant}/[Controller]")] +public class MyController : MyProjectNameController +{ + [HttpGet] + public IActionResult Get() + { + return Ok("Hello My Page"); + } +} +``` + +```cshtml +@page "{__tenant?}/mypage" +@model MyPageModel + + + +

My Page

+ + +``` + +When you access `https://abp.io/acme/my` or `https://abp.io/acme/mypage`, ABP will automatically resolve the tenant information from the route. + +## Adding __tenant to Global Routes + +While we've shown how to add `{__tenant}` to individual controllers or pages, you might want to add it globally to your entire application. Here's how to implement this: + +```cs +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Mvc.ApplicationModels; + +namespace MyCompanyName; + +public class AddTenantRouteToPages : IPageRouteModelConvention, IApplicationModelConvention +{ + public void Apply(PageRouteModel model) + { + var selectorCount = model.Selectors.Count; + var selectorModels = new List(); + for (var i = 0; i < selectorCount; i++) + { + var selector = model.Selectors[i]; + selectorModels.Add(new SelectorModel + { + AttributeRouteModel = new AttributeRouteModel + { + Template = AttributeRouteModel.CombineTemplates("{__tenant:regex(^[a-zA-Z0-9]+$)}", selector.AttributeRouteModel!.Template!.RemovePreFix("/")) + } + }); + } + foreach (var selectorModel in selectorModels) + { + model.Selectors.Add(selectorModel); + } + } +} + +public class AddTenantRouteToControllers :IApplicationModelConvention +{ + public void Apply(ApplicationModel application) + { + var controllers = application.Controllers; + foreach (var controller in controllers) + { + var selector = controller.Selectors.FirstOrDefault(); + if (selector == null || selector.AttributeRouteModel == null) + { + controller.Selectors.Add(new SelectorModel + { + AttributeRouteModel = new AttributeRouteModel + { + Template = AttributeRouteModel.CombineTemplates("{__tenant:regex(^[[a-zA-Z0-9]]+$)}", controller.ControllerName) + } + }); + controller.Selectors.Add(new SelectorModel + { + AttributeRouteModel = new AttributeRouteModel + { + Template = controller.ControllerName + } + }); + } + else + { + var template = selector.AttributeRouteModel?.Template; + template = template.IsNullOrWhiteSpace() ? "{__tenant:regex(^[[a-zA-Z0-9]]+$)}" : AttributeRouteModel.CombineTemplates("{__tenant:regex(^[[a-zA-Z0-9]]+$)}", template.RemovePreFix("/")); + controller.Selectors.Add(new SelectorModel + { + AttributeRouteModel = new AttributeRouteModel + { + Template = template + } + }); + } + } + } +} +``` + +Register the services: + +```cs +public override void ConfigureServices(ServiceConfigurationContext context) +{ + //... + + PostConfigure(options => + { + options.Conventions.Add(new AddTenantRouteToPages()); + }); + + PostConfigure(options => + { + options.Conventions.Add(new AddTenantRouteToControllers()); + }); + + // Configure cookie path to prevent authentication cookie loss + context.Services.ConfigureApplicationCookie(x => + { + x.Cookie.Path = "/"; + }); + //... +} +``` + +After implementing this, you'll notice that all controllers in your Swagger UI will have the `{__tenant}` route added: + +![Swagger UI](./swagger-ui.png) + +## Handling Navigation Links + +To ensure navigation links automatically include tenant information, we need to add middleware that dynamically adds the tenant to the PathBase: + +```cs +public override void OnApplicationInitialization(ApplicationInitializationContext context) +{ + //... + app.Use(async (httpContext, next) => + { + var tenantMatch = Regex.Match(httpContext.Request.Path, "^/([^/.]+)(?:/.*)?$"); + if (tenantMatch.Groups.Count > 1 && !string.IsNullOrEmpty(tenantMatch.Groups[1].Value)) + { + var tenantName = tenantMatch.Groups[1].Value; + if (!tenantName.IsNullOrWhiteSpace()) + { + var tenantStore = httpContext.RequestServices.GetRequiredService(); + var tenantNormalizer = httpContext.RequestServices.GetRequiredService(); + var tenantInfo = await tenantStore.FindAsync(tenantNormalizer.NormalizeName(tenantName)!); + if (tenantInfo != null) + { + if (httpContext.Request.Path.StartsWithSegments(new PathString(tenantName.EnsureStartsWith('/')), out var matchedPath, out var remainingPath)) + { + var originalPath = httpContext.Request.Path; + var originalPathBase = httpContext.Request.PathBase; + httpContext.Request.Path = remainingPath; + httpContext.Request.PathBase = originalPathBase.Add(matchedPath); + try + { + await next(httpContext); + } + finally + { + httpContext.Request.Path = originalPath; + httpContext.Request.PathBase = originalPathBase; + } + return; + } + } + } + } + + await next(httpContext); + }); + app.UseRouting(); + app.MapAbpStaticAssets(); + //... +} +``` + +![ui](ui.png) + +After setting the PathBase, we need to add a custom tenant resolver to extract tenant information from the `PathBase`: + +```cs +public class MyRouteTenantResolveContributor : RouteTenantResolveContributor +{ + public const string ContributorName = "MyRoute"; + + public override string Name => ContributorName; + + protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext) + { + var tenantId = httpContext.GetRouteValue(context.GetAbpAspNetCoreMultiTenancyOptions().TenantKey) ?? httpContext.Request.PathBase.ToString(); + var tenantIdStr = tenantId?.ToString()?.RemovePreFix("/"); + return Task.FromResult(!tenantIdStr.IsNullOrWhiteSpace() ? Convert.ToString(tenantIdStr) : null); + } +} +``` + +Register the MyRouteTenantResolveContributor with the ABP Framework: + +```cs +public override void ConfigureServices(ServiceConfigurationContext context) +{ + //... + Configure(options => + { + options.TenantResolvers.Add(new MyRouteTenantResolveContributor()); + }); + //... +} +``` + +### Modifying abp.appPath + +```csharp +public override void ConfigureServices(ServiceConfigurationContext context) +{ + //... + context.Services.AddOptions().Configure((options, rootServiceProvider) => + { + var currentTenant = rootServiceProvider.GetRequiredService(); + if (!currentTenant.Name.IsNullOrWhiteSpace()) + { + options.BaseUrl = currentTenant.Name.EnsureStartsWith('/').EnsureEndsWith('/'); + } + }); + + context.Services.RemoveAll(x => x.ServiceType == typeof(IOptions)); + context.Services.Add(ServiceDescriptor.Scoped(typeof(IOptions<>), typeof(OptionsManager<>))); + //... +} +``` + +Browser console output: + +```cs +> https://localhost:44303/acme/ +> abp.appPath +> '/acme/' +``` + +## Summary + +By following these steps, you can implement tenant resolution from routes in the ABP Framework and handle navigation links appropriately. This approach provides a clean and maintainable way to manage multi-tenancy in your application. + + +## References + +- [ABP Multi-Tenancy](https://docs.abp.io/en/abp/latest/Multi-Tenancy) +- [Routing in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing) +- [HTML base tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) diff --git a/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/cover.png b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/cover.png new file mode 100644 index 0000000000..ebd7978ac8 Binary files /dev/null and b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/cover.png differ diff --git a/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/swagger-ui.png b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/swagger-ui.png new file mode 100644 index 0000000000..72da9bd571 Binary files /dev/null and b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/swagger-ui.png differ diff --git a/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/ui.png b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/ui.png new file mode 100644 index 0000000000..3ae3f6650c Binary files /dev/null and b/docs/en/Community-Articles/2025-05-19-RouteTenantResolveContributor/ui.png differ diff --git a/docs/en/cli/index.md b/docs/en/cli/index.md index 44cab0caa4..02521e72cb 100644 --- a/docs/en/cli/index.md +++ b/docs/en/cli/index.md @@ -342,6 +342,7 @@ Note that this command can upgrade your solution from a previous version, and al * `--solution-name` or `-sn`: Specify the solution name. Search `*.sln` files in the directory by default. * `--check-all`: Check the new version of each package separately. Default is `false`. * `--version` or `-v`: Specifies the version to use for update. If not specified, latest version is used. +* * `--leptonx-version` or `-lv`: Specifies the LeptonX version to use for update. If not specified, latest version or the version that is compatible with `--version` argument is used. ### clean diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index fc3844317d..d031e87466 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -83,47 +83,59 @@ { "text": "Overview", "path": "tutorials/book-store", - "isIndex": true + "isIndex": true, + "isInSeries": true }, { "text": "1: Creating the Server Side", - "path": "tutorials/book-store/part-01.md" + "path": "tutorials/book-store/part-01.md", + "isInSeries": true + }, { "text": "2: The Book List Page", - "path": "tutorials/book-store/part-02.md" + "path": "tutorials/book-store/part-02.md", + "isInSeries": true }, { "text": "3: Creating, Updating and Deleting Books", - "path": "tutorials/book-store/part-03.md" + "path": "tutorials/book-store/part-03.md", + "isInSeries": true }, { "text": "4: Integration Tests", - "path": "tutorials/book-store/part-04.md" + "path": "tutorials/book-store/part-04.md", + "isInSeries": true }, { "text": "5: Authorization", - "path": "tutorials/book-store/part-05.md" + "path": "tutorials/book-store/part-05.md", + "isInSeries": true }, { "text": "6: Authors: Domain Layer", - "path": "tutorials/book-store/part-06.md" + "path": "tutorials/book-store/part-06.md", + "isInSeries": true }, { "text": "7: Authors: Database Integration", - "path": "tutorials/book-store/part-07.md" + "path": "tutorials/book-store/part-07.md", + "isInSeries": true }, { "text": "8: Authors: Application Layer", - "path": "tutorials/book-store/part-08.md" + "path": "tutorials/book-store/part-08.md", + "isInSeries": true }, { "text": "9: Authors: User Interface", - "path": "tutorials/book-store/part-09.md" + "path": "tutorials/book-store/part-09.md", + "isInSeries": true }, { "text": "10: Book to Author Relation", - "path": "tutorials/book-store/part-10.md" + "path": "tutorials/book-store/part-10.md", + "isInSeries": true } ] }, @@ -135,27 +147,33 @@ { "text": "Overview", "path": "tutorials/book-store-with-abp-suite", - "isIndex": true + "isIndex": true, + "isInSeries": true }, { "text": "1: Creating the Solution", - "path": "tutorials/book-store-with-abp-suite/part-01.md" + "path": "tutorials/book-store-with-abp-suite/part-01.md", + "isInSeries": true }, { "text": "2: Creating the Books", - "path": "tutorials/book-store-with-abp-suite/part-02.md" + "path": "tutorials/book-store-with-abp-suite/part-02.md", + "isInSeries": true }, { "text": "3: Creating the Authors", - "path": "tutorials/book-store-with-abp-suite/part-03.md" + "path": "tutorials/book-store-with-abp-suite/part-03.md", + "isInSeries": true }, { "text": "4: Book to Author Relation", - "path": "tutorials/book-store-with-abp-suite/part-04.md" + "path": "tutorials/book-store-with-abp-suite/part-04.md", + "isInSeries": true }, { "text": "5: Customizing the Generated Code", - "path": "tutorials/book-store-with-abp-suite/part-05.md" + "path": "tutorials/book-store-with-abp-suite/part-05.md", + "isInSeries": true } ] }, @@ -2070,19 +2088,23 @@ "items": [ { "text": "Deploy to Azure Web App Service", - "path": "solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md" + "path": "solution-templates/layered-web-application/deployment/azure-deployment/azure-deployment.md", + "isInSeries": true }, { "text": "Creating an Azure Web App Service Environment", - "path": "solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md" + "path": "solution-templates/layered-web-application/deployment/azure-deployment/step1-create-azure-resources.md", + "isInSeries": true }, { "text": "Customizing the Configuration of Your ABP Application", - "path": "solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md" + "path": "solution-templates/layered-web-application/deployment/azure-deployment/step2-configuration-application.md", + "isInSeries": true }, { "text": "Deploying Application With GitHub Actions", - "path": "solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md" + "path": "solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md", + "isInSeries": true } ] }, diff --git a/docs/en/framework/api-development/static-csharp-clients.md b/docs/en/framework/api-development/static-csharp-clients.md index c8eaea4231..b3cf80fcfc 100644 --- a/docs/en/framework/api-development/static-csharp-clients.md +++ b/docs/en/framework/api-development/static-csharp-clients.md @@ -47,7 +47,7 @@ Implement this class in your service application. You can use [auto API controll First, add [Volo.Abp.Http.Client](https://www.nuget.org/packages/Volo.Abp.Http.Client) nuget package to your client project: ```` -Install-Package Volo.Abp.Http.Client +dotnet add package Volo.Abp.Http.Client ```` Then add `AbpHttpClientModule` dependency to your module: diff --git a/docs/en/framework/api-development/swagger.md b/docs/en/framework/api-development/swagger.md index 1699e4d0d2..fb27bcf27b 100644 --- a/docs/en/framework/api-development/swagger.md +++ b/docs/en/framework/api-development/swagger.md @@ -29,7 +29,7 @@ If you want to manually install; 1. Add the [Volo.Abp.Swashbuckle](https://www.nuget.org/packages/Volo.Abp.Swashbuckle) NuGet package to your `Web` or `HttpApi.Host` project: - `Install-Package Volo.Abp.Swashbuckle` + `dotnet add package Volo.Abp.Swashbuckle` 2. Add the `AbpSwashbuckleModule` to the dependency list of your module: diff --git a/docs/en/framework/architecture/modularity/basics.md b/docs/en/framework/architecture/modularity/basics.md index f92e6edc3b..2b3aaad214 100644 --- a/docs/en/framework/architecture/modularity/basics.md +++ b/docs/en/framework/architecture/modularity/basics.md @@ -1,7 +1,5 @@ # Modularity -## Introduction - ABP was designed to support to build fully modular applications and systems where every module may have entities, services, database integration, APIs, UI components and so on; * This document introduces the basics of the module system. diff --git a/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md b/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md index 8a5b50652e..ac041895d7 100644 --- a/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md +++ b/docs/en/framework/architecture/modularity/extending/module-entity-extensions.md @@ -151,6 +151,17 @@ property => > Tip: Use `DefaultValueFactory` option only if the default value may change over the time (like `DateTime.Now` in this example). If it is a constant value, then use the `DefaultValue` option. +### DataTypeAttribute + +`DataTypeAttribute` is used to specify the type of the property. It is used to determine how to render the property on the user interface: + +```csharp +property => +{ + property.Attributes.Add(new DataTypeAttribute(DataType.Date)); +} +``` + ### Validation Entity extension system allows you to define validation for extension properties in a few ways. diff --git a/docs/en/framework/data/entity-framework-core/index.md b/docs/en/framework/data/entity-framework-core/index.md index 293e58daad..e462662410 100644 --- a/docs/en/framework/data/entity-framework-core/index.md +++ b/docs/en/framework/data/entity-framework-core/index.md @@ -142,24 +142,27 @@ Configure(options => Add actions for the `ConfigureConventions` and `OnModelCreating` methods of the `DbContext` as shown below: ````csharp -options.DefaultConventionAction = (dbContext, builder) => +Configure(options => { - // This action is called for ConfigureConventions method of all DbContexts. -}; + options.ConfigureDefaultConvention((dbContext, builder) => + { + // This action is called for ConfigureConventions method of all DbContexts. + }); -options.ConfigureConventions((dbContext, builder) => -{ - // This action is called for ConfigureConventions method of specific DbContext. -}); + options.ConfigureConventions((dbContext, builder) => + { + // This action is called for ConfigureConventions method of specific DbContext. + }); -options.DefaultOnModelCreatingAction = (dbContext, builder) => -{ - // This action is called for OnModelCreating method of all DbContexts. -}; + options.ConfigureDefaultOnModelCreating((dbContext, builder) => + { + // This action is called for OnModelCreating method of all DbContexts. + }); -options.ConfigureOnModelCreating((dbContext, builder) => -{ - // This action is called for OnModelCreating method of specific DbContext. + options.ConfigureOnModelCreating((dbContext, builder) => + { + // This action is called for OnModelCreating method of specific DbContext. + }); }); ```` @@ -755,7 +758,17 @@ public static class QADbContextModelCreatingExtensions > The `Object Extension` feature need the `Change Tracking`, which means you can't use the read-only repositories for the entities that have `extension properties(MapEfCoreProperty)`, Please see the [Repositories documentation](../../architecture/domain-driven-design/repositories.md) to learn the change tracking behavior. -See the "*ConfigureByConvention Method*" section above for more information. +See the **ConfigureByConvention Method** section above for more information. + +### Accessing Extra Properties(Shadow Properties) + +Extra properties stored in separate fields in the database are known as **Shadow Properties**. These properties are not defined in the entity class, but are part of the EF Core model and can be referenced in LINQ queries using the EF.Property static method + +```csharp +var query = (await GetQueryableAsync()).Where(x => EF.Property(x, "Title") == "MyTitle"); +``` + +See the [EF Core Shadow and Indexer Properties document](https://learn.microsoft.com/en-us/ef/core/modeling/shadow-properties) for more information. ## Advanced Topics @@ -962,4 +975,4 @@ public class MyCustomEfCoreBulkOperationProvider * [Entities](../../architecture/domain-driven-design/entities.md) * [Repositories](../../architecture/domain-driven-design/repositories.md) -* [Video tutorial](https://abp.io/video-courses/essentials/abp-ef-core) \ No newline at end of file +* [Video tutorial](https://abp.io/video-courses/essentials/abp-ef-core) diff --git a/docs/en/framework/data/entity-framework-core/postgresql.md b/docs/en/framework/data/entity-framework-core/postgresql.md index 8561e8bada..e25cc2c5fb 100644 --- a/docs/en/framework/data/entity-framework-core/postgresql.md +++ b/docs/en/framework/data/entity-framework-core/postgresql.md @@ -21,6 +21,15 @@ Find `UseSqlServer()` call in *YourProjectName*DbContextFactory.cs inside the `. > Depending on your solution structure, you may find more `UseSqlServer()` calls that needs to be changed. + +## EnableLegacyTimestampBehavior + +Please enable the `Npgsql.EnableLegacyTimestampBehavior` in `PreConfigureServices` method of your EF Core module and `DbContextFactory(IDesignTimeDbContextFactory)` class. + +`AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);` + +See https://www.npgsql.org/efcore/release-notes/6.0.html#opting-out-of-the-new-timestamp-mapping-logic + ## Change the Connection Strings PostgreSql connection strings are different than SQL Server connection strings. So, check all `appsettings.json` files in your solution and replace the connection strings inside them. See the [connectionstrings.com](https://www.connectionstrings.com/postgresql/) for details of PostgreSql connection string options. diff --git a/docs/en/framework/fundamentals/caching.md b/docs/en/framework/fundamentals/caching.md index bdef675f64..c1a720b394 100644 --- a/docs/en/framework/fundamentals/caching.md +++ b/docs/en/framework/fundamentals/caching.md @@ -270,7 +270,7 @@ Distributed cache service provides an interesting feature. Assume that you've up ### IDistributedCacheSerializer -`IDistributedCacheSerializer` service is used to serialize and deserialize the cache items. The default implementation is the `Utf8JsonDistributedCacheSerializer` class that uses `IJsonSerializer` service to convert objects to [JSON](../../json-serialization.md) and vice verse. Then it uses UTC8 encoding to convert the JSON string to a byte array which is accepted by the distributed cache. +`IDistributedCacheSerializer` service is used to serialize and deserialize the cache items. The default implementation is the `Utf8JsonDistributedCacheSerializer` class that uses `IJsonSerializer` service to convert objects to [JSON](../../json-serialization.md) and vice verse. Then it uses UTF8 encoding to convert the JSON string to a byte array which is accepted by the distributed cache. You can [replace](./dependency-injection.md) this service with your own implementation if you want to implement your own serialization logic. diff --git a/docs/en/framework/fundamentals/configuration.md b/docs/en/framework/fundamentals/configuration.md index 7611017b7e..997d347d2a 100644 --- a/docs/en/framework/fundamentals/configuration.md +++ b/docs/en/framework/fundamentals/configuration.md @@ -1,3 +1,52 @@ # Configuration -ASP.NET Core has an flexible and extensible key-value based configuration system. In fact, the configuration system is a part of Microsoft.Extensions libraries and it is independent from ASP.NET Core. That means it can be used in any type of application. See [Microsoft's documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) to learn the configuration infrastructure. ABP is 100% compatible with the configuration system. \ No newline at end of file +ASP.NET Core has an flexible and extensible key-value based configuration system. The configuration system is a part of Microsoft.Extensions libraries and it is independent from ASP.NET Core. That means it can be used in any type of application. + +See [Microsoft's documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) to learn the configuration infrastructure. ABP is 100% compatible with the configuration system. + +## Getting the Configuration + +You may need to get the `IConfiguration` service in various places in your codebase. The following section shows two common ways. + +### In Module Classes + +You typically need to get configuration while initializing your application. You can get the `IConfiguration` service using the `ServiceConfigurationContext.Configuration` property inside your [module class](../architecture/modularity/basics.md) as the following example: + +````csharp +public class MyAppModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + var connectionString = context.Configuration["ConnectionStrings:Default"]; + } +} +```` + +`context.Configuration` is a shortcut property for the `context.Services.GetConfiguration()` method. In general, prefer using `context.Configuration` for simplicity and readability when working within module classes. Use `context.Services.GetConfiguration()` in other contexts where you have an `IServiceCollection` object but do not have access to the `context.Configuration` property. (`IServiceCollection.GetConfiguration` is an extension method that can be used whenever you have an `IServiceCollection` object). + +### In Your Services + +You can directly [inject](dependency-injection.md) the `IConfiguration` service into your services: + +````csharp +public class MyService : ITransientDependency +{ + private readonly IConfiguration _configuration; + + public MyService(IConfiguration configuration) + { + _configuration = configuration; + } + + public string? GetConnectionString() + { + return _configuration["ConnectionStrings:Default"]; + } +} +```` + +## See Also + +* [Microsoft's Configuration Documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/) +* [The Options Pattern](options.md) + diff --git a/docs/en/framework/fundamentals/fluent-validation.md b/docs/en/framework/fundamentals/fluent-validation.md index d3af69bae9..207cddcbd3 100644 --- a/docs/en/framework/fundamentals/fluent-validation.md +++ b/docs/en/framework/fundamentals/fluent-validation.md @@ -21,7 +21,7 @@ If you want to manually install; 1. Add the [Volo.Abp.FluentValidation](https://www.nuget.org/packages/Volo.Abp.FluentValidation) NuGet package to your project: ```` - Install-Package Volo.Abp.FluentValidation + dotnet add package Volo.Abp.FluentValidation ```` 2. Add the `AbpFluentValidationModule` to the dependency list of your module: diff --git a/docs/en/framework/fundamentals/localization.md b/docs/en/framework/fundamentals/localization.md index 61118fd742..6e8a3f678a 100644 --- a/docs/en/framework/fundamentals/localization.md +++ b/docs/en/framework/fundamentals/localization.md @@ -248,6 +248,17 @@ namespace MyProject The `L` property is also available for some other base classes like `AbpController` and `AbpPageModel`. +## Supported Languages + +You can configure the `AbpLocalizationOptions`'s `Languages` property to add the languages supported by the application. The template already sets common languages, but you can add new languages as shown below: + +```csharp +Configure(options => +{ + options.Languages.Add(new LanguageInfo("uz", "uz", "Uzbek")); +}); +``` + ## The Client Side See the following documents to learn how to reuse the same localization texts in the JavaScript side; diff --git a/docs/en/framework/infrastructure/background-jobs/hangfire.md b/docs/en/framework/infrastructure/background-jobs/hangfire.md index 396c7498b5..f5991ee19b 100644 --- a/docs/en/framework/infrastructure/background-jobs/hangfire.md +++ b/docs/en/framework/infrastructure/background-jobs/hangfire.md @@ -25,7 +25,7 @@ If you want to manually install; 1. Add the [Volo.Abp.BackgroundJobs.HangFire](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.HangFire) NuGet package to your project: ```` - Install-Package Volo.Abp.BackgroundJobs.HangFire + dotnet add package Volo.Abp.BackgroundJobs.HangFire ```` 2. Add the `AbpBackgroundJobsHangfireModule` to the dependency list of your module: @@ -84,6 +84,24 @@ After you have installed these NuGet packages, you need to configure your projec } ```` +### AbpHangfireOptions + +You can configure the [BackgroundJobServerOptions](https://api.hangfire.io/html/T_Hangfire_BackgroundJobServerOptions.htm) of `AbpHangfireOptions` to customize the server. + +````csharp +Configure(options => +{ + // If no ServerOptions is set, ABP will use the default BackgroundJobServerOptions instance. + options.ServerOptions = new BackgroundJobServerOptions + { + Queues = ["default", "alpha"], + //... other properties + }; +}); +```` + +> You don't need to call `AddHangfireServer` method, ABP will use AbpHangfireOptions's `ServerOptions` to create a server. + ### Specifying Queue You can use the [`QueueAttribute`](https://docs.hangfire.io/en/latest/background-processing/configuring-queues.html) to specify the queue: diff --git a/docs/en/framework/infrastructure/background-jobs/quartz.md b/docs/en/framework/infrastructure/background-jobs/quartz.md index 93cf5d53bf..1b18fd36ae 100644 --- a/docs/en/framework/infrastructure/background-jobs/quartz.md +++ b/docs/en/framework/infrastructure/background-jobs/quartz.md @@ -25,7 +25,7 @@ If you want to manually install; 1. Add the [Volo.Abp.BackgroundJobs.Quartz](https://www.nuget.org/packages/Volo.Abp.BackgroundJobs.Quartz) NuGet package to your project: ```` - Install-Package Volo.Abp.BackgroundJobs.Quartz + dotnet add package Volo.Abp.BackgroundJobs.Quartz ```` 2. Add the `AbpBackgroundJobsQuartzModule` to the dependency list of your module: diff --git a/docs/en/framework/infrastructure/background-workers/hangfire.md b/docs/en/framework/infrastructure/background-workers/hangfire.md index 3ccbaf35bd..7fec8be273 100644 --- a/docs/en/framework/infrastructure/background-workers/hangfire.md +++ b/docs/en/framework/infrastructure/background-workers/hangfire.md @@ -23,7 +23,7 @@ If you want to manually install; 1. Add the [Volo.Abp.BackgroundWorkers.Hangfire](https://www.nuget.org/packages/Volo.Abp.BackgroundWorkers.Hangfire) NuGet package to your project: ```` - Install-Package Volo.Abp.BackgroundWorkers.Hangfire + dotnet add package Volo.Abp.BackgroundWorkers.Hangfire ```` 2. Add the `AbpBackgroundWorkersHangfireModule` to the dependency list of your module: @@ -84,6 +84,24 @@ After you have installed these NuGet packages, you need to configure your projec } ```` +### AbpHangfireOptions + +You can configure the [BackgroundJobServerOptions](https://api.hangfire.io/html/T_Hangfire_BackgroundJobServerOptions.htm) of `AbpHangfireOptions` to customize the server. + +````csharp +Configure(options => +{ + // If no ServerOptions is set, ABP will use the default BackgroundJobServerOptions instance. + options.ServerOptions = new BackgroundJobServerOptions + { + Queues = ["default", "alpha"], + //... other properties + }; +}); +```` + +> You don't need to call `AddHangfireServer` method, ABP will use AbpHangfireOptions's `ServerOptions` to create a server. + ## Create a Background Worker `HangfireBackgroundWorkerBase` is an easy way to create a background worker. diff --git a/docs/en/framework/infrastructure/background-workers/quartz.md b/docs/en/framework/infrastructure/background-workers/quartz.md index 663fe22a7f..909371adb0 100644 --- a/docs/en/framework/infrastructure/background-workers/quartz.md +++ b/docs/en/framework/infrastructure/background-workers/quartz.md @@ -21,7 +21,7 @@ If you want to manually install; 1. Add the [Volo.Abp.BackgroundWorkers.Quartz](https://www.nuget.org/packages/Volo.Abp.BackgroundWorkers.Quartz) NuGet package to your project: ```` - Install-Package Volo.Abp.BackgroundWorkers.Quartz + dotnet add package Volo.Abp.BackgroundWorkers.Quartz ```` 2. Add the `AbpBackgroundWorkersQuartzModule` to the dependency list of your module: diff --git a/docs/en/framework/infrastructure/current-user.md b/docs/en/framework/infrastructure/current-user.md index d9082633f5..aa1974ab92 100644 --- a/docs/en/framework/infrastructure/current-user.md +++ b/docs/en/framework/infrastructure/current-user.md @@ -138,7 +138,7 @@ public class MyAppService : ApplicationService { new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()), new Claim(AbpClaimTypes.UserName, "john"), - new Claim("MyCustomCliam", "42") + new Claim("Claim", "42") } ) ); diff --git a/docs/en/framework/infrastructure/event-bus/distributed/index.md b/docs/en/framework/infrastructure/event-bus/distributed/index.md index 9ed2121057..d56215fa12 100644 --- a/docs/en/framework/infrastructure/event-bus/distributed/index.md +++ b/docs/en/framework/infrastructure/event-bus/distributed/index.md @@ -297,10 +297,14 @@ Configure(options => options.AutoEventSelectors.Add( type => type.Namespace.StartsWith("MyProject.") ); + + //Ignore for a single entity + options.IgnoredEventSelectors.Add(); }); ```` -* The last one provides flexibility to decide if the events should be published for the given entity type. Returns `true` to accept a `Type`. +* The `type.Namespace.StartsWith("MyProject.")` provides flexibility to decide if the events should be published for the given entity type. Returns `true` to accept a `Type`. +* The `IgnoredEventSelectors` is used to ignore the events for the specified entity types. It is useful if you enabled for all entities and want to ignore for some entities. You can add more than one selector. If one of the selectors match for an entity type, then it is selected. diff --git a/docs/en/framework/infrastructure/features.md b/docs/en/framework/infrastructure/features.md index ef5d97bd91..a6bc52e48b 100644 --- a/docs/en/framework/infrastructure/features.md +++ b/docs/en/framework/infrastructure/features.md @@ -424,7 +424,7 @@ namespace FeaturesDemo return Task.FromResult("true"); } - return null; + return Task.FromResult(null); } } } diff --git a/docs/en/framework/infrastructure/image-manipulation.md b/docs/en/framework/infrastructure/image-manipulation.md index 7ab8dc562e..a1ee6e1584 100644 --- a/docs/en/framework/infrastructure/image-manipulation.md +++ b/docs/en/framework/infrastructure/image-manipulation.md @@ -22,7 +22,7 @@ If you want to manually install; 1. Add the [Volo.Abp.Imaging.Abstractions](https://www.nuget.org/packages/Volo.Abp.Imaging.Abstractions) NuGet package to your project: ``` -Install-Package Volo.Abp.Imaging.Abstractions +dotnet add package Volo.Abp.Imaging.Abstractions ``` 2. Add the `AbpImagingAbstractionsModule` to the dependency list of your module: @@ -240,7 +240,7 @@ If you want to manually install; 1. Add the [Volo.Abp.Imaging.MagickNet](https://www.nuget.org/packages/Volo.Abp.Imaging.MagickNet) NuGet package to your project: ``` -Install-Package Volo.Abp.Imaging.MagickNet +dotnet add package Volo.Abp.Imaging.MagickNet ``` 2. Add `AbpImagingMagickNetModule` to your [module](../architecture/modularity/basics.md)'s dependency list: @@ -284,7 +284,7 @@ If you want to manually install; 1. Add the [Volo.Abp.Imaging.ImageSharp](https://www.nuget.org/packages/Volo.Abp.Imaging.ImageSharp) NuGet package to your project: ``` -Install-Package Volo.Abp.Imaging.ImageSharp +dotnet add package Volo.Abp.Imaging.ImageSharp ``` 2. Add `AbpImagingImageSharpModule` to your [module](../architecture/modularity/basics.md)'s dependency list: @@ -350,7 +350,7 @@ If you want to manually install; 1. Add the [Volo.Abp.Imaging.AspNetCore](https://www.nuget.org/packages/Volo.Abp.Imaging.AspNetCore) NuGet package to your project: ``` -Install-Package Volo.Abp.Imaging.AspNetCore +dotnet add package Volo.Abp.Imaging.AspNetCore ``` 2. Add `AbpImagingAspNetCoreModule` to your [module](../architecture/modularity/basics.md)'s dependency list: diff --git a/docs/en/framework/infrastructure/sms-sending.md b/docs/en/framework/infrastructure/sms-sending.md index e6bc9135e5..ef2a86445f 100644 --- a/docs/en/framework/infrastructure/sms-sending.md +++ b/docs/en/framework/infrastructure/sms-sending.md @@ -26,7 +26,7 @@ If you want to manually install; 1. Add the [Volo.Abp.Sms](https://www.nuget.org/packages/Volo.Abp.Sms) NuGet package to your project: ``` -Install-Package Volo.Abp.Sms +dotnet add package Volo.Abp.Sms ``` 2. Add the `AbpSmsModule` to the dependency list of your module: diff --git a/docs/en/framework/infrastructure/string-encryption.md b/docs/en/framework/infrastructure/string-encryption.md index 5f37f1fa99..bb398425f6 100644 --- a/docs/en/framework/infrastructure/string-encryption.md +++ b/docs/en/framework/infrastructure/string-encryption.md @@ -22,7 +22,7 @@ If you want to manually install; 1. Add the [Volo.Abp.Security](https://www.nuget.org/packages/Volo.Abp.Security) NuGet package to your project: - `Install-Package Volo.Abp.Security` + `dotnet add package Volo.Abp.Security` 2. Add the `AbpSecurityModule` to the dependency list of your module: @@ -52,11 +52,11 @@ All encryption operations are included in `IStringEncryptionService`. You can in public string Encrypt(string value) { - // To enrcypt a value + // To encrypt a value return StringEncryptionService.Encrypt(value); } - public string Decrpyt(string value) + public string Decrypt(string value) { // To decrypt a value return StringEncryptionService.Decrypt(value); @@ -122,4 +122,4 @@ Configure(opts => - **Keysize:** This constant is used to determine the keysize of the encryption algorithm. - Default value: `256` \ No newline at end of file + Default value: `256` diff --git a/docs/en/framework/infrastructure/text-templating/razor.md b/docs/en/framework/infrastructure/text-templating/razor.md index 1d17d4337e..77db5467aa 100644 --- a/docs/en/framework/infrastructure/text-templating/razor.md +++ b/docs/en/framework/infrastructure/text-templating/razor.md @@ -25,7 +25,7 @@ If you want to manually install; 1. Add the [Volo.Abp.TextTemplating.Razor](https://www.nuget.org/packages/Volo.Abp.TextTemplating.Razor) NuGet package to your project: ```` -Install-Package Volo.Abp.TextTemplating.Razor +dotnet add package Volo.Abp.TextTemplating.Razor ```` 2. Add the `AbpTextTemplatingRazorModule` to the dependency list of your module: diff --git a/docs/en/framework/infrastructure/text-templating/scriban.md b/docs/en/framework/infrastructure/text-templating/scriban.md index bd54914411..99d160ce85 100644 --- a/docs/en/framework/infrastructure/text-templating/scriban.md +++ b/docs/en/framework/infrastructure/text-templating/scriban.md @@ -19,7 +19,7 @@ If you want to manually install; 1. Add the [Volo.Abp.TextTemplating.Scriban](https://www.nuget.org/packages/Volo.Abp.TextTemplating.Scriban) NuGet package to your project: ```` -Install-Package Volo.Abp.TextTemplating.Scriban +dotnet add package Volo.Abp.TextTemplating.Scriban ```` 2. Add the `AbpTextTemplatingScribanModule` to the dependency list of your module: diff --git a/docs/en/framework/infrastructure/timing.md b/docs/en/framework/infrastructure/timing.md index be5569f863..9f104b6336 100644 --- a/docs/en/framework/infrastructure/timing.md +++ b/docs/en/framework/infrastructure/timing.md @@ -88,6 +88,61 @@ var normalizedDateTime = Clock.Normalize(dateTime) `DisableDateTimeNormalization` attribute can be used to disable the normalization operation for desired classes or properties. +### DateTime Converter Between UTC and User's Time Zone + +#### Convert given UTC to user's time zone. + +`DateTime ConvertToUserTime(DateTime utcDateTime)` and `DateTimeOffset ConvertToUserTime(DateTimeOffset dateTimeOffset)` methods convert given UTC `DateTime` or `DateTimeOffset` to the user's time zone. + +> If `SupportsMultipleTimezone` is `false` or `dateTime.Kind` is not `Utc` or these is no timezone setting, it returns the given `DateTime` or `DateTimeOffset` without any changes. + +**Example:** + +If user's `TimeZone Setting` is `Europe/Istanbul` + +````csharp +// 2025-03-01T05:30:00Z +var utcTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc); + +var userTime = Clock.ConvertToUserTime(utcTime); + +// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours later. +userTime.Kind.ShouldBe(DateTimeKind.Unspecified); +userTime.ToString("O").ShouldBe("2025-03-01T08:30:00"); +```` + +````csharp +// 2025-03-01T05:30:00Z +var utcTime = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc), TimeSpan.Zero); + +var userTime = Clock.ConvertToUserTime(utcTime); + +// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours later. +userTime.Offset.ShouldBe(TimeSpan.FromHours(3)); +userTime.ToString("O").ShouldBe("2025-03-01T08:30:00.0000000+03:00"); +```` + +#### Converts given user's DateTime to UTC + +`DateTime ConvertToUtc(DateTime dateTime)` method convert given user's `DateTime` to UTC. + +> If `SupportsMultipleTimezone` is `false` or `dateTime.Kind` is `Utc` or these is no timezone setting, it returns the given `DateTime` without any changes. + +**Example:** + +If user's `TimeZone Setting` is `Europe/Istanbul` + +````csharp +// 2025-03-01T05:30:00 +var userTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified); //Same as Local + +var utcTime = Clock.ConvertToUtc(userTime); + +// Europe/Istanbul has 3 hours difference with UTC. So, the result will be 3 hours earlier. +utcTime.Kind.ShouldBe(DateTimeKind.Utc); +utcTime.ToString("O").ShouldBe("2025-03-01T02:30:00.0000000Z"); +```` + ### Other IClock Properties In addition to the `Now`, `IClock` service has the following properties: @@ -101,10 +156,24 @@ This section covers the ABP infrastructure related to managing time zones. ### TimeZone Setting -ABP defines **a setting**, named `Abp.Timing.TimeZone`, that can be used to set and get the time zone for a user, [tenant](../architecture/multi-tenancy) or globally for the application. The default value is `UTC`. +ABP defines **a setting**, named `Abp.Timing.TimeZone`, that can be used to set and get the time zone for a user, [tenant](../architecture/multi-tenancy) or globally for the application. The default value is empty, which means the application will use the server's time zone. + +You can change your host/tenant global time zone in the [Settings Management UI](../../modules/setting-management#setting-management-ui) + +The [Account Pro Module](../../modules/account-pro#Time-Zone-Setting) supports user to set their own time zone in the account settings page. See the [setting documentation](../infrastructure/settings.md) to learn more about the setting system. +### UseAbpTimeZone Middleware + +The `app.UseAbpTimeZone()` middleware is used to set the time zone for the current request. + + * It will get timezone from settings, the order is `User` -> `Tenant` -> `Application/Global`. + * If current request is anonymous, it will get timezone from the request header/cookie/form/query string. the key is `__timezone`. + +> If you want to get current timezone, you can inject `ICurrentTimezoneProvider` service. +> Please add this middleware after authentication. + ### ITimezoneProvider `ITimezoneProvider` is a service to simply convert [Windows Time Zone Id](https://support.microsoft.com/en-us/help/973627/microsoft-time-zone-index-values) values to [Iana Time Zone Name](https://www.iana.org/time-zones) values and vice verse. It also provides methods to get the list of these time zones and get a `TimeZoneInfo` with a given name. diff --git a/docs/en/framework/real-time/signalr.md b/docs/en/framework/real-time/signalr.md index d6cbbfbada..2d2710c77d 100644 --- a/docs/en/framework/real-time/signalr.md +++ b/docs/en/framework/real-time/signalr.md @@ -27,7 +27,7 @@ If you want to manually install; 1. Add the [Volo.Abp.AspNetCore.SignalR](https://www.nuget.org/packages/Volo.Abp.AspNetCore.SignalR) NuGet package to your project: ``` - Install-Package Volo.Abp.AspNetCore.SignalR + dotnet add package Volo.Abp.AspNetCore.SignalR ``` Or use the Visual Studio NuGet package management UI to install it. diff --git a/docs/en/framework/ui/maui/index.md b/docs/en/framework/ui/maui/index.md index 573278a060..28f74aa6a3 100644 --- a/docs/en/framework/ui/maui/index.md +++ b/docs/en/framework/ui/maui/index.md @@ -37,10 +37,15 @@ Open a command line terminal and run the `adb reverse` command to expose a port `adb reverse tcp:44305 tcp:44305` -> You should replace "44305" with the real port. -> You should run the command after starting the emulator. +> Replace `44305` with the port number your backend application is running on. +> +> Run this command **after** the Android emulator has started. -> If you don't have a separate installation of Android Debug Bridge, you can open it from **Visual Studio** by following toolbar menu `Tools` > `Android` > `Android Adb Command Prompt`. Android emulator has to be running for this operation. +> [!IMPORTANT] +> If your project uses a **tiered** or **microservice** architecture, ensure that both the **auth server** and all **remote service ports** are properly proxied using the `adb reverse` command. You can find all the required remote service ports and AuthServer configurations in your `YourProjectName.Maui/appsettings.json` file. + +> [!NOTE] +> If you don't have a separate installation of **Android Debug Bridge** _(adb)_, you can open it from **Visual Studio** by following toolbar menu `Tools` > `Android` > `Android Adb Command Prompt`. Android emulator has to be running for this operation. ### iOS diff --git a/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md b/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md index bc3b7d8fc2..c279f685c0 100644 --- a/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md +++ b/docs/en/framework/ui/mvc-razor-pages/customization-user-interface.md @@ -89,7 +89,10 @@ This example overrides the **login page** defined by the [Account Module](../../ Create a page model class deriving from the ` LoginModel ` (defined in the ` Volo.Abp.Account.Web.Pages.Account ` namespace): +> If you are using the `AbpAccountWebOpenIddictModule` or `AbpAccountPublicWebOpenIddictModule`, the base class is `OpenIddictSupportedLoginModel` instead of `LoginModel`. And you should change the `ExposeServices` attribute to `[ExposeServices(typeof (MyLoginModel), typeof(OpenIddictSupportedLoginModel), typeof(LoginModel))]` + ````csharp +[ExposeServices(typeof (MyLoginModel), typeof(LoginModel))] public class MyLoginModel : LoginModel { public MyLoginModel( @@ -114,8 +117,6 @@ public class MyLoginModel : LoginModel You can override any method or add new properties/methods if needed. -> Notice that we didn't use `[Dependency(ReplaceServices = true)]` or `[ExposeServices(typeof(LoginModel))]` since we don't want to replace the existing class in the dependency injection, we define a new one. - Copy `Login.cshtml` file into your solution as just described above. Change the **@model** directive to point to the `MyLoginModel`: ````xml diff --git a/docs/en/get-started/empty-aspnet-core-application.md b/docs/en/get-started/empty-aspnet-core-application.md index b0457db71b..95861719ce 100644 --- a/docs/en/get-started/empty-aspnet-core-application.md +++ b/docs/en/get-started/empty-aspnet-core-application.md @@ -104,7 +104,7 @@ Replacing ASP.NET Core's DI system by Autofac and integrating to ABP is pretty e 1. Install [Volo.Abp.Autofac](https://www.nuget.org/packages/Volo.Abp.Autofac) package ```` -Install-Package Volo.Abp.Autofac +dotnet add package Volo.Abp.Autofac ```` 2. Add the ``AbpAutofacModule`` Dependency diff --git a/docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png b/docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png index eb6c95e5bb..0f64d49a3b 100644 Binary files a/docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png and b/docs/en/get-started/images/abp-studio-no-layers-new-solution-dialog-ui-framework-0.9.13.png differ diff --git a/docs/en/get-started/single-layer-web-application.md b/docs/en/get-started/single-layer-web-application.md index 67d840d768..5c0a256c42 100644 --- a/docs/en/get-started/single-layer-web-application.md +++ b/docs/en/get-started/single-layer-web-application.md @@ -3,7 +3,7 @@ ````json //[doc-params] { - "UI": ["MVC", "Blazor", "BlazorServer", "NG"], + "UI": ["MVC", "Blazor", "BlazorServer", "BlazorWebApp", "NG"], "DB": ["EF", "Mongo"] } ```` diff --git a/docs/en/images/account-pro-time-zone-setting.png b/docs/en/images/account-pro-time-zone-setting.png new file mode 100644 index 0000000000..687ad7db70 Binary files /dev/null and b/docs/en/images/account-pro-time-zone-setting.png differ diff --git a/docs/en/images/samples-cms-kit.png b/docs/en/images/samples-cms-kit.png new file mode 100644 index 0000000000..0c4e3e5877 Binary files /dev/null and b/docs/en/images/samples-cms-kit.png differ diff --git a/docs/en/images/samples-easycrm.png b/docs/en/images/samples-easycrm.png new file mode 100644 index 0000000000..72924ae3e7 Binary files /dev/null and b/docs/en/images/samples-easycrm.png differ diff --git a/docs/en/images/samples-eshoponabp.png b/docs/en/images/samples-eshoponabp.png new file mode 100644 index 0000000000..f8e22fff7d Binary files /dev/null and b/docs/en/images/samples-eshoponabp.png differ diff --git a/docs/en/images/samples-eventhub.png b/docs/en/images/samples-eventhub.png new file mode 100644 index 0000000000..548412d62c Binary files /dev/null and b/docs/en/images/samples-eventhub.png differ diff --git a/docs/en/images/setting-management-email-ui.png b/docs/en/images/setting-management-email-ui.png index ab26a1d180..f02e8cd1c4 100644 Binary files a/docs/en/images/setting-management-email-ui.png and b/docs/en/images/setting-management-email-ui.png differ diff --git a/docs/en/images/setting-management-feature-management-ui.png b/docs/en/images/setting-management-feature-management-ui.png new file mode 100644 index 0000000000..b534fe830b Binary files /dev/null and b/docs/en/images/setting-management-feature-management-ui.png differ diff --git a/docs/en/images/setting-management-time-zone-ui.png b/docs/en/images/setting-management-time-zone-ui.png new file mode 100644 index 0000000000..fe65256ab5 Binary files /dev/null and b/docs/en/images/setting-management-time-zone-ui.png differ diff --git a/docs/en/modules/account-pro.md b/docs/en/modules/account-pro.md index 4ccc8b316a..c53a6f24ec 100644 --- a/docs/en/modules/account-pro.md +++ b/docs/en/modules/account-pro.md @@ -273,6 +273,12 @@ Users who register via both local registration and external/social login using t ![require-local-password-on-social-account-linking](../images/require-local-password-on-social-account-linking.png) +### Time Zone Setting + +Users can to set their own time zone in the account settings page if application is [supports multiple timezones](../framework/infrastructure/timing.md#clock-options). + +![account-pro-time-zone-setting](../images/account-pro-time-zone-setting.png) + ## Internals ### Settings diff --git a/docs/en/modules/cms-kit-pro/url-forwarding.md b/docs/en/modules/cms-kit-pro/url-forwarding.md index a059ef1305..10ca0a7f98 100644 --- a/docs/en/modules/cms-kit-pro/url-forwarding.md +++ b/docs/en/modules/cms-kit-pro/url-forwarding.md @@ -37,6 +37,20 @@ You can create new forwardings or update/delete existing ones, in the admin side ![url-forwarding-page](../../images/url-forwarding-page.png) + +## Options + +### ShortenedUrlCacheOptions + +`ShortenedUrlCacheOptions` is used to configure the cache settings for the URL forwarding system. Example: + +```csharp +Configure(options => +{ + options.CacheAllOnStartup = true; // Cache all shortened URLs on startup +}); +``` + # Internals ## Domain Layer diff --git a/docs/en/modules/docs.md b/docs/en/modules/docs.md index 69de3362a6..b564980ba3 100644 --- a/docs/en/modules/docs.md +++ b/docs/en/modules/docs.md @@ -73,25 +73,25 @@ Or you can also manually install nuget package to each project: * Install [Volo.Docs.Domain](https://www.nuget.org/packages/Volo.Docs.Domain/) nuget package to `Acme.MyProject.Domain` project. ```bash - Install-Package Volo.Docs.Domain + dotnet add package Volo.Docs.Domain ``` * Install [Volo.Docs.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Docs.EntityFrameworkCore/) nuget package to `Acme.MyProject.EntityFrameworkCore` project. ```bash - Install-Package Volo.Docs.EntityFrameworkCore + dotnet add package Volo.Docs.EntityFrameworkCore ``` * Install [Volo.Docs.Application](https://www.nuget.org/packages/Volo.Docs.Application/) nuget package to `Acme.MyProject.Application` project. ```bash - Install-Package Volo.Docs.Application + dotnet add package Volo.Docs.Application ``` * Install [Volo.Docs.Web](https://www.nuget.org/packages/Volo.Docs.Domain/) nuget package to `Acme.MyProject.Web` project. ```bash - Install-Package Volo.Docs.Web + dotnet add package Volo.Docs.Web ``` ##### 3.2.1- Adding Module Dependencies diff --git a/docs/en/modules/gdpr.md b/docs/en/modules/gdpr.md index c94fcbb4a0..bef763a41a 100644 --- a/docs/en/modules/gdpr.md +++ b/docs/en/modules/gdpr.md @@ -260,9 +260,11 @@ If you want to override the texts in the Cookie Consent component, you just need > Refer to the [Localization documentation](../framework/fundamentals/localization.md) for more info about defining localization resources and overriding existing localization entries that comes from pre-built modules. -### Configuring the Cookie Consent +### Configuring Cookie Consent -You can add Cookie Consent to your application by configuring the `AddAbpCookieConsent` in your module class as below: +To enable cookie consent in your application, follow these two steps: + +**1. Configure the service in your module class (inside the `ConfigureServices` method):** ```csharp context.Services.AddAbpCookieConsent(options => @@ -273,4 +275,23 @@ context.Services.AddAbpCookieConsent(options => }); ``` -After configuring the `AddAbpCookieConsent` and setting it enabled, a cookie consent text will be prepared according to the options and a cookie consent banner will be seen at the bottom of the page. Thus, the users of the application will be informed about the Cookie Policy and Privacy Policy of the company/application. +**2. Add the middleware (`UseAbpCookieConsent`) to the request pipeline (in the `OnApplicationInitialization` method):** + +```diff +public override void OnApplicationInitialization(ApplicationInitializationContenxt context) +{ + var app = context.GetApplicationBuilder(); + //... + ++ app.UseAbpCookieConsent(); + app.UseCorrelationId(); + app.UseRouting(); + app.MapAbpStaticAssets(); + app.UseAbpSecurityHeaders(); + app.UseAuthentication(); + + //... +} +``` + +Once configured, a cookie consent banner will be shown at the bottom of the page. It includes links to your _Cookie Policy_ and _Privacy Policy_, helping inform users and support GDPR compliance. diff --git a/docs/en/modules/language-management.md b/docs/en/modules/language-management.md index 77490f28ef..62327378a4 100644 --- a/docs/en/modules/language-management.md +++ b/docs/en/modules/language-management.md @@ -62,7 +62,7 @@ This module adds some initial data (see [the data seed system](../framework/infr * Creates language records configured using `AbpLocalizationOptions`. -If you want to change the seeded language list, see the next section. +If you want to change the seeded language list, see the [Localization](../framework/fundamentals/localization.md#Supported-Languages) document. ## Internals @@ -77,6 +77,11 @@ This module follows the [Entity Best Practices & Conventions](../framework/archi * `Language` (aggregate root): Represents a language in the system. * `LanguageText` (aggregate root): Represents a language text in the system. +##### Dynamic Localization + +* `LocalizationResourceRecord` (aggregate root): Represents a localization resource in the system. +* `LocalizationTextRecord` (aggregate root): Represents all texts of a localization resource in the system. + #### Repositories This module follows the [Repository Best Practices & Conventions](../framework/architecture/best-practices/repositories.md) guide. @@ -85,6 +90,8 @@ Following custom repositories are defined for this module: * `ILanguageRepository` * `ILanguageTextRepository` +* `ILocalizationResourceRecordRepository` +* `ILocalizationTextRecordRepository` #### Domain Services @@ -121,6 +128,8 @@ See the [connection strings](../framework/fundamentals/connection-strings.md) do * **AbpLanguages** * **AbpLanguageTexts** +* **AbpLocalizationResources** +* **AbpLocalizationTexts** #### MongoDB @@ -128,6 +137,8 @@ See the [connection strings](../framework/fundamentals/connection-strings.md) do * **AbpLanguages** * **AbpLanguageTexts** +* **AbpLocalizationResources** +* **AbpLocalizationTexts** ### Permissions diff --git a/docs/en/modules/payment-custom-gateway.md b/docs/en/modules/payment-custom-gateway.md index 40cd073da6..cdf847b528 100644 --- a/docs/en/modules/payment-custom-gateway.md +++ b/docs/en/modules/payment-custom-gateway.md @@ -6,7 +6,7 @@ This document explains creating custom a payment gateway that's different than t ## Creating Core Operations -- Create **MyPaymentGateway.cs** and implement `IPaymentGateway` +- Create **MyPaymentGateway.cs** in the **Domain** layer of your project and implement `IPaymentGateway`. ```csharp public class MyPaymentGateway : IPaymentGateway, ITransientDependency @@ -57,7 +57,7 @@ This document explains creating custom a payment gateway that's different than t } ``` -- You should configure your gateway in `PaymentOptions` +- You should also configure `PaymentOptions` for your gateway in the **Domain** layer of your project as shown below. ```csharp Configure(options => @@ -119,7 +119,7 @@ There are 2 types of pages that are supported by default. You can define a pre-p

Operation Done

``` -- Configure your pages in `PaymentWebOptions` +- Configure your pages using `PaymentWebOptions` in **Web** layer of your project. ```csharp Configure(options => diff --git a/docs/en/modules/setting-management.md b/docs/en/modules/setting-management.md index 32dd52f4b6..842233e8b4 100644 --- a/docs/en/modules/setting-management.md +++ b/docs/en/modules/setting-management.md @@ -118,12 +118,16 @@ The order of the providers are important. Providers are executed in the reverse ## Setting Management UI -Setting Mangement module provided the email setting UI by default. +Setting Mangement module provided the Email setting, Feature management and Timezone setting UI by default. ![EmailSettingUi](../images/setting-management-email-ui.png) > You can click the Send test email button to send a test email to check your email settings. +![FeatureManagementUi](../images/setting-management-feature-management-ui.png) + +![TimeZoneSettingUi](../images/setting-management-time-zone-ui.png) + Setting it is extensible; You can add your tabs to this page for your application settings. ### MVC UI diff --git a/docs/en/modules/virtual-file-explorer.md b/docs/en/modules/virtual-file-explorer.md index 21bccfd999..3157198c30 100644 --- a/docs/en/modules/virtual-file-explorer.md +++ b/docs/en/modules/virtual-file-explorer.md @@ -24,7 +24,7 @@ Or you can also manually install nuget package to `Acme.MyProject.Web` project: * Install [Volo.Abp.VirtualFileExplorer.Web](https://www.nuget.org/packages/Volo.Abp.VirtualFileExplorer.Web/) nuget package to `Acme.MyProject.Web` project. - `Install-Package Volo.Abp.VirtualFileExplorer.Web` + `dotnet add package Volo.Abp.VirtualFileExplorer.Web` ##### 2.1- Adding Module Dependencies diff --git a/docs/en/release-info/migration-guides/abp-8-2.md b/docs/en/release-info/migration-guides/abp-8-2.md index 15de922d4f..5f811da2d4 100644 --- a/docs/en/release-info/migration-guides/abp-8-2.md +++ b/docs/en/release-info/migration-guides/abp-8-2.md @@ -28,6 +28,7 @@ With this version on, ABP Framework allows you to use single blog mode, without * `Volo.Blogging.Pages.Members` -> `Volo.Blogging.Pages.Blogs.Members` (members folder) > If you haven't overridden the pages above, then you don't need to make any additional changes. See [#19418](https://github.com/abpframework/abp/pull/19418) for more information. + ## Removed `FlagIcon` property from the `ILanguageInfo` The `FlagIcon` property has been removed from the `ILanguageInfo` interface since we removed the flag icon library in the earlier versions from all of our themes and none of them using it now. @@ -57,11 +58,20 @@ In this version, the Angular UI has been updated to use the Angular version 17.3 The **Session Management** feature allows you to prevent concurrent login and manage user sessions. -In this version, a new entity called `IdentitySession` has been added to the framework and you should create a new migration and apply it to your database. +In this version, a new entity called `IdentitySession` has been added to the framework and you need to add new `DbSet` to your `DbContext` class if it implements `IIdentityDbContext` interface. + +```csharp +public class YourDbContext : AbpDbContext, IIdentityDbContext +{ + public DbSet Sessions { get; set; } +} +``` + +You should also create a new migration and apply it to your database. ## Upgraded NuGet Dependencies -You can see the following list of NuGet libraries that have been upgraded with this release, if you are using one of these packages explicitly, you may consider upgrading them in your solution: +You can see the following list of NuGet libraries that have been upgraded with this release, **if you are using one of these packages explicitly**, you may consider upgrading them in your solution, especially **Microsoft.IdentityModel.*** packages: | Package | Old Version | New Version | | ---------------------------------------------------------- | ----------- | ----------- | diff --git a/docs/en/release-info/release-notes.md b/docs/en/release-info/release-notes.md index 166dd03fc4..4c6bec206e 100644 --- a/docs/en/release-info/release-notes.md +++ b/docs/en/release-info/release-notes.md @@ -1,8 +1,12 @@ # Release Notes -This document contains **brief release notes** for each release. Release notes only include **major features** and **visible enhancements**. They don't include all the development done in the related version. To see raw and detailed change logs for every release, please check the related milestone and [the change logs page](https://abp.io/pro-releases) (only for paid license holders). +This document contains **brief release notes** for each release. Release notes only include **major features** and **visible enhancements**. They don't include all the development done in the related version. + +Also see the following notes about ABP releases: + +* [ABP Studio release notes](../studio/release-notes.md) +* [Change logs for ABP pro packages](https://abp.io/pro-releases) -> If you want to read the release notes for each ABP Studio release, check it out from [here](../studio/release-notes.md). ## 9.2 (2025-03-25) @@ -15,7 +19,7 @@ This is currently a RC (release-candidate) and you can see the detailed **[blog * Identity Pro Module: Require Email Verification to Register * Switching users during OAuth login -## 9.1 (2025-01-16) +## 9.1 (2025-03-05) See the detailed **[blog post / announcement](https://abp.io/community/articles/abp.io-platform-9.1-final-has-been-released-h96a56qa)** for the v9.1 release. diff --git a/docs/en/samples/index.md b/docs/en/samples/index.md index 6aea3d3fa5..39512d0134 100644 --- a/docs/en/samples/index.md +++ b/docs/en/samples/index.md @@ -9,6 +9,8 @@ A reference application built with ABP. It implements the Domain Driven Design w * [Live demo](https://www.openeventhub.com/) * [Source code](https://github.com/abpframework/eventhub) +![samples-event-hub](../images/samples-eventhub.png) + ## eShopOnAbp > ⚠️ **Important Notice** @@ -18,6 +20,8 @@ Reference microservice solution built with ABP and .NET. * [Source code](https://github.com/abpframework/eShopOnAbp) +![eshoponabp](../images/samples-eshoponabp.png) + ## CMS Kit Demo A minimal example website built with the [CMS Kit module](../modules/cms-kit/index.md). @@ -25,6 +29,8 @@ A minimal example website built with the [CMS Kit module](../modules/cms-kit/ind * [Live demo](https://cms-kit-demo.abpdemo.com/) * [Source code](https://github.com/abpframework/cms-kit-demo) +![samples-cms-kit](../images/samples-cms-kit.png) + ## Easy CRM A middle-size CRM application built with ABP. @@ -32,6 +38,8 @@ A middle-size CRM application built with ABP. * [Live demo](http://easycrm.abp.io/) * [Click here](easy-crm.md) to see the details and download the source code. +![samples-easy-crm](../images/samples-easycrm.png) + ## Book Store A simple CRUD application to show basic principles of developing an application with ABP. The same sample was implemented with different technologies and different modules: diff --git a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md index a9ec807c64..14f2a48d66 100644 --- a/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md +++ b/docs/en/solution-templates/layered-web-application/deployment/azure-deployment/step3-deployment-github-action.md @@ -480,7 +480,7 @@ push: workflow_dispatch: jobs: -build: + build: runs-on: ubuntu-latest steps: 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 3d33cbd7a1..0de00c8d35 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 @@ -283,6 +283,34 @@ See: - https://learn.microsoft.com/en-us/aspnet/web-api/overview/testing-and-debugging/troubleshooting-http-405-errors-after-publishing-web-api-applications#resolve-http-405-errors - https://learn.microsoft.com/en-us/troubleshoot/developer/webapps/iis/site-behavior-performance/http-error-405-website#resolution-for-cause-3 +## Publish the Application(s) as IIS sub-application + +If your MVC application is a sub-application, you need to set the `BaseUrl` property of `AbpThemingOptions` to the sub-application’s path. The `BaseUrl` is used to configure the `base` element in the `head` section of the layout page. + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + Configure(options => + { + options.BaseUrl = "/myapp/"; + }); +} +``` + +```html + + + + ... + + + ... + + +``` + +For Blazor applications, you can to set the `base` tag in the `App.razor` file instead of configure `AbpThemingOptions`. + ## 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. diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md index ef498fcac5..cfb8e9fb61 100644 --- a/docs/en/studio/release-notes.md +++ b/docs/en/studio/release-notes.md @@ -2,6 +2,19 @@ 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.26 (2025-04-30) + +* Fixed the issue where C# applications would not stop when requested. +* Added idle session timeout feature to Blazor WebAssembly applications. +* Added “Setup as a modular solution” option to application startup templates. +* Automatically added remote service base URL after generating C# proxies. +* Configured Helm charts for Kubernetes health check endpoints. +* Fixed auditing issue in Blazor WebAssembly applications. +* Fixed login error after registering a new user in Blazor WebApp. +* Implemented password login flow in Studio CLI. +* Supported non-root user mode in Docker Compose configurations. +* Upgraded templates to version `9.1.1`. + ## 0.9.25 (2025-03-12) * Added ready/health check for solution runner. diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md index cd82da602a..88d9be25fe 100644 --- a/docs/en/studio/version-mapping.md +++ b/docs/en/studio/version-mapping.md @@ -4,6 +4,7 @@ This document provides a general overview of the relationship between various ve | **ABP Studio Version** | **ABP Version of Startup Template** | |------------------------|---------------------------| +| 0.9.26 | 9.1.1 | | 0.9.24 - 0.9.25 | 9.1.0 | | 0.9.22 - 0.9.23 | 9.0.4 | | 0.9.20 - 0.9.21 | 9.0.3 | diff --git a/docs/en/tutorials/book-store/part-09.md b/docs/en/tutorials/book-store/part-09.md index 5bf9f90af1..06db5f37d9 100644 --- a/docs/en/tutorials/book-store/part-09.md +++ b/docs/en/tutorials/book-store/part-09.md @@ -1038,8 +1038,6 @@ Create a new Razor Component Page, `/Pages/Authors.razor`, in the {{ if UI == "B * This code is similar to the `Books.razor`, except it doesn't inherit from the `AbpCrudPageBase`, but uses its own implementation. * Injects the `IAuthorAppService` to consume the server side HTTP APIs from the UI. We can directly inject application service interfaces and use just like regular method calls by the help of [Dynamic C# HTTP API Client Proxy System](../../framework/api-development/dynamic-csharp-clients.md), which performs REST API calls for us. See the `Authors` class below to see the usage. -* Injects the `IAuthorizationService` to check [permissions](../../framework/fundamentals/authorization.md). -* Injects the `IObjectMapper` for [object to object mapping](../../framework/infrastructure/object-to-object-mapping.md). Create a new code behind file, `Authors.razor.cs`, under the `Pages` folder, with the following content: @@ -1158,14 +1156,21 @@ public partial class Authors private async Task DeleteAuthorAsync(AuthorDto author) { - var confirmMessage = L["AuthorDeletionConfirmationMessage", author.Name]; - if (!await Message.Confirm(confirmMessage)) + try { - return; - } + var confirmMessage = L["AuthorDeletionConfirmationMessage", author.Name]; + if (!await Message.Confirm(confirmMessage)) + { + return; + } - await AuthorAppService.DeleteAsync(author.Id); - await GetAuthorsAsync(); + await AuthorAppService.DeleteAsync(author.Id); + await GetAuthorsAsync(); + } + catch(Exception ex) + { + await HandleErrorAsync(ex); + } } private void CloseEditAuthorModal() @@ -1175,21 +1180,35 @@ public partial class Authors private async Task CreateAuthorAsync() { - if (await CreateValidationsRef.ValidateAll()) + try { - await AuthorAppService.CreateAsync(NewAuthor); - await GetAuthorsAsync(); - CreateAuthorModal.Hide(); + if (await CreateValidationsRef.ValidateAll()) + { + await AuthorAppService.CreateAsync(NewAuthor); + await GetAuthorsAsync(); + CreateAuthorModal.Hide(); + } + } + catch(Exception ex) + { + await HandleErrorAsync(ex); } } private async Task UpdateAuthorAsync() { - if (await EditValidationsRef.ValidateAll()) + try { - await AuthorAppService.UpdateAsync(EditingAuthorId, EditingAuthor); - await GetAuthorsAsync(); - EditAuthorModal.Hide(); + if (await EditValidationsRef.ValidateAll()) + { + await AuthorAppService.UpdateAsync(EditingAuthorId, EditingAuthor); + await GetAuthorsAsync(); + EditAuthorModal.Hide(); + } + } + catch(Exception ex) + { + await HandleErrorAsync(ex); } } } diff --git a/docs/en/tutorials/microservice/part-06.md b/docs/en/tutorials/microservice/part-06.md index af05bbd792..1cc19bf6d8 100644 --- a/docs/en/tutorials/microservice/part-06.md +++ b/docs/en/tutorials/microservice/part-06.md @@ -107,9 +107,9 @@ public class ProductIntegrationService : ApplicationService, IProductIntegration 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 +### Adding a Reference to the `CloudCrm.OrderingService` 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: +First, we need to add a reference to the `CloudCrm.OrderingService` 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) @@ -304,3 +304,18 @@ Now, the Ordering service displays the product name instead of the product ID. W > **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. + +### Updating the Kubernetes Configuration + +ABP microservice startup template provides [pre-configured Helm charts](../../solution-templates/microservice/helm-charts-and-kubernetes.md) to deploy your solution to Kubernetes. When you develop your solution, you should also care about configurations of these charts if you want to keep them up to date and working. + +In the section *Generating Proxy Classes for the Integration Service* above, we added a new configuration to the `appsettings.json` file of the Ordering microservice. We should configure the corresponding Helm chart configuration to keep it synchronized. + +Open the `etc\helm\cloudcrm\charts\ordering\templates\ordering.yaml` file in a text editor, and add the following lines under the `env` section, just like the other values present (be careful on indents since it is critical in YAML files): + +````yaml +- name: "RemoteServices__CatalogService__BaseUrl" + value: "http://{%{{{ .Release.Name }}}%}-catalog" +```` + +With this simple configuration, now the Ordering module can discover the catalog microservice's URL inside your Kubernetes cluster. diff --git a/docs/en/tutorials/modular-crm/part-03.md b/docs/en/tutorials/modular-crm/part-03.md index 2dabfc54eb..38c6553fa3 100644 --- a/docs/en/tutorials/modular-crm/part-03.md +++ b/docs/en/tutorials/modular-crm/part-03.md @@ -436,7 +436,7 @@ Open the `ModularCrm.Products` .NET solution in your IDE, and find the `Pages/Pr ![visual-studio-products-cshtml](images/visual-studio-products-cshtml.png) -Replace the `IndexModel.cshtml.cs` file with the following content: +Replace the `Index.cshtml.cs` file with the following content: ````csharp using System.Collections.Generic; diff --git a/docs/en/tutorials/modular-crm/part-06.md b/docs/en/tutorials/modular-crm/part-06.md index f06baa93f0..d2820c6bdc 100644 --- a/docs/en/tutorials/modular-crm/part-06.md +++ b/docs/en/tutorials/modular-crm/part-06.md @@ -256,7 +256,7 @@ Let's see what we've changed: * In the last line, we are converting the product list to a dictionary, where the key is `Guid Id` and the value is `string Name`. That way, we can easily find a product's name with its ID. * Finally, we are mapping the orders to `OrderDto` objects and setting the product name by looking up the product ID in the dictionary. -Open the `Index.cshtml` file, and change the `@order.ProductId` part by `@Model.ProductName` to write the product name instead of the product ID. The final `Index.cshtml` content should be the following: +Open the `Index.cshtml` file, and change the `@order.ProductId` part by `@Order.ProductName` to write the product name instead of the product ID. The final `Index.cshtml` content should be the following: ````html @page diff --git a/docs/en/tutorials/todo/layered/index.md b/docs/en/tutorials/todo/layered/index.md index e6e310a39a..86a480ad42 100644 --- a/docs/en/tutorials/todo/layered/index.md +++ b/docs/en/tutorials/todo/layered/index.md @@ -528,7 +528,7 @@ The interesting part here is how we communicate with the server. See the *Dynami ### Index.css -As the final touch, Create a file named `Index.css` in the `Pages` folder of the *TodoApp.Web* project and replace it with the following content: +As the final touch, Create a file named `Index.css` in the `Pages` folder of the *TodoApp.Web* project and add the following content: ```css #TodoList{ @@ -664,7 +664,7 @@ Open the `Index.razor` file in the `Pages` folder of the {{if UI=="Blazor" || UI ### Index.razor.css -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 if UI=="BlazorServer"}} *TodoApp.Blazor* {{else if UI=="MAUIBlazor"}} *TodoApp.MauiBlazor* {{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 if UI=="BlazorServer"}} *TodoApp.Blazor* {{else if UI=="MAUIBlazor"}} *TodoApp.MauiBlazor* {{end}} project and add the following content: ```css #TodoList{ @@ -827,7 +827,7 @@ Open the `/angular/src/app/home/home.component.html` file and replace its conten ### home.component.scss -As the final touch, open the `/angular/src/app/home/home.component.scss` file and replace its content with the following code block: +As the final touch, open the `/angular/src/app/home/home.component.scss` file and add the following code block: ```css #TodoList{ diff --git a/docs/en/tutorials/todo/single-layer/index.md b/docs/en/tutorials/todo/single-layer/index.md index dc865a0a75..6ce5bec5b0 100644 --- a/docs/en/tutorials/todo/single-layer/index.md +++ b/docs/en/tutorials/todo/single-layer/index.md @@ -309,10 +309,8 @@ public interface ITodoAppService : IApplicationService Create a `TodoAppService` class under the `Services` folder of {{if UI=="Blazor"}}your `TodoApp.Host` project{{else}}your project{{end}}, as shown below: ```csharp -using TodoApp.Services; using TodoApp.Services.Dtos; using TodoApp.Entities; -using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; namespace TodoApp.Services; @@ -517,7 +515,7 @@ The interesting part here is how we communicate with the server. See the *Dynami ### Index.cshtml.css -As for the final touch, open the `Index.cshtml.css` file in the `Pages` folder and replace with the following content: +As for the final touch, open the `Index.cshtml.css` file in the `Pages` folder and add the following code block at the end of the file: ````css #TodoList{ @@ -655,7 +653,7 @@ Open the `Index.razor` file in the `Pages` folder and replace the content with t ### Index.razor.css -As the final touch, open the `Index.razor.css` file in the `Pages` folder and replace it with the following content: +As the final touch, open the `Index.razor.css` file in the `Pages` folder and add the following code block at the end of the file: ````css #TodoList{ @@ -801,7 +799,7 @@ Open the `/angular/src/app/home/home.component.html` file and replace its conten ### home.component.scss -As the final touch, open the `/angular/src/app/home/home.component.scss` file and replace its content with the following code block: +As the final touch, open the `/angular/src/app/home/home.component.scss` file and add the following code block at the end of the file: ````css #TodoList{ diff --git a/docs/en/ui-themes/lepton-x/blazor.md b/docs/en/ui-themes/lepton-x/blazor.md index 5e49752ebb..2287b5aeac 100644 --- a/docs/en/ui-themes/lepton-x/blazor.md +++ b/docs/en/ui-themes/lepton-x/blazor.md @@ -347,8 +347,43 @@ namespace LeptonX.DemoApp.Blazor.MyComponents > Don't forget to remove repeated attributes from the razor page! ---- +#### Customizing the Footer Section + +You can add a new `LeptonXFooter.razor` file and override the `Footer` component as follows: + +```cs +@using Volo.Abp.DependencyInjection +@using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu + +@inherits Footer +@attribute [ExposeServices(typeof(Footer))] +@attribute [Dependency(ReplaceServices = true)] + +
+
+ + +
+
+``` + +If you are using **Top Menu Layout**, then you can change the namespace as follows: + +```diff +- @using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.SideMenu ++ @using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout.TopMenu +``` +> You can use the same approach customize the other components always. ## Common Components diff --git a/docs/en/ui-themes/lepton-x/images/account-layout-background-style.png b/docs/en/ui-themes/lepton-x/images/account-layout-background-style.png new file mode 100644 index 0000000000..c8391da4d3 Binary files /dev/null and b/docs/en/ui-themes/lepton-x/images/account-layout-background-style.png differ diff --git a/docs/en/ui-themes/lepton-x/images/leptonx-mvc-customizing-footer.png b/docs/en/ui-themes/lepton-x/images/leptonx-mvc-customizing-footer.png new file mode 100644 index 0000000000..06721044b8 Binary files /dev/null and b/docs/en/ui-themes/lepton-x/images/leptonx-mvc-customizing-footer.png differ diff --git a/docs/en/ui-themes/lepton-x/mvc.md b/docs/en/ui-themes/lepton-x/mvc.md index ce12a0ea95..e41d12a331 100644 --- a/docs/en/ui-themes/lepton-x/mvc.md +++ b/docs/en/ui-themes/lepton-x/mvc.md @@ -47,7 +47,8 @@ Before starting to customize the theme, you can consider downloading the source --- ### Appearance -You can set a default theme, add or remove appearance styles by using **LeptonXThemeOptions**. + +You can set a default theme, add or remove appearance styles and layout background styles by using **LeptonXThemeOptions**. - `DefaultStyle`: Defines the default fallback theme. The default value is **Dim** @@ -133,15 +134,26 @@ Layout options of the MVC Razor Pages UI can be manageable by using **LeptonXThe - `MobileMenuSelector`: Defines items to be displayed at the mobile menu. The default value is the first 2 items from the main menu items. + ```csharp + Configure(options => + { + options.MobileMenuSelector = items => items.Where(x => x.MenuItem.Name == "MyProjectName.Home" || x.MenuItem.Name == "MyProjectName.Dashboard"); + }); + ``` + ![leptonx-mobile-menu-preview](images/mobile-menu-preview.png) +- `AccountLayoutBackgroundStyle`: Defines the background style of the account layout. + ```csharp Configure(options => { - options.MobileMenuSelector = items => items.Where(x => x.MenuItem.Name == "MyProjectName.Home" || x.MenuItem.Name == "MyProjectName.Dashboard"); + options.AccountLayoutBackgroundStyle = "background-image: url('/images/login-background-image.svg') !important;"; }); ``` + ![leptonx-account-layout-background-style](images/account-layout-background-style.png) + ### Layouts **LeptonX** offers two **ready-made layouts** for your web application. One of them is **placed** with the **menu items** on the **top** and the other with the **menu items** on the **sides**. @@ -162,6 +174,22 @@ Layout options of the MVC Razor Pages UI can be manageable by using **LeptonXThe > - **_Sidebar.cshtml** > - **_Toolbar.cshtml** +#### Customizing the Footer Section + +Add the **_Footer.cshtml** file under the **Themes/LeptonX/Layouts/Application** folder to customize the footer: + +```html + +```` + +![Customizing Footer](images/leptonx-mvc-customizing-footer.png) + +> You can customize the **_Sidebar.cshtml** and **_Toolbar.cshtml** files as well. + ### Account Layout ![Account layout](images/leptonx-account-layout-new.png) diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index db7bc55ff2..78f7ae0011 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -489,6 +489,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Bunny" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Bunny.Tests", "test\Volo.Abp.BlobStoring.Bunny.Tests\Volo.Abp.BlobStoring.Bunny.Tests.csproj", "{BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Timing.Tests", "test\Volo.Abp.Timing.Tests\Volo.Abp.Timing.Tests.csproj", "{58FCF22D-E8DB-4EB8-B586-9BB6E9899D64}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1459,6 +1461,10 @@ Global {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}.Debug|Any CPU.Build.0 = Debug|Any CPU {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}.Release|Any CPU.ActiveCfg = Release|Any CPU {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915}.Release|Any CPU.Build.0 = Release|Any CPU + {58FCF22D-E8DB-4EB8-B586-9BB6E9899D64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58FCF22D-E8DB-4EB8-B586-9BB6E9899D64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58FCF22D-E8DB-4EB8-B586-9BB6E9899D64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58FCF22D-E8DB-4EB8-B586-9BB6E9899D64}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1705,6 +1711,7 @@ Global {70720321-DED4-464F-B913-BDA5BBDD7982} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {1BBCBA72-CDB6-4882-96EE-D4CD149433A2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {BC4BB2D6-DFD8-4190-AAC3-32C0A7A8E915} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {58FCF22D-E8DB-4EB8-B586-9BB6E9899D64} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/AbpMauiBlazorClientHttpMessageHandler.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/AbpMauiBlazorClientHttpMessageHandler.cs index 9fb31979ac..562f35e5a8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/AbpMauiBlazorClientHttpMessageHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/AbpMauiBlazorClientHttpMessageHandler.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AspNetCore.Components.Progression; using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Components.MauiBlazor; @@ -13,12 +14,15 @@ public class AbpMauiBlazorClientHttpMessageHandler : DelegatingHandler, ITransie { private readonly IUiPageProgressService _uiPageProgressService; private readonly IMauiBlazorSelectedLanguageProvider _mauiBlazorSelectedLanguageProvider; + private readonly ICurrentTimezoneProvider _currentTimezoneProvider; public AbpMauiBlazorClientHttpMessageHandler( IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor, - IMauiBlazorSelectedLanguageProvider mauiBlazorSelectedLanguageProvider) + IMauiBlazorSelectedLanguageProvider mauiBlazorSelectedLanguageProvider, + ICurrentTimezoneProvider currentTimezoneProvider) { _mauiBlazorSelectedLanguageProvider = mauiBlazorSelectedLanguageProvider; + _currentTimezoneProvider = currentTimezoneProvider; _uiPageProgressService = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); } @@ -32,6 +36,7 @@ public class AbpMauiBlazorClientHttpMessageHandler : DelegatingHandler, ITransie }); await SetLanguageAsync(request); + await SetTimeZoneAsync(request); return await base.SendAsync(request, cancellationToken); } @@ -51,4 +56,15 @@ public class AbpMauiBlazorClientHttpMessageHandler : DelegatingHandler, ITransie request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(selectedLanguage!)); } } -} \ No newline at end of file + + private Task SetTimeZoneAsync(HttpRequestMessage request) + { + if (!_currentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + request.Headers.Remove(TimeZoneConsts.DefaultTimeZoneKey); + request.Headers.Add(TimeZoneConsts.DefaultTimeZoneKey, _currentTimezoneProvider.TimeZone); + } + + return Task.CompletedTask; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs index c2fd8e21aa..e4a2f8a3cc 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCachedApplicationConfigurationClient.cs @@ -1,10 +1,14 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.JSInterop; +using Volo.Abp.AspNetCore.Components.Web.Security; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; using Volo.Abp.AspNetCore.Mvc.Client; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; +using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Components.MauiBlazor { @@ -18,17 +22,33 @@ namespace Volo.Abp.AspNetCore.Components.MauiBlazor protected ICurrentTenantAccessor CurrentTenantAccessor { get; } + protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; } + + protected ApplicationConfigurationChangedService ApplicationConfigurationChangedService { get; } + + protected IJSRuntime JSRuntime { get; } + + protected IClock Clock { get; } + public MauiBlazorCachedApplicationConfigurationClient( AbpApplicationConfigurationClientProxy applicationConfigurationClientProxy, ApplicationConfigurationCache cache, ICurrentTenantAccessor currentTenantAccessor, + ICurrentTimezoneProvider currentTimezoneProvider, AuthenticationStateProvider authenticationStateProvider, - AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy) + AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy, + ApplicationConfigurationChangedService applicationConfigurationChangedService, + IJSRuntime jsRuntime, + IClock clock) { ApplicationConfigurationClientProxy = applicationConfigurationClientProxy; Cache = cache; CurrentTenantAccessor = currentTenantAccessor; + CurrentTimezoneProvider = currentTimezoneProvider; ApplicationLocalizationClientProxy = applicationLocalizationClientProxy; + ApplicationConfigurationChangedService = applicationConfigurationChangedService; + JSRuntime = jsRuntime; + Clock = clock; authenticationStateProvider.AuthenticationStateChanged += async _ => { await InitializeAsync(); }; } @@ -57,6 +77,17 @@ namespace Volo.Abp.AspNetCore.Components.MauiBlazor CurrentTenantAccessor.Current = new BasicTenantInfo( configurationDto.CurrentTenant.Id, configurationDto.CurrentTenant.Name); + + if (Clock.SupportsMultipleTimezone) + { + CurrentTimezoneProvider.TimeZone = !configurationDto.Timing.TimeZone.Iana.TimeZoneName.IsNullOrWhiteSpace() + ? configurationDto.Timing.TimeZone.Iana.TimeZoneName + : await JSRuntime.InvokeAsync("abp.clock.getBrowserTimeZone"); + + await JSRuntime.InvokeAsync("abp.clock.setBrowserTimeZoneToCookie"); + } + + ApplicationConfigurationChangedService.NotifyChanged(); } public virtual Task GetAsync() @@ -81,4 +112,4 @@ namespace Volo.Abp.AspNetCore.Components.MauiBlazor return configuration; } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCurrentTimezoneProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCurrentTimezoneProvider.cs new file mode 100644 index 0000000000..2a1a37da07 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiBlazorCurrentTimezoneProvider.cs @@ -0,0 +1,10 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; + +namespace Volo.Abp.AspNetCore.Components.MauiBlazor; + +[Dependency(ReplaceServices = true)] +public class MauiBlazorCurrentTimezoneProvider : ICurrentTimezoneProvider, ISingletonDependency +{ + public string? TimeZone { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiCurrentApplicationConfigurationCacheResetService.cs b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiCurrentApplicationConfigurationCacheResetService.cs new file mode 100644 index 0000000000..ad2f6ba983 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor/Volo/Abp/AspNetCore/Components/MauiBlazor/MauiCurrentApplicationConfigurationCacheResetService.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.Components.Web.Configuration; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.Components.MauiBlazor; + +[Dependency(ReplaceServices = true)] +public class MauiCurrentApplicationConfigurationCacheResetService : + ICurrentApplicationConfigurationCacheResetService, + ITransientDependency +{ + private readonly MauiBlazorCachedApplicationConfigurationClient _mauiBlazorCachedApplicationConfigurationClient; + + public MauiCurrentApplicationConfigurationCacheResetService(MauiBlazorCachedApplicationConfigurationClient mauiBlazorCachedApplicationConfigurationClient) + { + _mauiBlazorCachedApplicationConfigurationClient = mauiBlazorCachedApplicationConfigurationClient; + } + + public async Task ResetAsync() + { + await _mauiBlazorCachedApplicationConfigurationClient.InitializeAsync(); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs index 30a69f8d74..74481c9bbd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageHeader.razor.cs @@ -111,8 +111,7 @@ public partial class PageHeader : ComponentBase, IDisposable public void Dispose() { - PageLayout.ToolbarItems.Clear(); - PageLayout.BreadcrumbItems.Clear(); + PageLayout.Reset(); ToolbarItemRenders.Clear(); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageLayout.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageLayout.cs index 077ca5b32c..fc7d372b37 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageLayout.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Layout/PageLayout.cs @@ -41,4 +41,12 @@ public class PageLayout : IScopedDependency, INotifyPropertyChanged { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + + public void Reset() + { + Title = string.Empty; + MenuItemName = string.Empty; + BreadcrumbItems.Clear(); + ToolbarItems.Clear(); + } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeManager.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeManager.cs index 5abd114f83..76c7bbf556 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeManager.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Theming/DefaultThemeManager.cs @@ -29,6 +29,6 @@ public class DefaultThemeManager : IThemeManager, IScopedDependency, IServicePro } _currentTheme = (ITheme)ServiceProvider.GetRequiredService(ThemeSelector.GetCurrentThemeInfo().ThemeType); - return CurrentTheme; + return _currentTheme; } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs index c92c121628..5fa70baabe 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/AbpBlazorClientHttpMessageHandler.cs @@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.JSInterop; using Volo.Abp.AspNetCore.Components.Progression; using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Components.Web; @@ -21,6 +22,8 @@ public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDe private readonly IUiPageProgressService _uiPageProgressService; + private readonly ICurrentTimezoneProvider _currentTimezoneProvider; + private const string AntiForgeryCookieName = "XSRF-TOKEN"; private const string AntiForgeryHeaderName = "RequestVerificationToken"; @@ -29,11 +32,13 @@ public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDe IJSRuntime jsRuntime, ICookieService cookieService, NavigationManager navigationManager, - IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor) + IClientScopeServiceProviderAccessor clientScopeServiceProviderAccessor, + ICurrentTimezoneProvider currentTimezoneProvider) { _jsRuntime = jsRuntime; _cookieService = cookieService; _navigationManager = navigationManager; + _currentTimezoneProvider = currentTimezoneProvider; _uiPageProgressService = clientScopeServiceProviderAccessor.ServiceProvider.GetRequiredService(); } @@ -48,6 +53,7 @@ public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDe await SetLanguageAsync(request, cancellationToken); await SetAntiForgeryTokenAsync(request); + await SetTimeZoneAsync(request); return await base.SendAsync(request, cancellationToken); } @@ -94,4 +100,15 @@ public class AbpBlazorClientHttpMessageHandler : DelegatingHandler, ITransientDe request.Headers.Add(AntiForgeryHeaderName, token); } } + + private Task SetTimeZoneAsync(HttpRequestMessage request) + { + if (!_currentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + request.Headers.Remove(TimeZoneConsts.DefaultTimeZoneKey); + request.Headers.Add(TimeZoneConsts.DefaultTimeZoneKey, _currentTimezoneProvider.TimeZone); + } + + return Task.CompletedTask; + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs index a8b0f71dea..a73ba0e77d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs @@ -8,6 +8,7 @@ using Volo.Abp.AspNetCore.Components.Messages; using Volo.Abp.AspNetCore.ExceptionHandling; using Volo.Abp.DependencyInjection; using Volo.Abp.Http; +using Volo.Abp.Http.Client; namespace Volo.Abp.AspNetCore.Components.Web.ExceptionHandling; @@ -35,6 +36,8 @@ public class UserExceptionInformer : IUserExceptionInformer, IScopedDependency { //TODO: Create sync versions of the MessageService APIs. + LogException(context); + var errorInfo = GetErrorInfo(context); if (errorInfo.Details.IsNullOrEmpty()) @@ -49,6 +52,8 @@ public class UserExceptionInformer : IUserExceptionInformer, IScopedDependency public async Task InformAsync(UserExceptionInformerContext context) { + LogException(context); + var errorInfo = GetErrorInfo(context); if (errorInfo.Details.IsNullOrEmpty()) @@ -70,4 +75,14 @@ public class UserExceptionInformer : IUserExceptionInformer, IScopedDependency options.SendExceptionDataToClientTypes = Options.SendExceptionDataToClientTypes; }); } + + protected virtual void LogException(UserExceptionInformerContext context) + { + if (context.Exception is AbpRemoteCallException && OperatingSystem.IsBrowser()) + { + return; + } + + Logger.LogException(context.Exception); + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js index 51ff0151b6..30f1915005 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js +++ b/framework/src/Volo.Abp.AspNetCore.Components.Web/wwwroot/libs/abp/js/abp.js @@ -245,4 +245,14 @@ var abp = abp || {}; } } } + + abp.clock = abp.clock || {}; + + abp.clock.setBrowserTimeZoneToCookie = function () { + abp.utils.setCookieValue('__timezone', Intl.DateTimeFormat().resolvedOptions().timeZone, new Date(new Date().setFullYear(new Date().getFullYear() + 1)), '/'); + } + + abp.clock.getBrowserTimeZone = function () { + return Intl.DateTimeFormat().resolvedOptions().timeZone + } })(); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs index 1bcc1c1f45..2027ac1e69 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs @@ -1,3 +1,4 @@ +using System; using JetBrains.Annotations; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -19,10 +20,14 @@ public static class AbpBlazorWebAppServiceCollectionExtensions return services; } + [Obsolete("Use AddBlazorWebAppServices instead. See https://github.com/abpframework/abp/issues/22622")] public static IServiceCollection AddBlazorWebAppTieredServices([NotNull] this IServiceCollection services) { Check.NotNull(services, nameof(services)); + // Compatibility with old template code + services.AddTransient(); + services.AddScoped(); services.Replace(ServiceDescriptor.Singleton()); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs index b35960f071..d3f05820b0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs @@ -1,5 +1,7 @@ +using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Security.Claims; namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; @@ -8,21 +10,26 @@ public class RemoteAuthenticationStateProvider : AuthenticationStateProvider { protected ICurrentPrincipalAccessor CurrentPrincipalAccessor { get; } protected WebAssemblyCachedApplicationConfigurationClient WebAssemblyCachedApplicationConfigurationClient { get; } + protected IServiceProvider ServiceProvider { get; } public RemoteAuthenticationStateProvider( ICurrentPrincipalAccessor currentPrincipalAccessor, - WebAssemblyCachedApplicationConfigurationClient webAssemblyCachedApplicationConfigurationClient) + WebAssemblyCachedApplicationConfigurationClient webAssemblyCachedApplicationConfigurationClient, + IServiceProvider serviceProvider) { CurrentPrincipalAccessor = currentPrincipalAccessor; WebAssemblyCachedApplicationConfigurationClient = webAssemblyCachedApplicationConfigurationClient; + ServiceProvider = serviceProvider; } public async override Task GetAuthenticationStateAsync() { - if (CurrentPrincipalAccessor.Principal.Identity == null || - !CurrentPrincipalAccessor.Principal.Identity.IsAuthenticated) + if (ServiceProvider.GetService() != null) { - await WebAssemblyCachedApplicationConfigurationClient.InitializeAsync(); + if (CurrentPrincipalAccessor.Principal.Identity == null || !CurrentPrincipalAccessor.Principal.Identity.IsAuthenticated) + { + await WebAssemblyCachedApplicationConfigurationClient.InitializeAsync(); + } } return new AuthenticationState(CurrentPrincipalAccessor.Principal); diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProviderCompatible.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProviderCompatible.cs new file mode 100644 index 0000000000..780f96c631 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProviderCompatible.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp; + +/// +/// This class is used to indicate that the AddBlazorWebAppTieredServices method has been called for compatibility with the old template code +/// +internal sealed class AddBlazorWebAppTieredServicesHasBeenCalled +{ +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs index bebb2a78e1..acb792d454 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCachedApplicationConfigurationClient.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.JSInterop; using Volo.Abp.AspNetCore.Components.Web.Security; using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; @@ -6,6 +7,7 @@ using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ClientProxies; using Volo.Abp.AspNetCore.Mvc.Client; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; +using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Components.WebAssembly; @@ -19,24 +21,32 @@ public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicatio protected ICurrentTenantAccessor CurrentTenantAccessor { get; } + protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; } + protected ApplicationConfigurationChangedService ApplicationConfigurationChangedService { get; } protected IJSRuntime JSRuntime { get; } + protected IClock Clock { get; } + public WebAssemblyCachedApplicationConfigurationClient( AbpApplicationConfigurationClientProxy applicationConfigurationClientProxy, ApplicationConfigurationCache cache, ICurrentTenantAccessor currentTenantAccessor, + ICurrentTimezoneProvider currentTimezoneProvider, AbpApplicationLocalizationClientProxy applicationLocalizationClientProxy, ApplicationConfigurationChangedService applicationConfigurationChangedService, - IJSRuntime jsRuntime) + IJSRuntime jsRuntime, + IClock clock) { ApplicationConfigurationClientProxy = applicationConfigurationClientProxy; Cache = cache; CurrentTenantAccessor = currentTenantAccessor; + CurrentTimezoneProvider = currentTimezoneProvider; ApplicationLocalizationClientProxy = applicationLocalizationClientProxy; ApplicationConfigurationChangedService = applicationConfigurationChangedService; JSRuntime = jsRuntime; + Clock = clock; } public virtual async Task InitializeAsync() @@ -63,12 +73,21 @@ public class WebAssemblyCachedApplicationConfigurationClient : ICachedApplicatio await JSRuntime.InvokeVoidAsync("abp.utils.removeOidcUser"); } - ApplicationConfigurationChangedService.NotifyChanged(); - CurrentTenantAccessor.Current = new BasicTenantInfo( configurationDto.CurrentTenant.Id, configurationDto.CurrentTenant.Name ); + + if (Clock.SupportsMultipleTimezone) + { + CurrentTimezoneProvider.TimeZone = !configurationDto.Timing.TimeZone.Iana.TimeZoneName.IsNullOrWhiteSpace() + ? configurationDto.Timing.TimeZone.Iana.TimeZoneName + : await JSRuntime.InvokeAsync("abp.clock.getBrowserTimeZone"); + + await JSRuntime.InvokeAsync("abp.clock.setBrowserTimeZoneToCookie"); + } + + ApplicationConfigurationChangedService.NotifyChanged(); } public virtual Task GetAsync() diff --git a/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentTimezoneProvider.cs b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentTimezoneProvider.cs new file mode 100644 index 0000000000..c387ec30ea --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebAssemblyCurrentTimezoneProvider.cs @@ -0,0 +1,10 @@ +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; + +namespace Volo.Abp.AspNetCore.Components.WebAssembly; + +[Dependency(ReplaceServices = true)] +public class WebAssemblyCurrentTimezoneProvider : ICurrentTimezoneProvider, ISingletonDependency +{ + public string? TimeZone { get; set; } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs index 6f2df20de8..6b2fe0d98f 100644 --- a/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs +++ b/framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs @@ -172,8 +172,7 @@ public abstract class AbpComponentBase : OwningComponentBase { return; } - - Logger.LogException(exception); + await InvokeAsync(async () => { await UserExceptionInformer.InformAsync(new UserExceptionInformerContext(exception)); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs index d213c9f451..95e07a06e0 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs @@ -16,7 +16,9 @@ public class AbpAspNetCoreMvcNewtonsoftModule : AbpModule context.Services.AddOptions() .Configure((options, rootServiceProvider) => { - options.SerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver(rootServiceProvider.GetRequiredService()); + options.SerializerSettings.ContractResolver = + new AbpCamelCasePropertyNamesContractResolver(rootServiceProvider + .GetRequiredService()); }); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs index 62cae94413..af1538bbde 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelper.cs @@ -47,11 +47,13 @@ public class AbpInputTagHelper : AbpTagHelper } if (isCheckBox) { - output.Attributes.AddClass("custom-checkbox"); - output.Attributes.AddClass("custom-control"); + if (!TagHelper.UseSwitchCheckBox) + { + output.Attributes.AddClass("custom-checkbox"); + output.Attributes.AddClass("custom-control"); + } + else + { + output.Attributes.AddClass("form-switch"); + } + output.Attributes.AddClass("form-check"); } } @@ -266,7 +274,7 @@ public class AbpInputTagHelperService : AbpTagHelperService } protected virtual async Task GetLabelAsHtmlAsync(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag, bool isCheckbox) - { + { if (IsOutputHidden(inputTag) || TagHelper.SuppressLabel) { return string.Empty; @@ -395,7 +403,7 @@ public class AbpInputTagHelperService : AbpTagHelperService } innerOutput.Content.AppendHtml($" "); } - + innerOutput.Content.AppendHtml(GetRequiredSymbol(context, output)); return innerOutput.Render(_encoder); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs index bd3a4abe48..5088c08293 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs @@ -16,63 +16,28 @@ using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; using Volo.Abp.Json; +using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form.DatePicker; public abstract class AbpDatePickerBaseTagHelperService : AbpTagHelperService where TTagHelper : AbpDatePickerBaseTagHelper { - protected readonly Dictionary> SupportedInputTypes = new() - { - { - typeof(string), o => - { - if(o is string s && DateTime.TryParse(s, out var dt)) - { - return dt.ToString("O"); - } - - return string.Empty; - } - }, - { - typeof(DateTime), o => - { - if(o is DateTime dt && dt != default) - { - return dt.ToString("O"); - } - - return string.Empty; - } - }, - {typeof(DateTime?), o => ((DateTime?) o)?.ToString("O")!}, - { - typeof(DateTimeOffset), o => - { - if(o is DateTimeOffset dto && dto != default) - { - return dto.ToString("O"); - } - - return string.Empty; - } - }, - {typeof(DateTimeOffset?), o => ((DateTimeOffset?) o)?.ToString("O")!} - }; + protected readonly Dictionary> SupportedInputTypes; protected readonly IJsonSerializer JsonSerializer; protected readonly IHtmlGenerator Generator; protected readonly HtmlEncoder Encoder; protected readonly IServiceProvider ServiceProvider; protected readonly IAbpTagHelperLocalizer TagHelperLocalizer; + protected readonly IClock Clock; protected virtual string TagName { get; set; } = "abp-date-picker"; protected IStringLocalizer L { get; } protected abstract TagHelperOutput TagHelperOutput { get; set; } protected AbpDatePickerBaseTagHelperService(IJsonSerializer jsonSerializer, IHtmlGenerator generator, HtmlEncoder encoder, IServiceProvider serviceProvider, IStringLocalizer l, - IAbpTagHelperLocalizer tagHelperLocalizer) + IAbpTagHelperLocalizer tagHelperLocalizer, IClock clock) { JsonSerializer = jsonSerializer; Generator = generator; @@ -80,6 +45,65 @@ public abstract class AbpDatePickerBaseTagHelperService : AbpTagHelp ServiceProvider = serviceProvider; L = l; TagHelperLocalizer = tagHelperLocalizer; + Clock = clock; + + SupportedInputTypes = new Dictionary> + { + { + typeof(string), x => + { + if(x is string s && DateTime.TryParse(s, out var dt)) + { + return Clock.ConvertToUserTime(dt).ToString("O"); + } + + return string.Empty; + } + }, + { + typeof(DateTime), x => + { + if(x is DateTime dt && dt != default) + { + return Clock.ConvertToUserTime(dt).ToString("O"); + } + + return string.Empty; + } + }, + { + typeof(DateTime?), x => + { + if(x is DateTime dt && dt != default) + { + return Clock.ConvertToUserTime(dt).ToString("O"); + } + return string.Empty; + } + }, + { + typeof(DateTimeOffset), x => + { + if(x is DateTimeOffset dto && dto != default) + { + return Clock.ConvertToUserTime(dto).DateTime.ToString("O"); + } + + return string.Empty; + } + }, + { + typeof(DateTimeOffset?), x => + { + if(x is DateTimeOffset dto && dto != default) + { + return Clock.ConvertToUserTime(dto).DateTime.ToString("O"); + } + + return string.Empty; + } + } + }; } protected virtual T? GetAttribute() where T : Attribute @@ -233,6 +257,7 @@ public abstract class AbpDatePickerBaseTagHelperService : AbpTagHelp } protected abstract int GetOrder(); + protected abstract void AddBaseTagAttributes(TagHelperAttributeList attributes); protected virtual string GetExtraInputHtml(TagHelperContext context, TagHelperOutput output) @@ -375,7 +400,7 @@ public abstract class AbpDatePickerBaseTagHelperService : AbpTagHelp { attrList.Add("data-visible-date-format", options.VisibleDateFormat); } - + if(!options.InputDateFormat.IsNullOrEmpty()) { attrList.Add("data-input-date-format", options.InputDateFormat); @@ -754,7 +779,7 @@ public abstract class AbpDatePickerBaseTagHelperService : AbpTagHelp { return Task.FromResult(string.Empty); } - + return GetValidationAsHtmlByInputAsync(context, output, @for); } @@ -766,7 +791,7 @@ public abstract class AbpDatePickerBaseTagHelperService : AbpTagHelp new ValidationMessageTagHelper(Generator) { For = @for, ViewContext = TagHelper.ViewContext }; var attributeList = new TagHelperAttributeList { { "class", "text-danger" } }; - + if(!output.Attributes.TryGetAttribute("name", out var nameAttribute) || nameAttribute == null || nameAttribute.Value == null) { if (nameAttribute != null) @@ -776,7 +801,7 @@ public abstract class AbpDatePickerBaseTagHelperService : AbpTagHelp nameAttribute = new TagHelperAttribute("name", "date_" + Guid.NewGuid().ToString("N")); output.Attributes.Add(nameAttribute); } - + attributeList.Add("data-valmsg-for", nameAttribute.Value); return await validationMessageTagHelper.RenderAsync(attributeList, context, Encoder, "span", diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs index 3fc2861b59..5370a9a7de 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs @@ -8,14 +8,22 @@ using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; using Volo.Abp.Json; +using Volo.Abp.Timing; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form.DatePicker; public class AbpDatePickerTagHelperService : AbpDatePickerBaseTagHelperService { - public AbpDatePickerTagHelperService(IJsonSerializer jsonSerializer, IHtmlGenerator generator, HtmlEncoder encoder, IServiceProvider serviceProvider, IStringLocalizer l, IAbpTagHelperLocalizer tagHelperLocalizer) : base(jsonSerializer, generator, encoder, serviceProvider, l, tagHelperLocalizer) + public AbpDatePickerTagHelperService( + IJsonSerializer jsonSerializer, + IHtmlGenerator generator, + HtmlEncoder encoder, + IServiceProvider serviceProvider, + IStringLocalizer l, + IAbpTagHelperLocalizer tagHelperLocalizer, + IClock clock) + : base(jsonSerializer, generator, encoder, serviceProvider, l, tagHelperLocalizer, clock) { - } protected override TagHelperOutput TagHelperOutput { get; set; } = default!; @@ -42,10 +50,28 @@ public class AbpDatePickerTagHelperService : AbpDatePickerBaseTagHelperService { - public AbpDateRangePickerTagHelperService(IJsonSerializer jsonSerializer, IHtmlGenerator generator, - HtmlEncoder encoder, IServiceProvider serviceProvider, IStringLocalizer l, - IAbpTagHelperLocalizer tagHelperLocalizer) : - base(jsonSerializer, generator, encoder, serviceProvider, l, - tagHelperLocalizer) + public AbpDateRangePickerTagHelperService( + IJsonSerializer jsonSerializer, IHtmlGenerator generator, + HtmlEncoder encoder, + IServiceProvider serviceProvider, + IStringLocalizer l, + IAbpTagHelperLocalizer tagHelperLocalizer, + IClock clock) : + base(jsonSerializer, generator, encoder, serviceProvider, l, tagHelperLocalizer, clock) { } @@ -34,7 +38,7 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ { if (TagHelper.AspForStart != null) { - var startDateAttributes = new TagHelperAttributeList { { "data-start-date", "true" }, { "type", "hidden" } }; + var startDateAttributes = new TagHelperAttributeList { { "data-hidden-datepicker", "true" }, { "data-start-date", "true" }, { "type", "hidden" } }; StartDateTagHelper = new InputTagHelper(Generator) { ViewContext = TagHelper.ViewContext, @@ -42,12 +46,29 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ InputTypeName = "hidden" }; + if (Clock.SupportsMultipleTimezone) + { + if (TagHelper.AspForStart.Model is DateTime dateTime) + { + StartDateTagHelper.Format = "{0:O}"; + StartDateTagHelper.Value = Clock.ConvertToUserTime(dateTime).ToString("O"); + startDateAttributes.Add("value", StartDateTagHelper.Value); + } + + if (TagHelper.AspForStart.Model is DateTimeOffset dateTimeOffset) + { + StartDateTagHelper.Format = "{0:O}"; + StartDateTagHelper.Value = Clock.ConvertToUserTime(dateTimeOffset).UtcDateTime.ToString("O"); + startDateAttributes.Add("value", StartDateTagHelper.Value); + } + } + StartDateTagHelperOutput = await StartDateTagHelper.ProcessAndGetOutputAsync(startDateAttributes, context, "input"); } if (TagHelper.AspForEnd != null) { - var endDateAttributes = new TagHelperAttributeList { { "data-end-date", "true" }, { "type", "hidden" } }; + var endDateAttributes = new TagHelperAttributeList { { "data-hidden-datepicker", "true" }, { "data-end-date", "true" }, { "type", "hidden" } }; EndDateTagHelper = new InputTagHelper(Generator) { ViewContext = TagHelper.ViewContext, @@ -55,6 +76,23 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ InputTypeName = "hidden" }; + if (Clock.SupportsMultipleTimezone) + { + if (TagHelper.AspForEnd.Model is DateTime dateTime) + { + EndDateTagHelper.Format = "{0:O}"; + EndDateTagHelper.Value = Clock.ConvertToUserTime(dateTime).ToString("O"); + endDateAttributes.Add("value", EndDateTagHelper.Value); + } + + if (TagHelper.AspForEnd.Model is DateTimeOffset dateTimeOffset) + { + EndDateTagHelper.Format = "{0:O}"; + EndDateTagHelper.Value = Clock.ConvertToUserTime(dateTimeOffset).UtcDateTime.ToString("O"); + endDateAttributes.Add("value", EndDateTagHelper.Value); + } + } + EndDateTagHelperOutput = await EndDateTagHelper.ProcessAndGetOutputAsync(endDateAttributes, context, "input"); } @@ -78,7 +116,7 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ protected override int GetOrder() { - return TagHelper.Order; + return TagHelper.AspForStart?.Metadata.Order ?? 0; } protected override void AddBaseTagAttributes(TagHelperAttributeList attributes) @@ -92,7 +130,7 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ attributes.Add("data-start-date", convert); } } - + if (TagHelper.AspForEnd?.Model != null && SupportedInputTypes.TryGetValue(TagHelper.AspForEnd.Metadata.ModelType, out var convertFuncEnd)) { @@ -113,4 +151,4 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ { return TagHelper.AspForStart ?? TagHelper.AspForEnd; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js index 9bba9ee9a9..d232dbd28a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js @@ -55,7 +55,7 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f function _createContainer() { _removeContainer(); - _$modalContainer = $('
'); + _$modalContainer = $('
'); var existsModals = $('[id^="Abp_Modal_"]'); if (existsModals.length) { existsModals.last().after(_$modalContainer) @@ -110,7 +110,7 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f _onOpenCallbacks.triggerAll(_publicApi); - if ($firstVisibleInput.data("datepicker")) { + if ($firstVisibleInput.data("datepicker") || $firstVisibleInput.data("daterangepicker")) { return; //don't pop-up date pickers... } 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 9bbf0abd28..bcb043a196 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 @@ -511,22 +511,19 @@ var abp = abp || {}; } }; - var ISOStringToDateTimeLocaleString = function (format) { - return function (data) { - var date = luxon - .DateTime - .fromISO(data, { - locale: abp.localization.currentCulture.name - }); - return format ? date.toLocaleString(format) : date.toLocaleString(); - }; + datatables.defaultRenderers['date'] = function (value) { + if (!value) { + return value; + } else { + return abp.clock.normalizeToLocaleString(value, { year: 'numeric', month: '2-digit', day: '2-digit' }); + } }; - datatables.defaultRenderers['date'] = function (value) { + datatables.defaultRenderers['time'] = function (value) { if (!value) { return value; } else { - return (ISOStringToDateTimeLocaleString())(value); + return abp.clock.normalizeToLocaleString(value, { hour: '2-digit', minute: '2-digit', second: '2-digit' }); } }; @@ -534,7 +531,7 @@ var abp = abp || {}; if (!value) { return value; } else { - return (ISOStringToDateTimeLocaleString(luxon.DateTime.DATETIME_SHORT))(value); + return abp.clock.normalizeToLocaleString(value); } }; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.css b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.css index 08bdc5d283..de679b468a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.css +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.css @@ -10,3 +10,8 @@ .dataTable tbody tr td div.dropdown ul.dropdown-menu li { cursor: pointer; } + +.abp-action-button ui.dropdown-menu[data-popper-reference-hidden]{ + visibility: hidden; + pointer-events: none; +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.min.css b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.min.css index ffc3d272a3..cd5ab5591b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.min.css +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.min.css @@ -1 +1 @@ -.dataTable{width:100% !important;border-spacing:0 !important;}.table td,.table th{padding:8px 10px;}.dataTable tbody tr td button{cursor:pointer;}.dataTable tbody tr td div.dropdown ul.dropdown-menu li{cursor:pointer;} +.dataTable{width:100%!important;border-spacing:0!important}.table td,.table th{padding:8px 10px}.dataTable tbody tr td button{cursor:pointer}.dataTable tbody tr td div.dropdown ul.dropdown-menu li{cursor:pointer}.abp-action-button ui.dropdown-menu[data-popper-reference-hidden]{visibility:hidden;pointer-events:none} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.scss b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.scss index 0ca0771faf..d2498b3cc7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.scss +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-styles.scss @@ -27,3 +27,10 @@ } } } + +.abp-action-button { + ui.dropdown-menu[data-popper-reference-hidden] { + visibility: hidden; + pointer-events: none; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js index 01fe50dec3..e10ceefbf9 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js @@ -752,4 +752,41 @@ $(function () { abp.dom.initializers.initializeDateRangePickers($('body')); }); -})(jQuery); \ No newline at end of file + + $.fn.handleDatepicker = function (datepickerSelector) { + var $this = $(this); + var datepickers = $this.find(datepickerSelector); + $this.find('input[class~="hidden-datepicker"]').remove(); + datepickers.each(function () { + var $this = $(this); + var datepicker = $this.data('daterangepicker'); + if (!datepicker) { + return; + } + if ($this.val() === '') { + return; + } + var name = $this.attr('name') || $this.data('name'); + $this.data('name', name).removeAttr('name'); + if (datepicker.singleDatePicker) { + var startDate = abp.clock.normalizeToString(datepicker.startDate.toDate()); + var startDateInput = $('').attr('type', 'hidden').attr('name', name).val(startDate).addClass('hidden-datepicker'); + $this.after(startDateInput); + } else { + if ($this.data('start-date')) { + var startDate = abp.clock.normalizeToString(datepicker.startDate.toDate()); + var startDateInput = $('').attr('type', 'hidden').attr('name', name).val(startDate).addClass('hidden-datepicker'); + $this.after(startDateInput); + } + if ($this.data('end-date')) { + var endDate = abp.clock.normalizeToString(datepicker.endDate.toDate()); + var endDateInput = $('').attr('type', 'hidden').attr('name', name).val(endDate).addClass('hidden-datepicker'); + $this.after(endDateInput); + } + } + }); + + return this; + }; + +})(jQuery); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/AbpThemingOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/AbpThemingOptions.cs index 1197ad6e53..bf999be982 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/AbpThemingOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI/Volo/Abp/AspNetCore/Mvc/UI/Theming/AbpThemingOptions.cs @@ -6,6 +6,12 @@ public class AbpThemingOptions public string? DefaultThemeName { get; set; } + /// + /// If set, the base element will be added to the head element of the page. + /// eg: + /// + public string? BaseUrl { get; set; } + public AbpThemingOptions() { Themes = new ThemeDictionary(); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs index 56acc2f745..548981053d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcOptions.cs @@ -16,6 +16,8 @@ public class AbpAspNetCoreMvcOptions public bool ExposeIntegrationServices { get; set; } = false; + public bool ExposeClientProxyServices { get; set; } = false; + public bool AutoModelValidation { get; set; } public bool EnableRazorRuntimeCompilationOnDevelopment { get; set; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs index 7f41f73165..73edea9fdf 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs @@ -311,7 +311,32 @@ public class AbpApplicationConfigurationAppService : ApplicationService, IAbpApp protected virtual async Task GetTimingConfigAsync() { - var windowsTimeZoneId = await _settingProvider.GetOrNullAsync(TimingSettingNames.TimeZone); + var timeZone = await _settingProvider.GetOrNullAsync(TimingSettingNames.TimeZone); + + string? timeZoneId = null; + string? timeZoneName = null; + if (!timeZone.IsNullOrWhiteSpace()) + { + try + { + if (_timezoneProvider.GetIanaTimezones().Any(x => x.Value == timeZone)) + { + timeZoneId = _timezoneProvider.IanaToWindows(timeZone); + timeZoneName = timeZone; + } + else if (_timezoneProvider.GetWindowsTimezones().Any(x => x.Value == timeZone)) + { + timeZoneId = timeZone; + timeZoneName = _timezoneProvider.WindowsToIana(timeZone); + } + } + catch (Exception ex) + { + timeZoneId = null; + timeZoneName = null; + Logger.LogWarning(ex, $"Exception occurred while getting timezone({timeZone}) information"); + } + } return new TimingDto { @@ -319,13 +344,11 @@ public class AbpApplicationConfigurationAppService : ApplicationService, IAbpApp { Windows = new WindowsTimeZone { - TimeZoneId = windowsTimeZoneId + TimeZoneId = timeZoneId }, Iana = new IanaTimeZone { - TimeZoneName = windowsTimeZoneId.IsNullOrWhiteSpace() - ? null - : _timezoneProvider.WindowsToIana(windowsTimeZoneId!) + TimeZoneName = timeZoneName } } }; diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs index 2cc051ba62..8fe801b9d5 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -99,6 +100,7 @@ public class AbpRemoteStreamContentModelBinder : IModelBin { var form = await request.ReadFormAsync(); + var useMemoryStream = form.Files.Count > 1; foreach (var file in form.Files) { // If there is an in the form and is left blank. @@ -109,13 +111,27 @@ public class AbpRemoteStreamContentModelBinder : IModelBin if (file.Name.Equals(modelName, StringComparison.OrdinalIgnoreCase)) { - postedFiles.Add(new RemoteStreamContent(file.OpenReadStream(), file.FileName, file.ContentType, file.Length).As()); + if (useMemoryStream) + { + var memoryStream = new MemoryStream(); + await file.OpenReadStream().CopyToAsync(memoryStream); + memoryStream.Position = 0; + postedFiles.Add(new RemoteStreamContent(memoryStream, file.FileName, file.ContentType, file.Length, disposeStream: false).As()); + bindingContext.HttpContext.Response.OnCompleted(async () => + { + await memoryStream.DisposeAsync(); + }); + } + else + { + postedFiles.Add(new RemoteStreamContent(file.OpenReadStream(), file.FileName, file.ContentType, file.Length, disposeStream: false).As()); + } } } } else if (bindingContext.IsTopLevelObject) { - postedFiles.Add(new RemoteStreamContent(request.Body, null, request.ContentType, request.ContentLength).As()); + postedFiles.Add(new RemoteStreamContent(request.Body, null, request.ContentType, request.ContentLength, disposeStream: false).As()); } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs index 3d3a71958a..31ba046250 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/AbpServiceConvention.cs @@ -74,16 +74,29 @@ public class AbpServiceConvention : IAbpServiceConvention, ITransientDependency protected virtual void RemoveIntegrationControllersIfNotExposed(ApplicationModel application) { - if (Options.ExposeIntegrationServices) + if (!Options.ExposeIntegrationServices) { - return; + var integrationControllers = GetControllers(application) + .Where(c => IntegrationServiceAttribute.IsDefinedOrInherited(c.ControllerType)) + .ToArray(); + + application.Controllers.RemoveAll(integrationControllers); + } + + if (!Options.ExposeClientProxyServices) + { + var clientProxyServiceControllers = GetControllers(application) + .Where(c => IsClientProxyService(c.ControllerType)) + .ToArray(); + + application.Controllers.RemoveAll(clientProxyServiceControllers); } - - var integrationControllers = GetControllers(application) - .Where(c => IntegrationServiceAttribute.IsDefinedOrInherited(c.ControllerType)) - .ToArray(); + } - application.Controllers.RemoveAll(integrationControllers); + protected virtual bool IsClientProxyService(Type controllerType) + { + return typeof(IApplicationService).IsAssignableFrom(controllerType) && + controllerType.GetBaseClasses().Any(x => x.IsGenericType && x.GetGenericTypeDefinition().FullName!.StartsWith("Volo.Abp.Http.Client.ClientProxying.ClientProxyBase")); } protected virtual IList GetControllers(ApplicationModel application) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs index 8c6edd2eb0..f2bac81316 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Json.SystemTextJson.JsonConverters; +using Volo.Abp.Json.SystemTextJson.Modifiers; namespace Volo.Abp.AspNetCore.Mvc.Json; @@ -26,6 +27,13 @@ public static class MvcCoreBuilderExtensions options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(rootServiceProvider .GetRequiredService>()); + + var dateTimeConverter = rootServiceProvider.GetRequiredService(); + var nullableDateTimeConverter = rootServiceProvider.GetRequiredService(); + + options.JsonSerializerOptions.TypeInfoResolver.As().Modifiers.Add( + new AbpDateTimeConverterModifier(dateTimeConverter, nullableDateTimeConverter) + .CreateModifyAction()); }); return builder; diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs index b4d5d4499c..b9142b5aed 100644 --- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.RequestLocalization; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.StaticAssets; +using Microsoft.AspNetCore.Timing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; @@ -114,7 +115,7 @@ public static class AbpApplicationBuilderExtensions return app.UseMiddleware(); } - [Obsolete("Replace with AbpClaimsTransformation")] + [Obsolete("Use the TransformAbpClaims extension method from IServiceCollection instead.")] public static IApplicationBuilder UseAbpClaimsMap(this IApplicationBuilder app) { return app.UseMiddleware(); @@ -269,4 +270,14 @@ public static class AbpApplicationBuilderExtensions return app; } + + /// + /// Use this middleware after middleware. + /// + /// + /// + public static IApplicationBuilder UseAbpTimeZone(this IApplicationBuilder app) + { + return app.UseMiddleware(); + } } diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Timing/AbpTimeZoneMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Timing/AbpTimeZoneMiddleware.cs new file mode 100644 index 0000000000..8ee803feb0 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Timing/AbpTimeZoneMiddleware.cs @@ -0,0 +1,82 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Middleware; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; +using Volo.Abp.Timing; +using Volo.Abp.Users; + +namespace Microsoft.AspNetCore.Timing; + +public class AbpTimeZoneMiddleware : AbpMiddlewareBase, ITransientDependency +{ + public async override Task InvokeAsync(HttpContext context, RequestDelegate next) + { + if (!context.RequestServices.GetRequiredService().SupportsMultipleTimezone) + { + await next(context); + return; + } + + // Try to get the timezone from the setting system first + var settingProvider = context.RequestServices.GetRequiredService(); + var timezone = await settingProvider.GetOrNullAsync(TimingSettingNames.TimeZone); + + if (timezone.IsNullOrWhiteSpace()) + { + // Try to get the timezone from the HTTP request if the setting is not available + timezone = await GetTimezoneFromRequestAsync(context); + } + + if (timezone.IsNullOrWhiteSpace()) + { + // Try to get the timezone from the current running server if the setting and request are not available + timezone = await GetLocalTimeZoneAsync(); + } + + var currentTimezoneProvider = context.RequestServices.GetRequiredService(); + using (currentTimezoneProvider.Change(timezone)) + { + await next(context); + } + } + + protected virtual async Task GetTimezoneFromRequestAsync(HttpContext context) + { + var timeZoneSources = new Func>[] + { + ctx => Task.FromResult(ctx.Request.Headers[TimeZoneConsts.DefaultTimeZoneKey].FirstOrDefault()), + ctx => Task.FromResult(ctx.Request.Query[TimeZoneConsts.DefaultTimeZoneKey].ToString()), + async ctx => ctx.Request.HasFormContentType + ? (await ctx.Request.ReadFormAsync())[TimeZoneConsts.DefaultTimeZoneKey].ToString() + : null, + ctx => Task.FromResult(ctx.Request.Cookies[TimeZoneConsts.DefaultTimeZoneKey]?.ToString()), + }; + + foreach (var source in timeZoneSources) + { + var timezone = await source(context); + if (!string.IsNullOrEmpty(timezone)) + { + return timezone; + } + } + + return null; + } + + protected virtual Task GetLocalTimeZoneAsync() + { + if (TimeZoneInfo.Local.HasIanaId) + { + return Task.FromResult(TimeZoneInfo.Local.Id); + } + + return TimeZoneInfo.TryConvertWindowsIdToIanaId(TimeZoneInfo.Local.Id, out var ianaName) + ? Task.FromResult(ianaName) + : Task.FromResult(null); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs index 2104edab0a..70fad0d19e 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs @@ -11,7 +11,7 @@ using Volo.Abp.Security.Claims; namespace Volo.Abp.AspNetCore.Security.Claims; -[Obsolete("Replace with AbpClaimsTransformation")] +[Obsolete("Use the TransformAbpClaims extension method from IServiceCollection instead.")] public class AbpClaimsMapMiddleware : AbpMiddlewareBase, ITransientDependency { public async override Task InvokeAsync(HttpContext context, RequestDelegate next) diff --git a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs index 3357d8f95c..e834b3d00d 100644 --- a/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs +++ b/framework/src/Volo.Abp.Autofac/Autofac/Builder/AbpRegistrationBuilderExtensions.cs @@ -38,7 +38,7 @@ public static class AbpRegistrationBuilderExtensions } registrationBuilder = registrationBuilder.EnablePropertyInjection(moduleContainer, implementationType); - registrationBuilder = registrationBuilder.InvokeRegistrationActions(registrationActionList, serviceType, implementationType); + registrationBuilder = registrationBuilder.InvokeRegistrationActions(registrationActionList, serviceType, implementationType, serviceDescriptor.ServiceKey); return registrationBuilder; } @@ -69,10 +69,11 @@ public static class AbpRegistrationBuilderExtensions this IRegistrationBuilder registrationBuilder, ServiceRegistrationActionList registrationActionList, Type serviceType, - Type implementationType) + Type implementationType, + object? serviceKey = null) where TActivatorData : ReflectionActivatorData { - var serviceRegistredArgs = new OnServiceRegistredContext(serviceType, implementationType); + var serviceRegistredArgs = new OnServiceRegistredContext(serviceType, implementationType, serviceKey); foreach (var registrationAction in registrationActionList) { diff --git a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs index ee747e4611..345a69703f 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs @@ -25,13 +25,8 @@ public class AbpBackgroundJobsHangfireModule : AbpModule if (!options.IsJobExecutionEnabled) { var hangfireOptions = context.ServiceProvider.GetRequiredService>().Value; - hangfireOptions.BackgroundJobServerFactory = CreateOnlyEnqueueJobServer; + context.ServiceProvider.GetRequiredService(); + hangfireOptions.BackgroundJobServerFactory = _ => null; } } - - private BackgroundJobServer? CreateOnlyEnqueueJobServer(IServiceProvider serviceProvider) - { - serviceProvider.GetRequiredService(); - return null; - } } diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs index 1dbe4a6dcc..bdc28c7ca0 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; @@ -120,46 +121,44 @@ public class JobQueue : IJobQueue ChannelAccessor?.Dispose(); } - protected virtual Task EnsureInitializedAsync() + protected virtual async Task EnsureInitializedAsync() { if (ChannelAccessor != null && ChannelAccessor.Channel.IsOpen) { - return Task.CompletedTask; + return; } - ChannelAccessor = ChannelPool.Acquire( + ChannelAccessor = await ChannelPool.AcquireAsync( ChannelPrefix + QueueConfiguration.QueueName, QueueConfiguration.ConnectionName ); - var result = QueueConfiguration.Declare(ChannelAccessor.Channel); + var result = await QueueConfiguration.DeclareAsync(ChannelAccessor.Channel); Logger.LogDebug($"RabbitMQ Queue '{QueueConfiguration.QueueName}' has {result.MessageCount} messages and {result.ConsumerCount} consumers."); // Declare delayed queue - QueueConfiguration.DeclareDelayed(ChannelAccessor.Channel); + await QueueConfiguration.DeclareDelayedAsync(ChannelAccessor.Channel); if (AbpBackgroundJobOptions.IsJobExecutionEnabled) { if (QueueConfiguration.PrefetchCount.HasValue) { - ChannelAccessor.Channel.BasicQos(0, QueueConfiguration.PrefetchCount.Value, false); + await ChannelAccessor.Channel.BasicQosAsync(0, QueueConfiguration.PrefetchCount.Value, false); } - + Consumer = new AsyncEventingBasicConsumer(ChannelAccessor.Channel); - Consumer.Received += MessageReceived; - + Consumer.ReceivedAsync += MessageReceived; + //TODO: What BasicConsume returns? - ChannelAccessor.Channel.BasicConsume( + await ChannelAccessor.Channel.BasicConsumeAsync( queue: QueueConfiguration.QueueName, autoAck: false, consumer: Consumer ); } - - return Task.CompletedTask; } - protected virtual Task PublishAsync( + protected virtual async Task PublishAsync( TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) @@ -167,29 +166,27 @@ public class JobQueue : IJobQueue //TODO: How to handle priority var routingKey = QueueConfiguration.QueueName; - var basicProperties = CreateBasicPropertiesToPublish(); + var basicProperties = new BasicProperties + { + Persistent = true + }; if (delay.HasValue) { routingKey = QueueConfiguration.DelayedQueueName; - basicProperties.Expiration = delay.Value.TotalMilliseconds.ToString(); + basicProperties.Expiration = delay.Value.TotalMilliseconds.ToString(CultureInfo.InvariantCulture); } - ChannelAccessor!.Channel.BasicPublish( - exchange: "", - routingKey: routingKey, - basicProperties: basicProperties, - body: Serializer.Serialize(args!) - ); - - return Task.CompletedTask; - } - - protected virtual IBasicProperties CreateBasicPropertiesToPublish() - { - var properties = ChannelAccessor!.Channel.CreateBasicProperties(); - properties.Persistent = true; - return properties; + if (ChannelAccessor != null) + { + await ChannelAccessor.Channel.BasicPublishAsync( + exchange: "", + routingKey: routingKey, + mandatory: false, + basicProperties: basicProperties, + body: Serializer.Serialize(args!) + ); + } } protected virtual async Task MessageReceived(object sender, BasicDeliverEventArgs ea) @@ -205,17 +202,17 @@ public class JobQueue : IJobQueue try { await JobExecuter.ExecuteAsync(context); - ChannelAccessor!.Channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false); + await ChannelAccessor!.Channel.BasicAckAsync(deliveryTag: ea.DeliveryTag, multiple: false); } catch (BackgroundJobExecutionException) { //TODO: Reject like that? - ChannelAccessor!.Channel.BasicReject(deliveryTag: ea.DeliveryTag, requeue: true); + await ChannelAccessor!.Channel.BasicRejectAsync(deliveryTag: ea.DeliveryTag, requeue: true); } catch (Exception) { //TODO: Reject like that? - ChannelAccessor!.Channel.BasicReject(deliveryTag: ea.DeliveryTag, requeue: false); + await ChannelAccessor!.Channel.BasicRejectAsync(deliveryTag: ea.DeliveryTag, requeue: false); } } } diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueConfiguration.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueConfiguration.cs index 9425cd0604..c6418f52f7 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueConfiguration.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueueConfiguration.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using RabbitMQ.Client; using Volo.Abp.RabbitMQ; @@ -34,15 +35,15 @@ public class JobQueueConfiguration : QueueDeclareConfiguration DelayedQueueName = delayedQueueName; } - public virtual QueueDeclareOk DeclareDelayed(IModel channel) + public virtual async Task DeclareDelayedAsync(IChannel channel) { - var delayedArguments = new Dictionary(Arguments) + var delayedArguments = new Dictionary(Arguments) { ["x-dead-letter-routing-key"] = QueueName, ["x-dead-letter-exchange"] = string.Empty }; - return channel.QueueDeclare( + return await channel.QueueDeclareAsync( queue: DelayedQueueName, durable: Durable, exclusive: Exclusive, diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs index 2577181143..433ac699d2 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/AbpBackgroundWorkersHangfireModule.cs @@ -1,5 +1,4 @@ -using System; -using Hangfire; +using Hangfire; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp.Hangfire; @@ -23,17 +22,12 @@ public class AbpBackgroundWorkersHangfireModule : AbpModule if (!options.IsEnabled) { var hangfireOptions = context.ServiceProvider.GetRequiredService>().Value; - hangfireOptions.BackgroundJobServerFactory = CreateOnlyEnqueueJobServer; + context.ServiceProvider.GetRequiredService(); + hangfireOptions.BackgroundJobServerFactory = _ => null; } context.ServiceProvider .GetRequiredService() .Initialize(); } - - private BackgroundJobServer? CreateOnlyEnqueueJobServer(IServiceProvider serviceProvider) - { - serviceProvider.GetRequiredService(); - return null; - } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 6f5c89a320..a2c7193437 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -357,10 +357,10 @@ public abstract class AbpCrudPageBase< } } - protected virtual Task CloseCreateModalAsync() + protected virtual async Task CloseCreateModalAsync() { + await InvokeAsync(CreateModal!.Hide); NewEntity = new TCreateViewModel(); - return InvokeAsync(CreateModal!.Hide); } protected virtual Task ClosingCreateModal(ModalClosingEventArgs eventArgs) @@ -474,11 +474,11 @@ public abstract class AbpCrudPageBase< protected virtual async Task OnCreatedEntityAsync() { - NewEntity = new TCreateViewModel(); await GetEntitiesAsync(); await InvokeAsync(CreateModal!.Hide); await Notify.Success(GetCreateMessage()); + NewEntity = new TCreateViewModel(); } protected virtual string GetCreateMessage() @@ -552,6 +552,11 @@ public abstract class AbpCrudPageBase< protected virtual async Task OnDeletedEntityAsync() { + if (Entities.Count == 1 && CurrentPage > 1) + { + CurrentPage -= 1; + } + await GetEntitiesAsync(); await InvokeAsync(StateHasChanged); await Notify.Success(GetDeleteMessage()); diff --git a/framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiObjectExtensionPropertyInfoExtensions.cs b/framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiObjectExtensionPropertyInfoExtensions.cs index 2773b88bed..fa4994e2f9 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiObjectExtensionPropertyInfoExtensions.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/BlazoriseUiObjectExtensionPropertyInfoExtensions.cs @@ -233,19 +233,17 @@ public static class BlazoriseUiObjectExtensionPropertyInfoExtensions switch (dataTypeAttribute.DataType) { case DataType.Password: - return typeof(TextExtensionProperty<,>); - case DataType.Date: - return typeof(DateTimeExtensionProperty<,>); - case DataType.Time: - return typeof(TimeExtensionProperty<,>); case DataType.EmailAddress: - return typeof(TextExtensionProperty<,>); case DataType.Url: - return typeof(TextExtensionProperty<,>); case DataType.PhoneNumber: return typeof(TextExtensionProperty<,>); + case DataType.Date: case DataType.DateTime: return typeof(DateTimeExtensionProperty<,>); + case DataType.Time: + return typeof(TimeExtensionProperty<,>); + case DataType.MultilineText: + return typeof(TextAreaExtensionProperty<,>); } } diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextAreaExtensionProperty.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextAreaExtensionProperty.razor new file mode 100644 index 0000000000..6acf7ba69d --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextAreaExtensionProperty.razor @@ -0,0 +1,19 @@ +@typeparam TEntity +@typeparam TResourceType +@using Volo.Abp.BlazoriseUI +@using Volo.Abp.Localization +@inherits ExtensionPropertyComponentBase + +@if (PropertyInfo != null && Entity != null) +{ + + + @PropertyInfo.GetLocalizedDisplayName(StringLocalizerFactory) + + + + + + + +} diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextAreaExtensionProperty.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextAreaExtensionProperty.razor.cs new file mode 100644 index 0000000000..853d1e7372 --- /dev/null +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/TextAreaExtensionProperty.razor.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Data; + +namespace Volo.Abp.BlazoriseUI.Components.ObjectExtending; +public partial class TextAreaExtensionProperty + where TEntity : IHasExtraProperties +{ + protected string? Value { + get { + return PropertyInfo.GetTextInputValueOrNull(Entity.GetProperty(PropertyInfo.Name)); + } + set { + Entity.SetProperty(PropertyInfo.Name, value, validate: false); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/PageAlert.razor b/framework/src/Volo.Abp.BlazoriseUI/Components/PageAlert.razor index 1a3809c985..51b12dd9f5 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/PageAlert.razor +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/PageAlert.razor @@ -5,16 +5,12 @@ { @alert.AlertMessage.Title - @if (alert.AlertMessage.Dismissible) - { - - } } @alert.AlertMessage.Text @if (alert.AlertMessage.Dismissible) - { - + { + } } diff --git a/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs index 1c04fdb755..d20c8d1214 100644 --- a/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Aliyun/Volo/Abp/BlobStoring/Aliyun/AliyunBlobProvider.cs @@ -86,7 +86,7 @@ public class AliyunBlobProvider : BlobProviderBase, ITransientDependency return null; } var result = ossClient.GetObject(containerName, blobName); - return await TryCopyToMemoryStreamAsync(result.Content, args.CancellationToken); + return result.ResponseStream; } protected virtual string GetContainerName(BlobProviderArgs args) diff --git a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs index 00a82a0f3e..7c520da471 100644 --- a/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Aws/Volo/Abp/BlobStoring/Aws/AwsBlobProvider.cs @@ -103,7 +103,7 @@ public class AwsBlobProvider : BlobProviderBase, ITransientDependency Key = blobName }); - return await TryCopyToMemoryStreamAsync(response.ResponseStream, args.CancellationToken); + return response.ResponseStream; } } diff --git a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs index 5d45e749ea..bea55c624d 100644 --- a/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs @@ -66,8 +66,7 @@ public class AzureBlobProvider : BlobProviderBase, ITransientDependency } var blobClient = GetBlobClient(args, blobName); - var download = await blobClient.DownloadAsync(); - return await TryCopyToMemoryStreamAsync(download.Value.Content, args.CancellationToken); + return await blobClient.OpenReadAsync(cancellationToken: args.CancellationToken); } protected virtual BlobClient GetBlobClient(BlobProviderArgs args, string blobName) diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs index a221441749..2a410005db 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs @@ -70,13 +70,7 @@ public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency return await Policy.Handle() .WaitAndRetryAsync(2, retryCount => TimeSpan.FromSeconds(retryCount)) - .ExecuteAsync(async () => - { - using (var fileStream = File.OpenRead(filePath)) - { - return await TryCopyToMemoryStreamAsync(fileStream, args.CancellationToken); - } - }); + .ExecuteAsync(() => Task.FromResult(File.OpenRead(filePath))); } protected virtual Task ExistsAsync(string filePath) diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs index de5f60ee4e..632bfa416e 100644 --- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs +++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs @@ -1,7 +1,5 @@ using Microsoft.Extensions.DependencyInjection; using System; -using Microsoft.Extensions.Caching.Hybrid; -using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Caching.Hybrid; using Volo.Abp.Json; using Volo.Abp.Modularity; diff --git a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/Hybrid/AbpHybridCache.cs b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/Hybrid/AbpHybridCache.cs index 2894af9f3d..66506a0b56 100644 --- a/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/Hybrid/AbpHybridCache.cs +++ b/framework/src/Volo.Abp.Caching/Volo/Abp/Caching/Hybrid/AbpHybridCache.cs @@ -75,7 +75,7 @@ public class AbpHybridCache : IHybridCache : IHybridCache>.Instance; KeyNormalizer = keyNormalizer; @@ -215,10 +215,15 @@ public class AbpHybridCache : IHybridCache(bytes, 0, bytes.Length));; + // Because HybridCache wraps the cache in L2(distributed cache), we can’t unwrap it directly and can only retrieve the value through its API + return await HybridCache.GetOrCreateAsync( + key: NormalizeKey(key), + factory: async cancel => await factory(), + options: optionsFactory?.Invoke(), + tags: null, + cancellationToken: token); } value = await factory(); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs index 76bc82f570..3ee7cfdea3 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs @@ -66,7 +66,14 @@ public class BundlingService : IBundlingService, ITransientDependency var frameworkVersion = GetTargetFrameworkVersion(projectFilePath, projectType); var projectName = Path.GetFileNameWithoutExtension(projectFilePath); - var assemblyFilePath = projectType == BundlingConsts.WebAssembly? PathHelper.GetWebAssemblyFilePath(directory, frameworkVersion, projectName) : PathHelper.GetMauiBlazorAssemblyFilePath(directory, projectName); + var assemblyFilePath = projectType == BundlingConsts.WebAssembly + ? PathHelper.GetWebAssemblyFilePath(directory, frameworkVersion, projectName) + : PathHelper.GetMauiBlazorAssemblyFilePath(directory, projectName); + if (assemblyFilePath == null) + { + throw new BundlingException("No assembly file found. Please build the project first."); + } + var startupModule = GetStartupModule(assemblyFilePath); var bundleDefinitions = new List(); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/PathHelper.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/PathHelper.cs index 1b6b56adab..4d3ff3ee77 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/PathHelper.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/PathHelper.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Linq; namespace Volo.Abp.Cli.Bundling; @@ -13,12 +14,16 @@ static internal class PathHelper static internal string GetWebAssemblyFilePath(string directory, string frameworkVersion, string projectFileName) { var outputDirectory = Path.Combine(directory, "bin", "Debug", frameworkVersion); - return Path.Combine(outputDirectory, projectFileName + ".dll"); + var path = Path.Combine(outputDirectory, projectFileName + ".dll"); + return !File.Exists(path) ? null : path; } static internal string GetMauiBlazorAssemblyFilePath(string directory, string projectFileName) { - return Directory.GetFiles(directory, "*.dll", SearchOption.AllDirectories).First(f => !f.Contains("android") && f.EndsWith(projectFileName + ".dll")); + return Directory.GetFiles(Path.Combine(directory, "bin"), "*.dll", SearchOption.AllDirectories).FirstOrDefault(f => + !f.Contains("android") && + !f.Contains("windows10") && + f.EndsWith(projectFileName + ".dll", StringComparison.OrdinalIgnoreCase)); } static internal string GetWwwRootPath(string directory) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs index 8d77675c3c..d968ae6b12 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliConsts.cs @@ -2,24 +2,24 @@ public static class CliConsts { - public const string Command = "AbpCliCommand"; + public static string Command = "AbpCliCommand"; - public const string BranchPrefix = "branch@"; + public static string BranchPrefix = "branch@"; - public const string DocsLink = "https://abp.io/docs"; + public static string DocsLink = "https://abp.io/docs"; - public const string HttpClientName = "AbpHttpClient"; + public static string HttpClientName = "AbpHttpClient"; - public const string GithubHttpClientName = "GithubHttpClient"; + public static string GithubHttpClientName = "GithubHttpClient"; - public const string LogoutUrl = CliUrls.WwwAbpIo + "api/license/logout"; + public static string LogoutUrl = CliUrls.WwwAbpIo + "api/license/logout"; - public const string LicenseCodePlaceHolder = @""; + public static string LicenseCodePlaceHolder = @""; - public const string AppSettingsJsonFileName = "appsettings.json"; + public static string AppSettingsJsonFileName = "appsettings.json"; + + public static string AppSettingsSecretJsonFileName = "appsettings.secrets.json"; - public const string AppSettingsSecretJsonFileName = "appsettings.secrets.json"; - public static class MemoryKeys { public const string LatestCliVersionCheckDate = "LatestCliVersionCheckDate"; diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs index 35ae34b895..b1c0cb2a0d 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs @@ -5,19 +5,33 @@ namespace Volo.Abp.Cli; public static class CliUrls { - public const string WwwAbpIo = WwwAbpIoProduction; - public const string AccountAbpIo = AccountAbpIoProduction; - public const string NuGetRootPath = NuGetRootPathProduction; - public const string LatestVersionCheckFullPath = - "https://raw.githubusercontent.com/abpframework/abp/dev/latest-versions.json"; - - public const string WwwAbpIoProduction = "https://abp.io/"; - public const string AccountAbpIoProduction = "https://account.abp.io/"; - public const string NuGetRootPathProduction = "https://nuget.abp.io/"; - - public const string WwwAbpIoDevelopment = "https://localhost:44328/"; - public const string AccountAbpIoDevelopment = "https://localhost:44333/"; - public const string NuGetRootPathDevelopment = "https://localhost:44373/"; + public static string WwwAbpIo + { + get => WwwAbpIoProduction; + set => WwwAbpIoProduction = value; + } + + public static string AccountAbpIo + { + get => AccountAbpIoProduction; + set => AccountAbpIoProduction = value; + } + + public static string NuGetRootPath + { + get => NuGetRootPathProduction; + set => NuGetRootPathProduction = value; + } + + public static string LatestVersionCheckFullPath = "https://raw.githubusercontent.com/abpframework/abp/dev/latest-versions.json"; + + public static string WwwAbpIoProduction = "https://abp.io/"; + public static string AccountAbpIoProduction = "https://account.abp.io/"; + public static string NuGetRootPathProduction = "https://nuget.abp.io/"; + + public static string WwwAbpIoDevelopment = "https://localhost:44328/"; + public static string AccountAbpIoDevelopment = "https://localhost:44333/"; + public static string NuGetRootPathDevelopment = "https://localhost:44373/"; public static string GetNuGetServiceIndexUrl(string apiKey) { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs index 9fb647806b..cc13e9d187 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs @@ -68,7 +68,7 @@ public class HelpCommand : IConsoleCommand, ITransientDependency sb.AppendLine("Command List:"); sb.AppendLine(""); - foreach (var command in AbpCliOptions.Commands.ToArray().Where(NotHiddenFromCommandList)) + foreach (var command in AbpCliOptions.Commands.ToArray().Where(NotHiddenFromCommandList).OrderBy(x => x.Key)) { var method = command.Value.GetMethod("GetShortDescription", BindingFlags.Static | BindingFlags.Public); if (method == null) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs index ad0992af4e..8c6df3b0b9 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs @@ -38,24 +38,25 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long) ?? Directory.GetCurrentDirectory(); var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long); + var leptonXVersion = commandLineArgs.Options.GetOrNull(Options.LeptonXVersion.Short, Options.LeptonXVersion.Long); if (updateNuget || !updateNpm) { - await UpdateNugetPackages(commandLineArgs, directory, version); + await UpdateNugetPackages(commandLineArgs, directory, version, leptonXVersion); } if (updateNpm || !updateNuget) { - await UpdateNpmPackages(directory, version); + await UpdateNpmPackages(directory, version, leptonXVersion); } } - private async Task UpdateNpmPackages(string directory, string version) + private async Task UpdateNpmPackages(string directory, string version, string leptonXVersion) { - await _npmPackagesUpdater.Update(directory, version: version); + await _npmPackagesUpdater.Update(directory, version: version, leptonXVersion: leptonXVersion); } - private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory, string version) + private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory, string version, string leptonXVersion) { var solutions = new List(); var givenSolution = commandLineArgs.Options.GetOrNull(Options.SolutionName.Short, Options.SolutionName.Long); @@ -77,7 +78,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency { var solutionName = Path.GetFileName(solution).RemovePostFix(".sln"); - await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll, version: version); + await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll, version: version, leptonXVersion: leptonXVersion); Logger.LogInformation("Volo packages are updated in {SolutionName} solution", solutionName); } @@ -90,7 +91,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency { var projectName = Path.GetFileName(project).RemovePostFix(".csproj"); - await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll, version: version); + await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll, version: version, leptonXVersion: leptonXVersion); Logger.LogInformation("Volo packages are updated in {ProjectName} project", projectName); return; @@ -120,6 +121,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency sb.AppendLine("-sn|--solution-name (Specify the solution name)"); sb.AppendLine("--check-all (Check the new version of each package separately)"); sb.AppendLine("-v|--version (default: latest version)"); + sb.AppendLine("-lv|--leptonx-version (default: latest LeptonX version)"); sb.AppendLine(""); sb.AppendLine("Some examples:"); sb.AppendLine(""); @@ -167,5 +169,11 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency public const string Short = "v"; public const string Long = "version"; } + + public static class LeptonXVersion + { + public const string Short = "lv"; + public const string Long = "leptonx-version"; + } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs index 2c88f1e8c5..d543b43d65 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs @@ -50,7 +50,7 @@ public class NpmPackagesUpdater : ITransientDependency public async Task Update(string rootDirectory, bool includePreviews = false, bool includeReleaseCandidates = false, - bool switchToStable = false, string version = null, bool includePreRc = false) + bool switchToStable = false, string version = null, string leptonXVersion = null, bool includePreRc = false) { var fileList = _packageJsonFileFinder.Find(rootDirectory); @@ -80,6 +80,7 @@ public class NpmPackagesUpdater : ITransientDependency var updated = await UpdatePackagesInFile(file, includePreviews, includeReleaseCandidates, switchToStable, version, + leptonXVersion, includePreRc); packagesUpdated.TryAdd(file, updated); @@ -162,6 +163,7 @@ public class NpmPackagesUpdater : ITransientDependency bool includeReleaseCandidates = false, bool switchToStable = false, string specifiedVersion = null, + string specifiedLeptonXVersion = null, bool includePreRc = false) { var packagesUpdated = false; @@ -177,7 +179,7 @@ public class NpmPackagesUpdater : ITransientDependency foreach (var abpPackage in abpPackages) { var updated = await TryUpdatingPackage(filePath, abpPackage, includePreviews, includeReleaseCandidates, - switchToStable, specifiedVersion, includePreRc); + switchToStable, specifiedVersion, specifiedLeptonXVersion, includePreRc); if (updated) { @@ -188,7 +190,7 @@ public class NpmPackagesUpdater : ITransientDependency var updatedContent = packageJson.ToString(Formatting.Indented); File.WriteAllText(filePath, updatedContent); - + return packagesUpdated; } @@ -199,6 +201,7 @@ public class NpmPackagesUpdater : ITransientDependency bool includeReleaseCandidates = false, bool switchToStable = false, string specifiedVersion = null, + string specifiedLeptonXVersion = null, bool includePreRc = false) { var currentVersion = (string)package.Value; @@ -207,18 +210,36 @@ public class NpmPackagesUpdater : ITransientDependency if (!specifiedVersion.IsNullOrWhiteSpace()) { - if (!SpecifiedVersionExists(specifiedVersion, package)) + if (package.Name.IndexOf("leptonx", StringComparison.InvariantCultureIgnoreCase) > 0 && !specifiedLeptonXVersion.IsNullOrWhiteSpace()) { - return false; - } + if (!SpecifiedVersionExists(specifiedLeptonXVersion, package)) + { + return false; + } - if (SemanticVersion.Parse(specifiedVersion) <= - SemanticVersion.Parse(currentVersion.RemovePreFix("~", "^"))) - { - return false; + if (SemanticVersion.Parse(specifiedLeptonXVersion) <= + SemanticVersion.Parse(currentVersion.RemovePreFix("~", "^"))) + { + return false; + } + + version = specifiedLeptonXVersion.EnsureStartsWith('^'); } + else + { + if (!SpecifiedVersionExists(specifiedVersion, package)) + { + return false; + } - version = specifiedVersion.EnsureStartsWith('^'); + if (SemanticVersion.Parse(specifiedVersion) <= + SemanticVersion.Parse(currentVersion.RemovePreFix("~", "^"))) + { + return false; + } + + version = specifiedVersion.EnsureStartsWith('^'); + } } else { diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs index 4ece393913..924d6041b1 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs @@ -27,7 +27,14 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency Logger = NullLogger.Instance; } - public async Task UpdateSolutionAsync(string solutionPath, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null) + public async Task UpdateSolutionAsync( + string solutionPath, + bool includePreviews = false, + bool includeReleaseCandidates = false, + bool switchToStable = false, + bool checkAll = false, + string version = null, + string leptonXVersion = null) { var projectPaths = ProjectFinder.GetProjectFiles(solutionPath); @@ -58,6 +65,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency latestReleaseCandidateVersionInfo.Version, latestVersionFromMyGet, version, + leptonXVersion, latestStableVersions: latestStableVersions); fs.Seek(0, SeekOrigin.Begin); @@ -75,7 +83,14 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency } } - public async Task UpdateProjectAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null) + public async Task UpdateProjectAsync( + string projectPath, + bool includeNightlyPreviews = false, + bool includeReleaseCandidates = false, + bool switchToStable = false, + bool checkAll = false, + string version = null, + string leptonXVersion = null) { if (checkAll && version.IsNullOrWhiteSpace()) { @@ -102,6 +117,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency latestReleaseCandidateVersionInfo.Version, latestVersionFromMyGet, version, + leptonXVersion, latestStableVersions: latestStableVersions); fs.Seek(0, SeekOrigin.Begin); @@ -166,6 +182,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency SemanticVersion latestNugetReleaseCandidateVersion = null, string latestMyGetVersion = null, string specifiedVersion = null, + string specifiedLeptonXVersion = null, List latestStableVersions = null) { string packageId = null; @@ -222,21 +239,35 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency var leptonXPackageVersion = latestStableVersions? .FirstOrDefault(v => v.Version.Equals(specifiedVersion, StringComparison.InvariantCultureIgnoreCase))?.LeptonX?.Version; - if ((isLeptonXPackage && string.IsNullOrWhiteSpace(leptonXPackageVersion)) || isStudioPackage) + if ((isLeptonXPackage && string.IsNullOrWhiteSpace(leptonXPackageVersion) && specifiedLeptonXVersion.IsNullOrWhiteSpace()) || isStudioPackage) { Logger.LogWarning("Package: {PackageId} could not be updated. Please manually update the package version yourself to prevent version mismatches!", packageId); continue; } - var isLeptonXPackageWithVersion = isLeptonXPackage && !string.IsNullOrWhiteSpace(leptonXPackageVersion); - - if (isLeptonXPackageWithVersion || await SpecifiedVersionExists(specifiedVersion, packageId)) + if (isLeptonXPackage) { - TryUpdatingPackage(isLeptonXPackageWithVersion ? leptonXPackageVersion : specifiedVersion); + var isLeptonXPackageWithVersion = isLeptonXPackage && !string.IsNullOrWhiteSpace(leptonXPackageVersion); + + if (isLeptonXPackageWithVersion || await SpecifiedVersionExists(specifiedLeptonXVersion, packageId)) + { + TryUpdatingPackage(specifiedLeptonXVersion ?? leptonXPackageVersion); + } + else + { + Logger.LogWarning($"Package \"{packageId}\" specified version v{specifiedLeptonXVersion} does not exist!"); + } } else { - Logger.LogWarning("Package \"{PackageId}\" specified version v{SpecifiedVersion} does not exist!", packageId, specifiedVersion); + if (await SpecifiedVersionExists(specifiedVersion, packageId)) + { + TryUpdatingPackage(specifiedVersion); + } + else + { + Logger.LogWarning($"Package \"{packageId}\" specified version v{specifiedVersion} does not exist!"); + } } void TryUpdatingPackage(string versionToUpdate) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs index bc67fac38f..3d6fa77208 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Content/RemoteStreamContent.cs @@ -17,7 +17,6 @@ public class RemoteStreamContent : IRemoteStreamContent public RemoteStreamContent(Stream stream, string? fileName = null, string? contentType = null, long? readOnlyLength = null, bool disposeStream = true) { _stream = stream; - FileName = fileName; if (contentType != null) { @@ -34,10 +33,16 @@ public class RemoteStreamContent : IRemoteStreamContent public virtual void Dispose() { - if (!_disposed && _disposeStream) + if (_disposed) { - _disposed = true; - _stream?.Dispose(); + return; } + + if (_disposeStream) + { + _stream.Dispose(); + } + + _disposed = true; } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceRegistredContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceRegistredContext.cs index 86dad068b6..a1c50c0c64 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceRegistredContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IOnServiceRegistredContext.cs @@ -9,4 +9,6 @@ public interface IOnServiceRegistredContext ITypeList Interceptors { get; } Type ImplementationType { get; } + + object? ServiceKey { get; } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceRegistredContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceRegistredContext.cs index a843b136f6..8491c94e91 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceRegistredContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/OnServiceRegistredContext.cs @@ -13,10 +13,13 @@ public class OnServiceRegistredContext : IOnServiceRegistredContext public virtual Type ImplementationType { get; } - public OnServiceRegistredContext(Type serviceType, [NotNull] Type implementationType) + public virtual object? ServiceKey { get; } + + public OnServiceRegistredContext(Type serviceType, [NotNull] Type implementationType, object? serviceKey = null) { ServiceType = Check.NotNull(serviceType, nameof(serviceType)); ImplementationType = Check.NotNull(implementationType, nameof(implementationType)); + ServiceKey = serviceKey; Interceptors = new TypeList(); } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ServiceConfigurationContext.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ServiceConfigurationContext.cs index 6141777cec..f1e55b85d8 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ServiceConfigurationContext.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ServiceConfigurationContext.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using JetBrains.Annotations; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace Volo.Abp.Modularity; @@ -8,6 +9,13 @@ public class ServiceConfigurationContext { public IServiceCollection Services { get; } + public IConfiguration Configuration { + get { + return _configuration ??= Services.GetConfiguration(); + } + } + private IConfiguration? _configuration; + public IDictionary Items { get; } /// @@ -29,4 +37,4 @@ public class ServiceConfigurationContext Services = Check.NotNull(services, nameof(services)); Items = new Dictionary(); } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/AbpDistributedEntityEventOptions.cs b/framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/AbpDistributedEntityEventOptions.cs index 19af763c85..8109d945bc 100644 --- a/framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/AbpDistributedEntityEventOptions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain.Shared/Volo/Abp/Domain/Entities/Events/Distributed/AbpDistributedEntityEventOptions.cs @@ -4,11 +4,14 @@ public class AbpDistributedEntityEventOptions { public IAutoEntityDistributedEventSelectorList AutoEventSelectors { get; } + public IAutoEntityDistributedEventSelectorList IgnoredEventSelectors { get; } + public EtoMappingDictionary EtoMappings { get; set; } public AbpDistributedEntityEventOptions() { AutoEventSelectors = new AutoEntityDistributedEventSelectorList(); + IgnoredEventSelectors = new AutoEntityDistributedEventSelectorList(); EtoMappings = new EtoMappingDictionary(); } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs index 62d0b5304e..7cea931c12 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheBase.cs @@ -16,12 +16,12 @@ public abstract class EntityCacheBase : where TEntityCacheItem : class { protected IReadOnlyRepository Repository { get; } - protected IDistributedCache Cache { get; } + protected IDistributedCache, TKey> Cache { get; } protected IUnitOfWorkManager UnitOfWorkManager { get; } protected EntityCacheBase( IReadOnlyRepository repository, - IDistributedCache cache, + IDistributedCache, TKey> cache, IUnitOfWorkManager unitOfWorkManager) { Repository = repository; @@ -31,7 +31,7 @@ public abstract class EntityCacheBase : public virtual async Task FindAsync(TKey id) { - return await Cache.GetOrAddAsync( + return (await Cache.GetOrAddAsync( id, async () => { @@ -41,7 +41,7 @@ public abstract class EntityCacheBase : } return MapToCacheItem(await Repository.FindAsync(id))!; - }); + }))?.Value; } public virtual async Task GetAsync(TKey id) @@ -56,7 +56,7 @@ public abstract class EntityCacheBase : } return MapToCacheItem(await Repository.GetAsync(id))!; - }))!; + }))!.Value!; } protected virtual bool HasObjectExtensionInfo() @@ -65,15 +65,10 @@ public abstract class EntityCacheBase : ObjectExtensionManager.Instance.GetOrNull(typeof(TEntity)) != null; } - protected abstract TEntityCacheItem? MapToCacheItem(TEntity? entity); + protected abstract EntityCacheItemWrapper? MapToCacheItem(TEntity? entity); public async Task HandleEventAsync(EntityChangedEventData eventData) { - if (eventData is EntityCreatedEventData) - { - return; - } - /* Why we are using double remove: * First Cache.RemoveAsync drops the cache item in a unit of work. * Some other application / thread may read the value from database and put it to the cache again diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheItemWrapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheItemWrapper.cs new file mode 100644 index 0000000000..e1d12692c8 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheItemWrapper.cs @@ -0,0 +1,12 @@ +namespace Volo.Abp.Domain.Entities.Caching; + +public class EntityCacheItemWrapper + where TEntityCacheItem : class +{ + public TEntityCacheItem? Value { get; set; } + + public EntityCacheItemWrapper(TEntityCacheItem? value) + { + Value = value; + } +} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapper.cs index a37ad49b1e..62b3162cdd 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapper.cs @@ -15,7 +15,7 @@ public class EntityCacheWithObjectMapper : public EntityCacheWithObjectMapper( IReadOnlyRepository repository, - IDistributedCache cache, + IDistributedCache, TKey> cache, IUnitOfWorkManager unitOfWorkManager, IObjectMapper objectMapper) : base(repository, cache, unitOfWorkManager) @@ -23,7 +23,7 @@ public class EntityCacheWithObjectMapper : ObjectMapper = objectMapper; } - protected override TEntityCacheItem? MapToCacheItem(TEntity? entity) + protected override EntityCacheItemWrapper? MapToCacheItem(TEntity? entity) { if (entity == null) { @@ -32,9 +32,9 @@ public class EntityCacheWithObjectMapper : if (typeof(TEntity) == typeof(TEntityCacheItem)) { - return entity.As(); + return new EntityCacheItemWrapper(entity.As()); } - return ObjectMapper.Map(entity); + return new EntityCacheItemWrapper(ObjectMapper.Map(entity)); } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapperContext.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapperContext.cs index f468598652..2471e1057c 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapperContext.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithObjectMapperContext.cs @@ -12,7 +12,7 @@ public class EntityCacheWithObjectMapperContext repository, - IDistributedCache cache, + IDistributedCache, TKey> cache, IUnitOfWorkManager unitOfWorkManager, IObjectMapper objectMapper)// Intentionally injected with TContext : base(repository, cache, unitOfWorkManager, objectMapper) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs index 125273173e..4738534831 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Caching/EntityCacheWithoutCacheItem.cs @@ -10,14 +10,14 @@ public class EntityCacheWithoutCacheItem : { public EntityCacheWithoutCacheItem( IReadOnlyRepository repository, - IDistributedCache cache, + IDistributedCache, TKey> cache, IUnitOfWorkManager unitOfWorkManager) : base(repository, cache, unitOfWorkManager) { } - protected override TEntity? MapToCacheItem(TEntity? entity) + protected override EntityCacheItemWrapper? MapToCacheItem(TEntity? entity) { - return entity; + return new EntityCacheItemWrapper(entity); } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/AbpEntityChangeOptions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/AbpEntityChangeOptions.cs index a42b921068..2c705a01fd 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/AbpEntityChangeOptions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/AbpEntityChangeOptions.cs @@ -10,8 +10,18 @@ public class AbpEntityChangeOptions public IEntitySelectorList IgnoredNavigationEntitySelectors { get; set; } + /// + /// Default: true. + /// Update the aggregate root when any navigation property changes. + /// Some properties like ConcurrencyStamp,LastModificationTime,LastModifierId etc. will be updated. + /// + public bool UpdateAggregateRootWhenNavigationChanges { get; set; } = true; + + public IEntitySelectorList IgnoredUpdateAggregateRootSelectors { get; set; } + public AbpEntityChangeOptions() { IgnoredNavigationEntitySelectors = new EntitySelectorList(); + IgnoredUpdateAggregateRootSelectors = new EntitySelectorList(); } } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs index 44eb5c058a..eb16a6910c 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs @@ -68,13 +68,9 @@ public class EntityChangeEventHelper : IEntityChangeEventHelper, ITransientDepen private bool ShouldPublishDistributedEventForEntity(object entity) { - return DistributedEntityEventOptions - .AutoEventSelectors - .IsMatch( - ProxyHelper - .UnProxy(entity) - .GetType() - ); + var entityType = ProxyHelper.UnProxy(entity).GetType(); + return !DistributedEntityEventOptions.IgnoredEventSelectors.IsMatch(entityType) && + DistributedEntityEventOptions.AutoEventSelectors.IsMatch(entityType); } public virtual void PublishEntityUpdatedEvent(object entity) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs index 2115d00200..e84778ae50 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryAsyncExtensions.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -12,7 +14,7 @@ public static class RepositoryAsyncExtensions { #region Contains - public static async Task ContainsAsync( + public async static Task ContainsAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] T item, CancellationToken cancellationToken = default) @@ -26,7 +28,7 @@ public static class RepositoryAsyncExtensions #region Any/All - public static async Task AnyAsync( + public async static Task AnyAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -35,7 +37,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AnyAsync(queryable, cancellationToken); } - public static async Task AnyAsync( + public async static Task AnyAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) @@ -45,7 +47,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AnyAsync(queryable, predicate, cancellationToken); } - public static async Task AllAsync( + public async static Task AllAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) @@ -59,7 +61,7 @@ public static class RepositoryAsyncExtensions #region Count/LongCount - public static async Task CountAsync( + public async static Task CountAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -68,7 +70,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.CountAsync(queryable, cancellationToken); } - public static async Task CountAsync( + public async static Task CountAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) @@ -78,7 +80,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.CountAsync(queryable, predicate, cancellationToken); } - public static async Task LongCountAsync( + public async static Task LongCountAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -87,7 +89,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.LongCountAsync(queryable, cancellationToken); } - public static async Task LongCountAsync( + public async static Task LongCountAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) @@ -101,41 +103,41 @@ public static class RepositoryAsyncExtensions #region First/FirstOrDefault - public static async Task FirstAsync( + public async static Task FirstAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.FirstAsync(queryable, cancellationToken); } - public static async Task FirstAsync( + public async static Task FirstAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.FirstAsync(queryable, predicate, cancellationToken); } - public static async Task FirstOrDefaultAsync( + public async static Task FirstOrDefaultAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.FirstOrDefaultAsync(queryable, cancellationToken); } - public static async Task FirstOrDefaultAsync( + public async static Task FirstOrDefaultAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.FirstOrDefaultAsync(queryable, predicate, cancellationToken); } @@ -143,49 +145,63 @@ public static class RepositoryAsyncExtensions #region Last/LastOrDefault - public static async Task LastAsync( + public async static Task LastAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.LastAsync(queryable, cancellationToken); } - public static async Task LastAsync( + public async static Task LastAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.LastAsync(queryable, predicate, cancellationToken); } - public static async Task LastOrDefaultAsync( + public async static Task LastOrDefaultAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.LastOrDefaultAsync(queryable, cancellationToken); } - public static async Task LastOrDefaultAsync( + public async static Task LastOrDefaultAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) where T : class, IEntity { - var queryable = await repository.GetQueryableAsync(); + var queryable = AddOrderById(await repository.GetQueryableAsync()); return await repository.AsyncExecuter.LastOrDefaultAsync(queryable, predicate, cancellationToken); } #endregion + #region OrderById + + private static IQueryable AddOrderById([NotNull] this IQueryable queryable) + where T : class, IEntity + { + if (typeof(T).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntity<>))) + { + queryable = queryable.OrderBy(nameof(IEntity.Id)); + } + return queryable; + } + + #endregion + #region Single/SingleOrDefault - public static async Task SingleAsync( + public async static Task SingleAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -194,7 +210,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SingleAsync(queryable, cancellationToken); } - public static async Task SingleAsync( + public async static Task SingleAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) @@ -204,7 +220,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SingleAsync(queryable, predicate, cancellationToken); } - public static async Task SingleOrDefaultAsync( + public async static Task SingleOrDefaultAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -213,7 +229,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SingleOrDefaultAsync(queryable, cancellationToken); } - public static async Task SingleOrDefaultAsync( + public async static Task SingleOrDefaultAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> predicate, CancellationToken cancellationToken = default) @@ -227,7 +243,7 @@ public static class RepositoryAsyncExtensions #region Min - public static async Task MinAsync( + public async static Task MinAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -236,7 +252,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.MinAsync(queryable, cancellationToken); } - public static async Task MinAsync( + public async static Task MinAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -250,7 +266,7 @@ public static class RepositoryAsyncExtensions #region Max - public static async Task MaxAsync( + public async static Task MaxAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -259,7 +275,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.MaxAsync(queryable, cancellationToken); } - public static async Task MaxAsync( + public async static Task MaxAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -273,7 +289,7 @@ public static class RepositoryAsyncExtensions #region Sum - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -283,7 +299,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -293,7 +309,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -303,7 +319,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -313,7 +329,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -323,7 +339,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -333,7 +349,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -343,7 +359,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -353,7 +369,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -363,7 +379,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.SumAsync(queryable, selector, cancellationToken); } - public static async Task SumAsync( + public async static Task SumAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -377,7 +393,7 @@ public static class RepositoryAsyncExtensions #region Average - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -387,7 +403,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -397,7 +413,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -407,7 +423,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -417,7 +433,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -427,7 +443,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -437,7 +453,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -447,7 +463,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -457,7 +473,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.AverageAsync(queryable, selector, cancellationToken); } - public static async Task AverageAsync( + public async static Task AverageAsync( [NotNull] this IReadOnlyRepository repository, [NotNull] Expression> selector, CancellationToken cancellationToken = default) @@ -471,7 +487,7 @@ public static class RepositoryAsyncExtensions #region ToList/Array - public static async Task> ToListAsync( + public async static Task> ToListAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity @@ -480,7 +496,7 @@ public static class RepositoryAsyncExtensions return await repository.AsyncExecuter.ToListAsync(queryable, cancellationToken); } - public static async Task ToArrayAsync( + public async static Task ToArrayAsync( [NotNull] this IReadOnlyRepository repository, CancellationToken cancellationToken = default) where T : class, IEntity 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 626daf0bb4..e91d08b8c9 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -274,7 +274,9 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, continue; } - if (entityEntry.State == EntityState.Unchanged) + if (EntityChangeOptions.Value.UpdateAggregateRootWhenNavigationChanges && + EntityChangeOptions.Value.IgnoredUpdateAggregateRootSelectors.All(selector => !selector.Predicate(entityEntry.Entity.GetType())) && + entityEntry.State == EntityState.Unchanged) { ApplyAbpConceptsForModifiedEntity(entityEntry, true); } @@ -446,7 +448,12 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, EntityChangeOptions.Value.IgnoredNavigationEntitySelectors.All(selector => !selector.Predicate(entry.Entity.GetType())) && AbpEfCoreNavigationHelper.IsNavigationEntryModified(entry)) { - ApplyAbpConceptsForModifiedEntity(entry, true); + if (EntityChangeOptions.Value.UpdateAggregateRootWhenNavigationChanges && + EntityChangeOptions.Value.IgnoredUpdateAggregateRootSelectors.All(selector => !selector.Predicate(entry.Entity.GetType()))) + { + ApplyAbpConceptsForModifiedEntity(entry, true); + } + if (entry.Entity is ISoftDelete && entry.Entity.As().IsDeleted) { EntityChangeEventHelper.PublishEntityDeletedEvent(entry.Entity); @@ -478,11 +485,13 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, } } - if (EntityChangeOptions.Value.PublishEntityUpdatedEventWhenNavigationChanges) + if (EntityChangeOptions.Value.PublishEntityUpdatedEventWhenNavigationChanges && + EntityChangeOptions.Value.UpdateAggregateRootWhenNavigationChanges) { foreach (var entry in AbpEfCoreNavigationHelper.GetChangedEntityEntries() .Where(x => x.State == EntityState.Unchanged) - .Where(x=> EntityChangeOptions.Value.IgnoredNavigationEntitySelectors.All(selector => !selector.Predicate(x.Entity.GetType())))) + .Where(x => EntityChangeOptions.Value.IgnoredNavigationEntitySelectors.All(selector => !selector.Predicate(x.Entity.GetType()))) + .Where(x => EntityChangeOptions.Value.IgnoredUpdateAggregateRootSelectors.All(selector => !selector.Predicate(x.Entity.GetType())))) { UpdateConcurrencyStamp(entry); } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index c98ef478d4..6af11ebeca 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Domain; +using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EntityFrameworkCore.DistributedEvents; using Volo.Abp.Modularity; using Volo.Abp.Uow.EntityFrameworkCore; @@ -28,5 +29,11 @@ public class AbpEntityFrameworkCoreModule : AbpModule context.Services.TryAddTransient(typeof(IDbContextProvider<>), typeof(UnitOfWorkDbContextProvider<>)); context.Services.AddTransient(typeof(IDbContextEventOutbox<>), typeof(DbContextEventOutbox<>)); context.Services.AddTransient(typeof(IDbContextEventInbox<>), typeof(DbContextEventInbox<>)); + + Configure(options => + { + options.IgnoredEventSelectors.Add(); + options.IgnoredEventSelectors.Add(); + }); } } diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/AbpRabbitMqEventBusOptions.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/AbpRabbitMqEventBusOptions.cs index 130f5b38e2..0b450ca26e 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/AbpRabbitMqEventBusOptions.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/AbpRabbitMqEventBusOptions.cs @@ -17,10 +17,10 @@ public class AbpRabbitMqEventBusOptions public ushort? PrefetchCount { get; set; } - public IDictionary QueueArguments { get; set; } = new Dictionary(); + public IDictionary QueueArguments { get; set; } = new Dictionary(); + + public IDictionary ExchangeArguments { get; set; } = new Dictionary(); - public IDictionary ExchangeArguments { get; set; } = new Dictionary(); - public string GetExchangeTypeOrDefault() { return string.IsNullOrEmpty(ExchangeType) diff --git a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs index b0f85afb56..3a647388b5 100644 --- a/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs +++ b/framework/src/Volo.Abp.EventBus.RabbitMQ/Volo/Abp/EventBus/RabbitMq/RabbitMqDistributedEventBus.cs @@ -97,7 +97,7 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, IRabbitMqDis SubscribeHandlers(AbpDistributedEventBusOptions.Handlers); } - private async Task ProcessEventAsync(IModel channel, BasicDeliverEventArgs ea) + private async Task ProcessEventAsync(IChannel channel, BasicDeliverEventArgs ea) { var eventName = ea.RoutingKey; var eventType = EventTypes.GetOrDefault(eventName); @@ -224,10 +224,10 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, IRabbitMqDis IEnumerable outgoingEvents, OutboxConfig outboxConfig) { - using (var channel = ConnectionPool.Get(AbpRabbitMqEventBusOptions.ConnectionName).CreateModel()) + using (var channel = await (await ConnectionPool.GetAsync(AbpRabbitMqEventBusOptions.ConnectionName)) + .CreateChannelAsync(new CreateChannelOptions(publisherConfirmationsEnabled: true, publisherConfirmationTrackingEnabled: true, new ThrottlingRateLimiter(256)))) { var outgoingEventArray = outgoingEvents.ToArray(); - channel.ConfirmSelect(); foreach (var outgoingEvent in outgoingEventArray) { @@ -248,8 +248,6 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, IRabbitMqDis }); } } - - channel.WaitForConfirmsOrDie(); } } @@ -293,31 +291,33 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, IRabbitMqDis return PublishAsync(eventName, body, headersArguments, eventId, correlationId); } - protected virtual Task PublishAsync( + protected virtual async Task PublishAsync( string eventName, byte[] body, Dictionary? headersArguments = null, Guid? eventId = null, string? correlationId = null) { - using (var channel = ConnectionPool.Get(AbpRabbitMqEventBusOptions.ConnectionName).CreateModel()) + using (var channel = await (await ConnectionPool.GetAsync(AbpRabbitMqEventBusOptions.ConnectionName)).CreateChannelAsync()) { - return PublishAsync(channel, eventName, body, headersArguments, eventId, correlationId); + await PublishAsync(channel, eventName, body, headersArguments, eventId, correlationId); } } - protected virtual Task PublishAsync( - IModel channel, + protected virtual async Task PublishAsync( + IChannel channel, string eventName, byte[] body, Dictionary? headersArguments = null, Guid? eventId = null, string? correlationId = null) { - EnsureExchangeExists(channel); + await EnsureExchangeExistsAsync(channel); - var properties = channel.CreateBasicProperties(); - properties.DeliveryMode = RabbitMqConsts.DeliveryModes.Persistent; + var properties = new BasicProperties + { + DeliveryMode = DeliveryModes.Persistent + }; if (properties.MessageId.IsNullOrEmpty()) { @@ -331,18 +331,16 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, IRabbitMqDis SetEventMessageHeaders(properties, headersArguments); - channel.BasicPublish( + await channel.BasicPublishAsync( exchange: AbpRabbitMqEventBusOptions.ExchangeName, routingKey: eventName, - mandatory: true, + mandatory: false, basicProperties: properties, body: body ); - - return Task.CompletedTask; } - private void EnsureExchangeExists(IModel channel) + protected virtual async Task EnsureExchangeExistsAsync(IChannel channel) { if (_exchangeCreated) { @@ -351,14 +349,14 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, IRabbitMqDis try { - using (var temporaryChannel = ConnectionPool.Get(AbpRabbitMqEventBusOptions.ConnectionName).CreateModel()) + using (var temporaryChannel = await (await ConnectionPool.GetAsync(AbpRabbitMqEventBusOptions.ConnectionName)).CreateChannelAsync()) { - temporaryChannel.ExchangeDeclarePassive(AbpRabbitMqEventBusOptions.ExchangeName); + await temporaryChannel.ExchangeDeclarePassiveAsync(AbpRabbitMqEventBusOptions.ExchangeName); } } catch (Exception) { - channel.ExchangeDeclare( + await channel.ExchangeDeclareAsync( AbpRabbitMqEventBusOptions.ExchangeName, AbpRabbitMqEventBusOptions.GetExchangeTypeOrDefault(), durable: true @@ -367,14 +365,14 @@ public class RabbitMqDistributedEventBus : DistributedEventBusBase, IRabbitMqDis _exchangeCreated = true; } - private void SetEventMessageHeaders(IBasicProperties properties, Dictionary? headersArguments) + protected virtual void SetEventMessageHeaders(IBasicProperties properties, Dictionary? headersArguments) { if (headersArguments == null) { return; } - properties.Headers ??= new Dictionary(); + properties.Headers ??= new Dictionary(); foreach (var header in headersArguments) { diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index 63d6aa82ad..dd5df32b8a 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -236,6 +236,8 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert errorInfo.ValidationErrors = GetValidationErrorInfos((exception as AbpValidationException)!); } + TryToLocalizeExceptionMessage(exception, errorInfo); + return errorInfo; } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyApiDescriptionFinder.cs index 1734469c04..619cf5685f 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyApiDescriptionFinder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyApiDescriptionFinder.cs @@ -3,12 +3,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.FileProviders.Physical; using Volo.Abp.DependencyInjection; using Volo.Abp.Http.Modeling; using Volo.Abp.Json; using Volo.Abp.VirtualFileSystem; -using Volo.Abp.VirtualFileSystem.Embedded; namespace Volo.Abp.Http.Client.ClientProxying; @@ -32,9 +30,7 @@ public class ClientProxyApiDescriptionFinder : IClientProxyApiDescriptionFinder, public virtual ActionApiDescriptionModel? FindAction(string methodName) { - return ActionApiDescriptionModels.TryGetValue(methodName, out var model) - ? model - : null; + return ActionApiDescriptionModels.TryGetValue(methodName, out var model) ? model : null; } public virtual ApplicationApiDescriptionModel GetApiDescription() @@ -54,7 +50,6 @@ public class ClientProxyApiDescriptionFinder : IClientProxyApiDescriptionFinder, foreach (var actionItem in controller.Actions.Values) { var actionKey = $"{appServiceType}.{actionItem.Name}.{string.Join("-", actionItem.ParametersOnMethod.Select(x => x.Type))}"; - if (!ActionApiDescriptionModels.ContainsKey(actionKey)) { ActionApiDescriptionModels.Add(actionKey, actionItem); @@ -92,39 +87,19 @@ public class ClientProxyApiDescriptionFinder : IClientProxyApiDescriptionFinder, protected virtual void GetGenerateProxyFileInfos(List fileInfoList, string path = "") { - foreach (var directoryContent in VirtualFileProvider.GetDirectoryContents(path)) + foreach (var fileInfo in VirtualFileProvider.GetDirectoryContents(path)) { - if (directoryContent.IsDirectory) + if (fileInfo.IsDirectory) { - GetGenerateProxyFileInfos(fileInfoList, GetDirectoryContentPath(path, directoryContent)); + GetGenerateProxyFileInfos(fileInfoList, path + fileInfo.Name.EnsureStartsWith('/')); } else { - if (directoryContent.Name.EndsWith("generate-proxy.json")) + if (fileInfo.Name.EndsWith("generate-proxy.json", StringComparison.OrdinalIgnoreCase)) { - fileInfoList.Add(VirtualFileProvider.GetFileInfo(GetProxyFileInfoPath(path, directoryContent))); + fileInfoList.Add(fileInfo); } } } } - - protected virtual string GetDirectoryContentPath(string rootPath, IFileInfo fileInfo) - { - return fileInfo switch - { - PhysicalDirectoryInfo physicalDirectoryInfo => rootPath + physicalDirectoryInfo.Name.EnsureStartsWith('/'), - VirtualDirectoryFileInfo => fileInfo.PhysicalPath!, - _ => rootPath + fileInfo.Name.EnsureStartsWith('/') - }; - } - - protected virtual string GetProxyFileInfoPath(string rootPath, IFileInfo fileInfo) - { - return fileInfo switch - { - EmbeddedResourceFileInfo embeddedFileInfo => embeddedFileInfo.VirtualPath, - InMemoryFileInfo inMemoryFileInfo => inMemoryFileInfo.DynamicPath, - _ => rootPath + fileInfo.Name.EnsureStartsWith('/') - }; - } } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs index 01c1e2a720..d09f97b24c 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs @@ -20,6 +20,7 @@ using Volo.Abp.Json; using Volo.Abp.MultiTenancy; using Volo.Abp.Reflection; using Volo.Abp.Threading; +using Volo.Abp.Timing; using Volo.Abp.Tracing; namespace Volo.Abp.Http.Client.ClientProxying; @@ -33,6 +34,7 @@ public class ClientProxyBase : ITransientDependency protected ICorrelationIdProvider CorrelationIdProvider => LazyServiceProvider.LazyGetRequiredService(); protected ICurrentTenant CurrentTenant => LazyServiceProvider.LazyGetRequiredService(); protected IOptions AbpCorrelationIdOptions => LazyServiceProvider.LazyGetRequiredService>(); + protected ICurrentTimezoneProvider CurrentTimezoneProvider => LazyServiceProvider.LazyGetRequiredService(); protected IProxyHttpClientFactory HttpClientFactory => LazyServiceProvider.LazyGetRequiredService(); protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider => LazyServiceProvider.LazyGetRequiredService(); protected IOptions ClientOptions => LazyServiceProvider.LazyGetRequiredService>(); @@ -337,6 +339,12 @@ public class ClientProxyBase : ITransientDependency //X-Requested-With requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest"); + + //Timezone + if (!CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + requestMessage.Headers.Add(TimeZoneConsts.DefaultTimeZoneKey, CurrentTimezoneProvider.TimeZone); + } } protected virtual StringSegment RemoveQuotes(StringSegment input) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs index c24404918e..91fc6f33bf 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyRequestPayloadBuilder.cs @@ -15,6 +15,7 @@ using Volo.Abp.Http.Client.Proxying; using Volo.Abp.Http.Modeling; using Volo.Abp.Http.ProxyScripting.Generators; using Volo.Abp.Json; +using Volo.Abp.Timing; namespace Volo.Abp.Http.Client.ClientProxying; @@ -33,9 +34,15 @@ public class ClientProxyRequestPayloadBuilder : ITransientDependency protected AbpHttpClientProxyingOptions HttpClientProxyingOptions { get; } - public ClientProxyRequestPayloadBuilder(IServiceScopeFactory serviceScopeFactory, IOptions httpClientProxyingOptions) + protected IClock Clock { get; } + + public ClientProxyRequestPayloadBuilder( + IServiceScopeFactory serviceScopeFactory, + IOptions httpClientProxyingOptions, + IClock clock) { ServiceScopeFactory = serviceScopeFactory; + Clock = clock; HttpClientProxyingOptions = httpClientProxyingOptions.Value; } @@ -156,12 +163,12 @@ public class ClientProxyRequestPayloadBuilder : ITransientDependency { foreach (var item in (IEnumerable) value) { - formData.Add(new StringContent(item.ToString()!, Encoding.UTF8), parameter.Name); + formData.Add(new StringContent(await ConvertValueToStringAsync(item), Encoding.UTF8), parameter.Name); } } else { - formData.Add(new StringContent(value.ToString()!, Encoding.UTF8), parameter.Name); + formData.Add(new StringContent(await ConvertValueToStringAsync(value), Encoding.UTF8), parameter.Name); } } @@ -172,4 +179,19 @@ public class ClientProxyRequestPayloadBuilder : ITransientDependency { return await converter.ConvertAsync(actionApiDescription, parameterApiDescription, value); } + + protected virtual Task ConvertValueToStringAsync(object value) + { + if (value is DateTime dateTimeValue) + { + if (Clock.SupportsMultipleTimezone || dateTimeValue.Kind == DateTimeKind.Utc) + { + return Task.FromResult(dateTimeValue.ToUniversalTime().ToString("O")); + } + + return Task.FromResult(dateTimeValue.ToString("yyyy-MM-ddTHH:mm:ss.fffffff").TrimEnd('0').TrimEnd('.')); + } + + return Task.FromResult(value.ToString()!); + } } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs index 65703dc56b..5be598af20 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyUrlBuilder.cs @@ -14,6 +14,7 @@ using Volo.Abp.Http.Client.Proxying; using Volo.Abp.Http.Modeling; using Volo.Abp.Http.ProxyScripting.Generators; using Volo.Abp.Localization; +using Volo.Abp.Timing; namespace Volo.Abp.Http.Client.ClientProxying; @@ -36,11 +37,16 @@ public class ClientProxyUrlBuilder : ITransientDependency protected IServiceScopeFactory ServiceScopeFactory { get; } protected AbpHttpClientProxyingOptions HttpClientProxyingOptions { get; } + protected IClock Clock { get; } - public ClientProxyUrlBuilder(IServiceScopeFactory serviceScopeFactory, IOptions httpClientProxyingOptions) + public ClientProxyUrlBuilder( + IServiceScopeFactory serviceScopeFactory, + IOptions httpClientProxyingOptions, + IClock clock) { ServiceScopeFactory = serviceScopeFactory; HttpClientProxyingOptions = httpClientProxyingOptions.Value; + Clock = clock; } public async Task GenerateUrlWithParametersAsync(ActionApiDescriptionModel action, IReadOnlyDictionary methodArguments, ApiVersionInfo apiVersion) @@ -218,13 +224,18 @@ public class ClientProxyUrlBuilder : ITransientDependency return true; } - protected virtual Task ConvertValueToStringAsync(object? value) + protected virtual Task ConvertValueToStringAsync(object value) { if (value is DateTime dateTimeValue) { - return Task.FromResult(dateTimeValue.ToUniversalTime().ToString("O"))!; + if (Clock.SupportsMultipleTimezone || dateTimeValue.Kind == DateTimeKind.Utc) + { + return Task.FromResult(dateTimeValue.ToUniversalTime().ToString("O")); + } + + return Task.FromResult(dateTimeValue.ToString("yyyy-MM-ddTHH:mm:ss.fffffff").TrimEnd('0').TrimEnd('.')); } - return Task.FromResult(value?.ToString()); + return Task.FromResult(value.ToString()!); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageCompressorContributor.cs b/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageCompressorContributor.cs index 9a2f53b988..da6b75b4b8 100644 --- a/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageCompressorContributor.cs +++ b/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageCompressorContributor.cs @@ -5,9 +5,6 @@ using System.Threading.Tasks; using Microsoft.Extensions.Options; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats; -using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.Formats.Webp; using Volo.Abp.DependencyInjection; using Volo.Abp.Http; @@ -32,7 +29,7 @@ public class ImageSharpImageCompressorContributor : IImageCompressorContributor, return new ImageCompressResult(stream, ImageProcessState.Unsupported); } - var image = await Image.LoadAsync(stream, cancellationToken); + using var image = await Image.LoadAsync(stream, cancellationToken); if (!CanCompress(image.Metadata.DecodedImageFormat!.DefaultMimeType)) { @@ -46,7 +43,7 @@ public class ImageSharpImageCompressorContributor : IImageCompressorContributor, return new ImageCompressResult(memoryStream, ImageProcessState.Done); } - memoryStream.Dispose(); + await memoryStream.DisposeAsync(); return new ImageCompressResult(stream, ImageProcessState.Canceled); } @@ -69,7 +66,7 @@ public class ImageSharpImageCompressorContributor : IImageCompressorContributor, } var newBytes = await result.Result.GetAllBytesAsync(cancellationToken); - result.Result.Dispose(); + await result.Result.DisposeAsync(); return new ImageCompressResult(newBytes, result.State); } @@ -100,7 +97,7 @@ public class ImageSharpImageCompressorContributor : IImageCompressorContributor, } catch { - memoryStream.Dispose(); + await memoryStream.DisposeAsync(); throw; } } @@ -110,11 +107,11 @@ public class ImageSharpImageCompressorContributor : IImageCompressorContributor, switch (format.DefaultMimeType) { case MimeTypes.Image.Jpeg: - return Options.JpegEncoder ?? new JpegEncoder(); + return Options.JpegEncoder; case MimeTypes.Image.Png: - return Options.PngEncoder ?? new PngEncoder(); + return Options.PngEncoder; case MimeTypes.Image.Webp: - return Options.WebpEncoder ?? new WebpEncoder(); + return Options.WebpEncoder; default: throw new NotSupportedException($"No encoder available for the given format: {format.Name}"); } diff --git a/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageResizerContributor.cs b/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageResizerContributor.cs index 6e17ddc9a8..e52155eaeb 100644 --- a/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageResizerContributor.cs +++ b/framework/src/Volo.Abp.Imaging.ImageSharp/Volo/Abp/Imaging/ImageSharpImageResizerContributor.cs @@ -23,7 +23,7 @@ public class ImageSharpImageResizerContributor : IImageResizerContributor, ITran return new ImageResizeResult(stream, ImageProcessState.Unsupported); } - var image = await Image.LoadAsync(stream, cancellationToken); + using var image = await Image.LoadAsync(stream, cancellationToken); if (!CanResize(image.Metadata.DecodedImageFormat!.DefaultMimeType)) { @@ -49,7 +49,7 @@ public class ImageSharpImageResizerContributor : IImageResizerContributor, ITran } catch { - memoryStream.Dispose(); + await memoryStream.DisposeAsync(); throw; } } @@ -76,7 +76,7 @@ public class ImageSharpImageResizerContributor : IImageResizerContributor, ITran var newBytes = await result.Result.GetAllBytesAsync(cancellationToken); - result.Result.Dispose(); + await result.Result.DisposeAsync(); return new ImageResizeResult(newBytes, result.State); } diff --git a/framework/src/Volo.Abp.Imaging.SkiaSharp/Volo/Abp/Imaging/SkiaSharpImageResizerContributor.cs b/framework/src/Volo.Abp.Imaging.SkiaSharp/Volo/Abp/Imaging/SkiaSharpImageResizerContributor.cs index 760acd0916..0ba2c7c833 100644 --- a/framework/src/Volo.Abp.Imaging.SkiaSharp/Volo/Abp/Imaging/SkiaSharpImageResizerContributor.cs +++ b/framework/src/Volo.Abp.Imaging.SkiaSharp/Volo/Abp/Imaging/SkiaSharpImageResizerContributor.cs @@ -25,21 +25,19 @@ public class SkiaSharpImageResizerContributor : IImageResizerContributor, ITrans return new ImageResizeResult(bytes, ImageProcessState.Unsupported); } - using (var memoryStream = new MemoryStream(bytes)) - { - var result = await TryResizeAsync(memoryStream, resizeArgs, mimeType, cancellationToken); + using var memoryStream = new MemoryStream(bytes); + var result = await TryResizeAsync(memoryStream, resizeArgs, mimeType, cancellationToken); - if (result.State != ImageProcessState.Done) - { - return new ImageResizeResult(bytes, result.State); - } + if (result.State != ImageProcessState.Done) + { + return new ImageResizeResult(bytes, result.State); + } - var newBytes = await result.Result.GetAllBytesAsync(cancellationToken); + var newBytes = await result.Result.GetAllBytesAsync(cancellationToken); - result.Result.Dispose(); + result.Result.Dispose(); - return new ImageResizeResult(newBytes, result.State); - } + return new ImageResizeResult(newBytes, result.State); } public virtual async Task> TryResizeAsync(Stream stream, ImageResizeArgs resizeArgs, string? mimeType = null, CancellationToken cancellationToken = default) @@ -51,21 +49,14 @@ public class SkiaSharpImageResizerContributor : IImageResizerContributor, ITrans var (memoryBitmapStream, memorySkCodecStream) = await CreateMemoryStream(stream); - using (var original = SKBitmap.Decode(memoryBitmapStream)) - { - using (var resized = original.Resize(new SKImageInfo(resizeArgs.Width, resizeArgs.Height), Options.SKFilterQuality)) - { - using (var image = SKImage.FromBitmap(resized)) - { - using (var codec = SKCodec.Create(memorySkCodecStream)) - { - var memoryStream = new MemoryStream(); - image.Encode(codec.EncodedFormat, Options.Quality).SaveTo(memoryStream); - return new ImageResizeResult(memoryStream, ImageProcessState.Done); - } - } - } - } + using var original = SKBitmap.Decode(memoryBitmapStream); + using var resized = original.Resize(new SKImageInfo(resizeArgs.Width, resizeArgs.Height), Options.SKFilterQuality); + using var image = SKImage.FromBitmap(resized); + using var codec = SKCodec.Create(memorySkCodecStream); + var memoryStream = new MemoryStream(); + using var skData = image.Encode(codec.EncodedFormat, Options.Quality); + skData.SaveTo(memoryStream); + return new ImageResizeResult(memoryStream, ImageProcessState.Done); } protected virtual async Task<(MemoryStream, MemoryStream)> CreateMemoryStream(Stream stream) diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs index effda40057..c95660e484 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpDateTimeConverter.cs @@ -19,6 +19,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency private readonly CultureInfo _culture = CultureInfo.InvariantCulture; private readonly IClock _clock; private readonly AbpJsonOptions _options; + private bool _skipDateTimeNormalization; public AbpDateTimeConverter(IClock clock, IOptions options) { @@ -26,6 +27,12 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency _options = options.Value; } + public virtual AbpDateTimeConverter SkipDateTimeNormalization() + { + _skipDateTimeNormalization = true; + return this; + } + public override bool CanConvert(Type objectType) { return objectType == typeof(DateTime) || objectType == typeof(DateTime?); @@ -46,7 +53,7 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency if (reader.TokenType == JsonToken.Date) { - return _clock.Normalize(reader.Value!.To()); + return Normalize(reader.Value!.To()); } if (reader.TokenType != JsonToken.String) @@ -67,20 +74,20 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency { if (DateTime.TryParseExact(dateText, format, _culture, _dateTimeStyles, out var d1)) { - return _clock.Normalize(d1); + return Normalize(d1); } } } var date = DateTime.Parse(dateText!, _culture, _dateTimeStyles); - return _clock.Normalize(date); + return Normalize(date); } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value != null) { - value = _clock.Normalize(value.To()); + value = Normalize(value.To()); } if (value is DateTime dateTime) @@ -111,4 +118,11 @@ public class AbpDateTimeConverter : DateTimeConverterBase, ITransientDependency return ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(member) == null; } + + protected virtual DateTime Normalize(DateTime dateTime) + { + return _skipDateTimeNormalization + ? dateTime + : _clock.Normalize(dateTime); + } } diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs index 6f93a6c54e..ea35831d86 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs @@ -13,7 +13,8 @@ public class AbpJsonNewtonsoftModule : AbpModule context.Services.AddOptions() .Configure((options, rootServiceProvider) => { - options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver(rootServiceProvider.GetRequiredService()); + options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver( + rootServiceProvider.GetRequiredService().SkipDateTimeNormalization()); }); } } diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs index 0450064f2f..8184ee6d45 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializer.cs @@ -86,7 +86,8 @@ public class AbpNewtonsoftJsonSerializer : IJsonSerializer, ITransientDependency if (!camelCase) { //Default contract resolver is AbpCamelCasePropertyNamesContractResolver} - settings.ContractResolver = new AbpDefaultContractResolver(RootServiceProvider.GetRequiredService()); + settings.ContractResolver = new AbpDefaultContractResolver(RootServiceProvider + .GetRequiredService().SkipDateTimeNormalization()); } if (indented) diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs index 498dedd8cd..0a5066cec1 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs @@ -29,14 +29,13 @@ public class AbpJsonSystemTextJsonModule : AbpModule options.JsonSerializerOptions.TypeInfoResolver = new AbpDefaultJsonTypeInfoResolver(rootServiceProvider .GetRequiredService>()); - }); - context.Services.AddOptions() - .Configure((options, rootServiceProvider) => - { - options.Modifiers.Add(new AbpDateTimeConverterModifier( - rootServiceProvider.GetRequiredService(), - rootServiceProvider.GetRequiredService()).CreateModifyAction()); + var dateTimeConverter = rootServiceProvider.GetRequiredService().SkipDateTimeNormalization(); + var nullableDateTimeConverter = rootServiceProvider.GetRequiredService().SkipDateTimeNormalization(); + + options.JsonSerializerOptions.TypeInfoResolver.As().Modifiers.Add( + new AbpDateTimeConverterModifier(dateTimeConverter, nullableDateTimeConverter) + .CreateModifyAction()); }); } } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs index 6f433ce918..7f72f0de71 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializer.cs @@ -40,21 +40,10 @@ public class AbpSystemTextJsonSerializer : IJsonSerializer, ITransientDependency camelCase, indented, Options.JsonSerializerOptions - }, _ => + }, _ => new JsonSerializerOptions(Options.JsonSerializerOptions) { - var settings = new JsonSerializerOptions(Options.JsonSerializerOptions); - - if (camelCase) - { - settings.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - } - - if (indented) - { - settings.WriteIndented = true; - } - - return settings; + PropertyNamingPolicy = camelCase ? JsonNamingPolicy.CamelCase : null, + WriteIndented = indented }); } } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs index a8653bb54a..3feea8d299 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs @@ -13,6 +13,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc { private readonly IClock _clock; private readonly AbpJsonOptions _options; + private bool _skipDateTimeNormalization; public AbpDateTimeConverter(IClock clock, IOptions abpJsonOptions) { @@ -20,6 +21,12 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc _options = abpJsonOptions.Value; } + public virtual AbpDateTimeConverter SkipDateTimeNormalization() + { + _skipDateTimeNormalization = true; + return this; + } + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (_options.InputDateTimeFormats.Any()) @@ -31,7 +38,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc var s = reader.GetString(); if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1)) { - return _clock.Normalize(d1); + return Normalize(d1); } } } @@ -43,7 +50,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc if (reader.TryGetDateTime(out var d3)) { - return _clock.Normalize(d3); + return Normalize(d3); } var dateText = reader.GetString(); @@ -51,7 +58,7 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc { if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d4)) { - return _clock.Normalize(d4); + return Normalize(d4); } } @@ -62,11 +69,16 @@ public class AbpDateTimeConverter : JsonConverter, ITransientDependenc { if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace()) { - writer.WriteStringValue(_clock.Normalize(value)); + writer.WriteStringValue(Normalize(value)); } else { - writer.WriteStringValue(_clock.Normalize(value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); + writer.WriteStringValue(Normalize(value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); } } + + protected virtual DateTime Normalize(DateTime dateTime) + { + return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime); + } } diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs index e8a94892da..e73f39d097 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs @@ -13,6 +13,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient { private readonly IClock _clock; private readonly AbpJsonOptions _options; + private bool _skipDateTimeNormalization; public AbpNullableDateTimeConverter(IClock clock, IOptions abpJsonOptions) { @@ -20,6 +21,12 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient _options = abpJsonOptions.Value; } + public virtual AbpNullableDateTimeConverter SkipDateTimeNormalization() + { + _skipDateTimeNormalization = true; + return this; + } + public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (_options.InputDateTimeFormats.Any()) @@ -31,7 +38,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient var s = reader.GetString(); if (DateTime.TryParseExact(s, format, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1)) { - return _clock.Normalize(d1); + return Normalize(d1); } } } @@ -43,7 +50,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient if (reader.TryGetDateTime(out var d2)) { - return _clock.Normalize(d2); + return Normalize(d2); } var dateText = reader.GetString(); @@ -51,7 +58,7 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient { if (DateTime.TryParse(dateText, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d3)) { - return _clock.Normalize(d3); + return Normalize(d3); } } @@ -68,12 +75,17 @@ public class AbpNullableDateTimeConverter : JsonConverter, ITransient { if (_options.OutputDateTimeFormat.IsNullOrWhiteSpace()) { - writer.WriteStringValue(_clock.Normalize(value.Value)); + writer.WriteStringValue(Normalize(value.Value)); } else { - writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); + writer.WriteStringValue(Normalize(value.Value).ToString(_options.OutputDateTimeFormat, CultureInfo.CurrentUICulture)); } } } + + protected virtual DateTime Normalize(DateTime dateTime) + { + return _skipDateTimeNormalization ? dateTime : _clock.Normalize(dateTime); + } } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs index b25bd9ec6e..d151dc78df 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs @@ -103,7 +103,7 @@ public abstract class VirtualFileLocalizationResourceContributorBase : ILocaliza { continue; } - + if (dictionaries.ContainsKey(dictionary.CultureName)) { throw new AbpException($"{file.GetVirtualOrPhysicalPathOrNull()} dictionary has a culture name '{dictionary.CultureName}' which is already defined! Localization resource: {_resource.ResourceName}"); @@ -121,7 +121,14 @@ public abstract class VirtualFileLocalizationResourceContributorBase : ILocaliza { using (var stream = file.CreateReadStream()) { - return CreateDictionaryFromFileContent(Utf8Helper.ReadStringFromStream(stream)); + try + { + return CreateDictionaryFromFileContent(Utf8Helper.ReadStringFromStream(stream)); + } + catch (Exception e) + { + throw new AbpException("Invalid localization file format: " + (file.GetVirtualOrPhysicalPathOrNull() ?? file.Name), e); + } } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpGuidCustomBsonTypeMapper.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpGuidCustomBsonTypeMapper.cs new file mode 100644 index 0000000000..4cfacc39fd --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpGuidCustomBsonTypeMapper.cs @@ -0,0 +1,13 @@ +using System; +using MongoDB.Bson; + +namespace Volo.Abp.MongoDB; + +public class AbpGuidCustomBsonTypeMapper : ICustomBsonTypeMapper +{ + public bool TryMapToBsonValue(object value, out BsonValue bsonValue) + { + bsonValue = new BsonBinaryData((Guid)value, GuidRepresentation.Standard); + return true; + } +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs index 91d2808010..195491d989 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs @@ -1,9 +1,11 @@ -using Microsoft.Extensions.DependencyInjection; +using System; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; using Volo.Abp.Domain; +using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Domain.Repositories.MongoDB; using Volo.Abp.Modularity; using Volo.Abp.MongoDB.DependencyInjection; @@ -15,6 +17,12 @@ namespace Volo.Abp.MongoDB; [DependsOn(typeof(AbpDddDomainModule))] public class AbpMongoDbModule : AbpModule { + static AbpMongoDbModule() + { + BsonSerializer.TryRegisterSerializer(new GuidSerializer(GuidRepresentation.Standard)); + BsonTypeMapper.RegisterCustomTypeMapper(typeof(Guid), new AbpGuidCustomBsonTypeMapper()); + } + public override void PreConfigureServices(ServiceConfigurationContext context) { context.Services.AddConventionalRegistrar(new AbpMongoDbConventionalRegistrar()); @@ -22,8 +30,6 @@ public class AbpMongoDbModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { - BsonSerializer.TryRegisterSerializer(new GuidSerializer(GuidRepresentation.Standard)); - context.Services.TryAddTransient( typeof(IMongoDbContextProvider<>), typeof(UnitOfWorkMongoDbContextProvider<>) @@ -48,5 +54,11 @@ public class AbpMongoDbModule : AbpModule typeof(IMongoDbContextEventInbox<>), typeof(MongoDbContextEventInbox<>) ); + + Configure(options => + { + options.IgnoredEventSelectors.Add(); + options.IgnoredEventSelectors.Add(); + }); } } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs index 9d1b706d8b..e5d726526b 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -64,7 +64,7 @@ public class MongoDbContextEventInbox : IMongoDbContextEventInb var outgoingEventRecords = await dbContext .IncomingEvents .AsQueryable() - .Where(x => !x.Processed) + .Where(x => x.Processed == false) .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs index da010b83c9..74b41dea23 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/AbpRabbitMqModule.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Json; using Volo.Abp.Modularity; using Volo.Abp.Threading; @@ -19,7 +20,6 @@ public class AbpRabbitMqModule : AbpModule { foreach (var connectionFactory in options.Connections.Values) { - connectionFactory.DispatchConsumersAsync = true; connectionFactory.AutomaticRecoveryEnabled = false; } }); @@ -27,12 +27,17 @@ public class AbpRabbitMqModule : AbpModule public override void OnApplicationShutdown(ApplicationShutdownContext context) { - context.ServiceProvider + AsyncHelper.RunSync(() => OnApplicationShutdownAsync(context)); + } + + public async override Task OnApplicationShutdownAsync(ApplicationShutdownContext context) + { + await context.ServiceProvider .GetRequiredService() - .Dispose(); + .DisposeAsync(); - context.ServiceProvider + await context.ServiceProvider .GetRequiredService() - .Dispose(); + .DisposeAsync(); } } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs index b7ed4c80c8..03d6029b69 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ChannelPool.cs @@ -3,10 +3,12 @@ using System.Collections.Concurrent; using System.Diagnostics; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using RabbitMQ.Client; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.RabbitMQ; @@ -16,6 +18,8 @@ public class ChannelPool : IChannelPool, ISingletonDependency protected ConcurrentDictionary Channels { get; } + protected SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); + protected bool IsDisposed { get; private set; } protected TimeSpan TotalDisposeWaitDuration { get; set; } = TimeSpan.FromSeconds(10); @@ -29,28 +33,54 @@ public class ChannelPool : IChannelPool, ISingletonDependency Logger = NullLogger.Instance; } - public virtual IChannelAccessor Acquire(string? channelName = null, string? connectionName = null) + public virtual async Task AcquireAsync(string? channelName = null, string? connectionName = null) { CheckDisposed(); channelName = channelName ?? ""; - var poolItem = Channels.GetOrAdd( - channelName, - _ => new ChannelPoolItem(CreateChannel(channelName, connectionName)) - ); + ChannelPoolItem poolItem; + + if (Channels.TryGetValue(channelName, out var existingChannelPoolItem)) + { + poolItem = existingChannelPoolItem; + } + else + { + using (await Semaphore.LockAsync()) + { + if (Channels.TryGetValue(channelName, out var existingChannelPoolItem2)) + { + poolItem = existingChannelPoolItem2; + } + else + { + poolItem = new ChannelPoolItem(await CreateChannelAsync(channelName, connectionName)); + Channels.TryAdd(channelName, poolItem); + } + } + } poolItem.Acquire(); if (poolItem.Channel.IsClosed) { - poolItem.Dispose(); + await poolItem.DisposeAsync(); Channels.TryRemove(channelName, out _); - poolItem = Channels.GetOrAdd( - channelName, - _ => new ChannelPoolItem(CreateChannel(channelName, connectionName)) - ); - + + using (await Semaphore.LockAsync()) + { + if (Channels.TryGetValue(channelName, out var existingChannelPoolItem3)) + { + poolItem = existingChannelPoolItem3; + } + else + { + poolItem = new ChannelPoolItem(await CreateChannelAsync(channelName, connectionName)); + Channels.TryAdd(channelName, poolItem); + } + } + poolItem.Acquire(); } @@ -61,14 +91,14 @@ public class ChannelPool : IChannelPool, ISingletonDependency ); } - protected virtual IModel CreateChannel(string channelName, string? connectionName) + protected virtual async Task CreateChannelAsync(string channelName, string? connectionName) { - return ConnectionPool - .Get(connectionName) - .CreateModel(); + return await (await ConnectionPool + .GetAsync(connectionName)) + .CreateChannelAsync(); } - protected void CheckDisposed() + protected virtual void CheckDisposed() { if (IsDisposed) { @@ -76,7 +106,7 @@ public class ChannelPool : IChannelPool, ISingletonDependency } } - public void Dispose() + public async ValueTask DisposeAsync() { if (IsDisposed) { @@ -104,10 +134,12 @@ public class ChannelPool : IChannelPool, ISingletonDependency try { poolItem.WaitIfInUse(remainingWaitDuration); - poolItem.Dispose(); + await poolItem.DisposeAsync(); } catch - { } + { + // ignored + } poolItemDisposeStopwatch.Stop(); @@ -128,9 +160,9 @@ public class ChannelPool : IChannelPool, ISingletonDependency Channels.Clear(); } - protected class ChannelPoolItem : IDisposable + protected class ChannelPoolItem : IAsyncDisposable { - public IModel Channel { get; } + public IChannel Channel { get; } public bool IsInUse { get => _isInUse; @@ -138,7 +170,7 @@ public class ChannelPool : IChannelPool, ISingletonDependency } private volatile bool _isInUse; - public ChannelPoolItem(IModel channel) + public ChannelPoolItem(IChannel channel) { Channel = channel; } @@ -178,21 +210,21 @@ public class ChannelPool : IChannelPool, ISingletonDependency } } - public void Dispose() + public async ValueTask DisposeAsync() { - Channel.Dispose(); + await Channel.DisposeAsync(); } } protected class ChannelAccessor : IChannelAccessor { - public IModel Channel { get; } + public IChannel Channel { get; } public string Name { get; } private readonly Action _disposeAction; - public ChannelAccessor(IModel channel, string name, Action disposeAction) + public ChannelAccessor(IChannel channel, string name, Action disposeAction) { _disposeAction = disposeAction; Name = name; diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs index 5f4556b96a..888de64613 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ConnectionPool.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Options; using RabbitMQ.Client; using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; namespace Volo.Abp.RabbitMQ; @@ -11,55 +13,51 @@ public class ConnectionPool : IConnectionPool, ISingletonDependency { protected AbpRabbitMqOptions Options { get; } - protected ConcurrentDictionary> Connections { get; } + protected ConcurrentDictionary Connections { get; } + + protected SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); private bool _isDisposed; public ConnectionPool(IOptions options) { Options = options.Value; - Connections = new ConcurrentDictionary>(); + Connections = new ConcurrentDictionary(); } - public virtual IConnection Get(string? connectionName = null) + public virtual async Task GetAsync(string? connectionName = null) { - connectionName ??= RabbitMqConnections.DefaultConnectionName; - var connectionFactory = Options.Connections.GetOrDefault(connectionName); - try + using (await Semaphore.LockAsync()) { - var connection = GetConnection(connectionName, connectionFactory); - - if (connection.IsOpen) + connectionName ??= RabbitMqConnections.DefaultConnectionName; + + if (Connections.TryGetValue(connectionName, out var existingConnection) && existingConnection.IsOpen) { - return connection; + return existingConnection; } - - connection.Dispose(); - Connections.TryRemove(connectionName, out _); - return GetConnection(connectionName, connectionFactory); - } - catch (Exception) - { - Connections.TryRemove(connectionName, out _); - throw; + + if(existingConnection != null) + { + await existingConnection.DisposeAsync(); + } + + var connectionFactory = Options.Connections.GetOrDefault(connectionName); + var connection = await GetConnectionAsync(connectionName, connectionFactory); + Connections[connectionName] = connection; + return connection; } } - protected virtual IConnection GetConnection(string connectionName, ConnectionFactory connectionFactory) + protected virtual async Task GetConnectionAsync(string connectionName, ConnectionFactory connectionFactory) { - return Connections.GetOrAdd( - connectionName, () => new Lazy(() => - { - var hostnames = connectionFactory.HostName.TrimEnd(';').Split(';'); - // Handle Rabbit MQ Cluster. - return hostnames.Length == 1 - ? connectionFactory.CreateConnection() - : connectionFactory.CreateConnection(hostnames); - }) - ).Value; + var hostnames = connectionFactory.HostName.TrimEnd(';').Split(';'); + // Handle Rabbit MQ Cluster. + return hostnames.Length == 1 + ? await connectionFactory.CreateConnectionAsync() + : await connectionFactory.CreateConnectionAsync(hostnames); } - public void Dispose() + public async ValueTask DisposeAsync() { if (_isDisposed) { @@ -72,11 +70,11 @@ public class ConnectionPool : IConnectionPool, ISingletonDependency { try { - connection.Value.Dispose(); + await connection.DisposeAsync(); } catch { - + // ignored } } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ExchangeDeclareConfiguration.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ExchangeDeclareConfiguration.cs index 5c239893c7..4a5c0f01d0 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ExchangeDeclareConfiguration.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/ExchangeDeclareConfiguration.cs @@ -12,19 +12,19 @@ public class ExchangeDeclareConfiguration public bool AutoDelete { get; set; } - public IDictionary Arguments { get; } + public IDictionary Arguments { get; } public ExchangeDeclareConfiguration( string exchangeName, string type, bool durable = false, bool autoDelete = false, - IDictionary? arguments = null) + IDictionary? arguments = null) { ExchangeName = exchangeName; Type = type; Durable = durable; AutoDelete = autoDelete; - Arguments = arguments?? new Dictionary(); + Arguments = arguments?? new Dictionary(); } } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelAccessor.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelAccessor.cs index ad8829f8ee..d4eb954a67 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelAccessor.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelAccessor.cs @@ -10,7 +10,7 @@ public interface IChannelAccessor : IDisposable /// Never dispose the object. /// Instead, dispose the after usage. /// - IModel Channel { get; } + IChannel Channel { get; } /// /// Name of the channel. diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelPool.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelPool.cs index 2ba6259fec..5a9611ad86 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelPool.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IChannelPool.cs @@ -1,8 +1,9 @@ using System; +using System.Threading.Tasks; namespace Volo.Abp.RabbitMQ; -public interface IChannelPool : IDisposable +public interface IChannelPool : IAsyncDisposable { - IChannelAccessor Acquire(string? channelName = null, string? connectionName = null); + Task AcquireAsync(string? channelName = null, string? connectionName = null); } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IConnectionPool.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IConnectionPool.cs index dc97476c84..02fdf286d9 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IConnectionPool.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IConnectionPool.cs @@ -1,9 +1,10 @@ using System; +using System.Threading.Tasks; using RabbitMQ.Client; namespace Volo.Abp.RabbitMQ; -public interface IConnectionPool : IDisposable +public interface IConnectionPool : IAsyncDisposable { - IConnection Get(string? connectionName = null); + Task GetAsync(string? connectionName = null); } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IRabbitMqMessageConsumer.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IRabbitMqMessageConsumer.cs index a24ad69a4a..8501b8958f 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IRabbitMqMessageConsumer.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/IRabbitMqMessageConsumer.cs @@ -11,5 +11,5 @@ public interface IRabbitMqMessageConsumer Task UnbindAsync(string routingKey); - void OnMessageReceived(Func callback); + void OnMessageReceived(Func callback); } diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/QueueDeclareConfiguration.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/QueueDeclareConfiguration.cs index eb59ec3058..ebb2c3e1cc 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/QueueDeclareConfiguration.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/QueueDeclareConfiguration.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using JetBrains.Annotations; using RabbitMQ.Client; @@ -13,10 +14,10 @@ public class QueueDeclareConfiguration public bool Exclusive { get; set; } public bool AutoDelete { get; set; } - - public ushort? PrefetchCount { get; set; } - public IDictionary Arguments { get; } + public ushort? PrefetchCount { get; set; } + + public IDictionary Arguments { get; } public QueueDeclareConfiguration( [NotNull] string queueName, @@ -24,19 +25,19 @@ public class QueueDeclareConfiguration bool exclusive = false, bool autoDelete = false, ushort? prefetchCount = null, - IDictionary? arguments = null) + IDictionary? arguments = null) { QueueName = queueName; Durable = durable; Exclusive = exclusive; AutoDelete = autoDelete; - Arguments = arguments?? new Dictionary(); + Arguments = arguments?? new Dictionary(); PrefetchCount = prefetchCount; } - public virtual QueueDeclareOk Declare(IModel channel) + public virtual async Task DeclareAsync(IChannel channel) { - return channel.QueueDeclare( + return await channel.QueueDeclareAsync( queue: QueueName, durable: Durable, exclusive: Exclusive, diff --git a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs index 6f361f7670..74dac68a61 100644 --- a/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs +++ b/framework/src/Volo.Abp.RabbitMQ/Volo/Abp/RabbitMQ/RabbitMqMessageConsumer.cs @@ -5,6 +5,7 @@ using RabbitMQ.Client; using RabbitMQ.Client.Events; using System; using System.Collections.Concurrent; +using System.Threading; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.ExceptionHandling; @@ -28,13 +29,13 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen protected string? ConnectionName { get; private set; } - protected ConcurrentBag> Callbacks { get; } + protected ConcurrentBag> Callbacks { get; } - protected IModel? Channel { get; private set; } + protected IChannel? Channel { get; private set; } protected ConcurrentQueue QueueBindCommands { get; } - protected object ChannelSendSyncLock { get; } = new object(); + protected SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); public RabbitMqMessageConsumer( IConnectionPool connectionPool, @@ -47,7 +48,7 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen Logger = NullLogger.Instance; QueueBindCommands = new ConcurrentQueue(); - Callbacks = new ConcurrentBag>(); + Callbacks = new ConcurrentBag>(); Timer.Period = 5000; //5 sec. Timer.Elapsed = Timer_Elapsed; @@ -88,21 +89,21 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen return; } - lock (ChannelSendSyncLock) + using (await Semaphore.LockAsync()) { if (QueueBindCommands.TryPeek(out var command)) { switch (command.Type) { case QueueBindType.Bind: - Channel.QueueBind( + await Channel.QueueBindAsync( queue: Queue.QueueName, exchange: Exchange.ExchangeName, routingKey: command.RoutingKey ); break; case QueueBindType.Unbind: - Channel.QueueUnbind( + await Channel.QueueUnbindAsync( queue: Queue.QueueName, exchange: Exchange.ExchangeName, routingKey: command.RoutingKey @@ -124,7 +125,7 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen } } - public virtual void OnMessageReceived(Func callback) + public virtual void OnMessageReceived(Func callback) { Callbacks.Add(callback); } @@ -144,11 +145,11 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen try { - Channel = ConnectionPool - .Get(ConnectionName) - .CreateModel(); + Channel = await (await ConnectionPool + .GetAsync(ConnectionName)) + .CreateChannelAsync(); - Channel.ExchangeDeclare( + await Channel.ExchangeDeclareAsync( exchange: Exchange.ExchangeName, type: Exchange.Type, durable: Exchange.Durable, @@ -156,7 +157,7 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen arguments: Exchange.Arguments ); - Channel.QueueDeclare( + await Channel.QueueDeclareAsync( queue: Queue.QueueName, durable: Queue.Durable, exclusive: Queue.Exclusive, @@ -166,13 +167,13 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen if (Queue.PrefetchCount.HasValue) { - Channel.BasicQos(0, Queue.PrefetchCount.Value, false); + await Channel.BasicQosAsync(0, Queue.PrefetchCount.Value, false); } - + var consumer = new AsyncEventingBasicConsumer(Channel); - consumer.Received += HandleIncomingMessageAsync; - - Channel.BasicConsume( + consumer.ReceivedAsync += HandleIncomingMessageAsync; + + await Channel.BasicConsumeAsync( queue: Queue.QueueName, autoAck: false, consumer: consumer @@ -194,17 +195,23 @@ public class RabbitMqMessageConsumer : IRabbitMqMessageConsumer, ITransientDepen await callback(Channel!, basicDeliverEventArgs); } - Channel?.BasicAck(basicDeliverEventArgs.DeliveryTag, multiple: false); + if (Channel != null) + { + await Channel.BasicAckAsync(basicDeliverEventArgs.DeliveryTag, multiple: false); + } } catch (Exception ex) { try { - Channel?.BasicNack( - basicDeliverEventArgs.DeliveryTag, - multiple: false, - requeue: true - ); + if (Channel != null) + { + await Channel.BasicNackAsync( + basicDeliverEventArgs.DeliveryTag, + multiple: false, + requeue: true + ); + } } // ReSharper disable once EmptyGeneralCatchClause catch { } diff --git a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.js b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.js index 0e13317cbf..11cbe56803 100644 --- a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.js +++ b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.js @@ -4,7 +4,9 @@ var abp = abp || {}; /* Application paths *****************************************/ //Current application root path (including virtual directory if exists). - abp.appPath = abp.appPath || '/'; + var baseElement = document.querySelector('base'); + var baseHref = baseElement ? baseElement.getAttribute('href') : null; + abp.appPath = baseHref || abp.appPath || '/'; /* UTILS ***************************************************/ diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs index 8788a2b5db..36bee9e8fd 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Clock.cs @@ -7,9 +7,16 @@ namespace Volo.Abp.Timing; public class Clock : IClock, ITransientDependency { protected AbpClockOptions Options { get; } + protected ICurrentTimezoneProvider CurrentTimezoneProvider { get; } + protected ITimezoneProvider TimezoneProvider { get; } - public Clock(IOptions options) + public Clock( + IOptions options, + ICurrentTimezoneProvider currentTimezoneProvider, + ITimezoneProvider timezoneProvider) { + CurrentTimezoneProvider = currentTimezoneProvider; + TimezoneProvider = timezoneProvider; Options = options.Value; } @@ -19,6 +26,11 @@ public class Clock : IClock, ITransientDependency public virtual bool SupportsMultipleTimezone => Options.Kind == DateTimeKind.Utc; + /// + /// Normalizes given . + /// + /// DateTime to be normalized. + /// Normalized DateTime public virtual DateTime Normalize(DateTime dateTime) { if (Kind == DateTimeKind.Unspecified || Kind == dateTime.Kind) @@ -38,4 +50,58 @@ public class Clock : IClock, ITransientDependency return DateTime.SpecifyKind(dateTime, Kind); } + + /// + /// Converts given UTC to user's time zone. + /// + /// DateTime to be normalized. + /// Converted DateTime + public virtual DateTime ConvertToUserTime(DateTime utcDateTime) + { + if (!SupportsMultipleTimezone || + utcDateTime.Kind != DateTimeKind.Utc || + CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + return utcDateTime; + } + + var timezoneInfo = TimezoneProvider.GetTimeZoneInfo(CurrentTimezoneProvider.TimeZone); + return TimeZoneInfo.ConvertTime(utcDateTime, timezoneInfo); + } + + /// + /// Converts given to user's time zone. + /// + /// DateTimeOffset to be normalized. + /// Converted DateTimeOffset + public virtual DateTimeOffset ConvertToUserTime(DateTimeOffset dateTimeOffset) + { + if (!SupportsMultipleTimezone || + CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + return dateTimeOffset; + } + + var timezoneInfo = TimezoneProvider.GetTimeZoneInfo(CurrentTimezoneProvider.TimeZone); + return TimeZoneInfo.ConvertTime(dateTimeOffset, timezoneInfo); + } + + /// + /// Converts given to UTC if the given time is not UTC and the current clock provider supports multiple time zones. + /// + /// DateTime to be normalized. + /// Converted DateTime + public DateTime ConvertToUtc(DateTime dateTime) + { + if (!SupportsMultipleTimezone || + dateTime.Kind == DateTimeKind.Utc || + CurrentTimezoneProvider.TimeZone.IsNullOrWhiteSpace()) + { + return dateTime; + } + + var timezoneInfo = TimezoneProvider.GetTimeZoneInfo(CurrentTimezoneProvider.TimeZone); + dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified); + return TimeZoneInfo.ConvertTimeToUtc(dateTime, timezoneInfo); + } } diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/CurrentTimezoneProvider.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/CurrentTimezoneProvider.cs new file mode 100644 index 0000000000..12781d4321 --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/CurrentTimezoneProvider.cs @@ -0,0 +1,20 @@ +using System.Threading; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Timing; + +public class CurrentTimezoneProvider : ICurrentTimezoneProvider, ISingletonDependency +{ + public string? TimeZone + { + get => _currentScope.Value; + set => _currentScope.Value = value; + } + + private readonly AsyncLocal _currentScope; + + public CurrentTimezoneProvider() + { + _currentScope = new AsyncLocal(); + } +} diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/CurrentTimezoneProviderExtensions.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/CurrentTimezoneProviderExtensions.cs new file mode 100644 index 0000000000..2fc79289ad --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/CurrentTimezoneProviderExtensions.cs @@ -0,0 +1,18 @@ +using System; + +namespace Volo.Abp.Timing; + +public static class CurrentTimezoneProviderExtensions +{ + public static IDisposable Change(this ICurrentTimezoneProvider currentTimezoneProvider, string? timeZone) + { + var parentScope = currentTimezoneProvider.TimeZone; + currentTimezoneProvider.TimeZone = timeZone; + + return new DisposeAction>(static (state) => + { + var (currentTimezoneProvider, parentScope) = state; + currentTimezoneProvider.TimeZone = parentScope; + }, (currentTimezoneProvider, parentScope)); + } +} diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClientTimezoneProvider.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClientTimezoneProvider.cs new file mode 100644 index 0000000000..69c2835adc --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClientTimezoneProvider.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.Timing; + +public interface ICurrentTimezoneProvider +{ + string? TimeZone { get; set; } +} diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs index 33db4b45a8..7bf83dc7e0 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/IClock.cs @@ -25,4 +25,25 @@ public interface IClock /// DateTime to be normalized. /// Normalized DateTime DateTime Normalize(DateTime dateTime); + + /// + /// Converts given UTC to user's time zone. + /// + /// DateTime to be normalized. + /// Converted DateTime + DateTime ConvertToUserTime(DateTime utcDateTime); + + /// + /// Converts given to user's time zone. + /// + /// DateTimeOffset to be normalized. + /// Converted DateTimeOffset + DateTimeOffset ConvertToUserTime(DateTimeOffset dateTimeOffset); + + /// + /// Converts given to UTC if the given time is not UTC and the current clock provider supports multiple time zones. + /// + /// DateTime to be normalized. + /// Converted DateTime + DateTime ConvertToUtc(DateTime dateTime); } diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs index 70d19090e2..565c04c6fa 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TZConvertTimezoneProvider.cs @@ -15,7 +15,7 @@ public class TZConvertTimezoneProvider : ITimezoneProvider, ITransientDependency public virtual List GetIanaTimezones() { - return TZConvert.KnownIanaTimeZoneNames.OrderBy(x => x).Select(x => new NameValue(x, x)).ToList(); + return TZConvert.KnownIanaTimeZoneNames.OrderBy(x => x).Where(x => x.Contains("/") && !x.Contains("Etc") || x == "UTC").Select(x => new NameValue(x, x)).ToList(); } public virtual string WindowsToIana(string windowsTimeZoneId) diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimeZoneConsts.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimeZoneConsts.cs new file mode 100644 index 0000000000..211247f5aa --- /dev/null +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimeZoneConsts.cs @@ -0,0 +1,6 @@ +namespace Volo.Abp.Timing; + +public class TimeZoneConsts +{ + public const string DefaultTimeZoneKey = "__timezone"; +} diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs index 066747df94..343e20feb5 100644 --- a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs +++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/TimingSettingProvider.cs @@ -10,7 +10,7 @@ public class TimingSettingProvider : SettingDefinitionProvider { context.Add( new SettingDefinition(TimingSettingNames.TimeZone, - "UTC", + "", L("DisplayName:Abp.Timing.Timezone"), L("Description:Abp.Timing.Timezone"), isVisibleToClients: true) diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs index 0e13746d66..1c705d8df3 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs @@ -159,6 +159,7 @@ public class AbpAspNetCoreMvcTestModule : AbpModule app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); + app.UseAbpTimeZone(); app.UseAuditing(); app.UseUnitOfWork(); app.UseConfiguredEndpoints(); diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/AbpTimeZoneMiddleware_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/AbpTimeZoneMiddleware_Tests.cs new file mode 100644 index 0000000000..7f12e5a07d --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/AbpTimeZoneMiddleware_Tests.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using Shouldly; +using Volo.Abp.Settings; +using Volo.Abp.Timing; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc.Timing; + +public class AbpTimeZoneMiddleware_Tests : AspNetCoreMvcTestBase +{ + private readonly ICurrentTimezoneProvider _currentTimezoneProvider; + private readonly ITimezoneProvider _timezoneProvider; + public AbpTimeZoneMiddleware_Tests() + { + _currentTimezoneProvider = GetRequiredService(); + _timezoneProvider = GetRequiredService(); + } + + protected override void ConfigureServices(IServiceCollection services) + { + services.Configure(options => + { + options.Kind = DateTimeKind.Utc; + }); + } + + [Fact] + public async Task Should_Override_TimeZone_Setting_By_Request() + { + using (_currentTimezoneProvider.Change("UTC")) + { + var result = await Client.GetStringAsync("api/timing-test"); + result.ShouldBe(GetLocalTimeZone()); + } + + // Query string + using (_currentTimezoneProvider.Change("UTC")) + { + var result = await Client.GetStringAsync("api/timing-test?__timezone=Europe/Istanbul"); + result.ShouldBe("Europe/Istanbul"); + } + + // Header + using (_currentTimezoneProvider.Change("UTC")) + { + Client.DefaultRequestHeaders.Add("__timezone", "Asia/Shanghai"); + var result = await Client.GetStringAsync("api/timing-test"); + result.ShouldBe("Asia/Shanghai"); + } + + // Form + using (_currentTimezoneProvider.Change("UTC")) + { + Client.DefaultRequestHeaders.Remove("__timezone"); + var result = await Client.PostAsync("api/timing-test", new FormUrlEncodedContent(new[] {new KeyValuePair("__timezone", "Europe/Germany")})); + (await result.Content.ReadAsStringAsync()).ShouldBe("Europe/Germany"); + } + + // Cookie + using (_currentTimezoneProvider.Change("UTC")) + { + Client.DefaultRequestHeaders.Remove("__timezone"); + Client.DefaultRequestHeaders.Add("Cookie", "__timezone=Europe/Istanbul"); + var result = await Client.GetStringAsync("api/timing-test"); + result.ShouldBe("Europe/Istanbul"); + } + } + + private string GetLocalTimeZone() + { + if (TimeZoneInfo.Local.HasIanaId) + { + return TimeZoneInfo.Local.Id; + } + + return TimeZoneInfo.TryConvertWindowsIdToIanaId(TimeZoneInfo.Local.Id, out var ianaName) + ? ianaName + : null; + } +} + + +public class AbpTimeZoneMiddleware_With_SettingValue_Tests : AspNetCoreMvcTestBase +{ + private readonly ICurrentTimezoneProvider _currentTimezoneProvider; + public AbpTimeZoneMiddleware_With_SettingValue_Tests() + { + _currentTimezoneProvider = GetRequiredService(); + } + + protected override void ConfigureServices(IServiceCollection services) + { + var settingStore = Substitute.For(); + settingStore.GetOrNullAsync(TimingSettingNames.TimeZone).Returns("Asia/Shanghai"); + services.AddSingleton(settingStore); + + services.Configure(options => + { + options.Kind = DateTimeKind.Utc; + }); + } + + [Fact] + public async Task Should_Not_Override_TimeZone_Setting_By_Request() + { + using (_currentTimezoneProvider.Change("UTC")) + { + var result = await Client.GetStringAsync("api/timing-test"); + result.ShouldBe("Asia/Shanghai"); + } + + // Query string + using (_currentTimezoneProvider.Change("UTC")) + { + var result = await Client.GetStringAsync("api/timing-test?__timezone=Europe/Istanbul"); + result.ShouldBe("Asia/Shanghai"); + } + + // Header + using (_currentTimezoneProvider.Change("UTC")) + { + Client.DefaultRequestHeaders.Add("__timezone", "Europe/Istanbul"); + var result = await Client.GetStringAsync("api/timing-test"); + result.ShouldBe("Asia/Shanghai"); + } + + // Form + using (_currentTimezoneProvider.Change("UTC")) + { + Client.DefaultRequestHeaders.Remove("__timezone"); + var result = await Client.PostAsync("api/timing-test", new FormUrlEncodedContent(new[] {new KeyValuePair("__timezone", "Europe/Istanbul")})); + (await result.Content.ReadAsStringAsync()).ShouldBe("Asia/Shanghai"); + } + + // Cookie + using (_currentTimezoneProvider.Change("UTC")) + { + Client.DefaultRequestHeaders.Remove("__timezone"); + Client.DefaultRequestHeaders.Add("Cookie", "__timezone=Europe/Istanbul"); + var result = await Client.GetStringAsync("api/timing-test"); + result.ShouldBe("Asia/Shanghai"); + } + } +} diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/TimingTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/TimingTestController.cs new file mode 100644 index 0000000000..a509e62ec5 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Timing/TimingTestController.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.Timing; + +namespace Volo.Abp.AspNetCore.Mvc.Timing; + +[Route("api/timing-test")] +public class UnitOfWorkTestController : AbpController +{ + private readonly ICurrentTimezoneProvider _currentTimezoneProvider; + + public UnitOfWorkTestController(ICurrentTimezoneProvider currentTimezoneProvider) + { + _currentTimezoneProvider = currentTimezoneProvider; + } + + [HttpGet] + public ActionResult GetAsync() + { + return Content(_currentTimezoneProvider.TimeZone ?? "null"); + } + + [HttpPost] + public ActionResult PostAsync() + { + return Content(_currentTimezoneProvider.TimeZone ?? "null"); + } +} diff --git a/framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFac_OnActivated_Tests.cs b/framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFac_OnActivated_Tests.cs index b2af6d85da..46c9ea2e8c 100644 --- a/framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFac_OnActivated_Tests.cs +++ b/framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFac_OnActivated_Tests.cs @@ -31,9 +31,9 @@ public class AutoFac_OnActivated_Tests : Autofac_Interception_Test var server = ServiceProvider.GetRequiredService(); server.Name.ShouldBe("MyServer12"); } -} -class MyServer -{ - public string Name { get; set; } = "MyServer"; + class MyServer + { + public string Name { get; set; } = "MyServer"; + } } diff --git a/framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFac_OnRegistred_Tests.cs b/framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFac_OnRegistred_Tests.cs new file mode 100644 index 0000000000..34b739cb7f --- /dev/null +++ b/framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFac_OnRegistred_Tests.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Autofac.Interception; +using Xunit; + +namespace Volo.Abp.Autofac; + +public class AutoFac_OnRegistred_Tests : Autofac_Interception_Test +{ + protected override Task AfterAddApplicationAsync(IServiceCollection services) + { + services.Add(ServiceDescriptor.KeyedTransient("key")); + services.OnRegistered(onServiceRegistredContext => + { + if (onServiceRegistredContext.ImplementationType == typeof(MyServer)) + { + onServiceRegistredContext.ServiceKey.ShouldBe("key"); + } + }); + + return base.AfterAddApplicationAsync(services); + } + + class MyServer + { + public string Name { get; set; } = "MyServer"; + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs index d82fb195ab..6249d588f5 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DomainEvents/DomainEvents_Tests.cs @@ -396,3 +396,134 @@ public class AbpEfCoreDomainEvents_Tests : EntityFrameworkCoreTestBase entityUpdatedEventTriggered.ShouldBeTrue(); } } + + +public abstract class AbpEfCoreDomainEvents_Disable_UpdateAggregateRoot_Tests : EntityFrameworkCoreTestBase +{ + protected readonly IRepository AppEntityWithNavigationsRepository; + protected readonly IRepository AppEntityWithNavigationForeignRepository; + protected readonly ILocalEventBus LocalEventBus; + + protected AbpEfCoreDomainEvents_Disable_UpdateAggregateRoot_Tests() + { + AppEntityWithNavigationsRepository = GetRequiredService>(); + AppEntityWithNavigationForeignRepository = GetRequiredService>(); + LocalEventBus = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.PublishEntityUpdatedEventWhenNavigationChanges = true; + options.UpdateAggregateRootWhenNavigationChanges = false; + }); + + base.AfterAddApplication(services); + } + + [Fact] + public async Task Should_Trigger_Domain_Events_But_Do_Not_Change_Aggregate_Root_When_Navigation_Changes_Tests() + { + var entityId = Guid.NewGuid(); + + var newEntity = await AppEntityWithNavigationsRepository.InsertAsync(new AppEntityWithNavigations(entityId, "TestEntity")); + + var latestConcurrencyStamp = newEntity.ConcurrencyStamp; + var lastModificationTime = newEntity.LastModificationTime; + + var entityUpdatedEventTriggered = false; + + LocalEventBus.Subscribe>(data => + { + entityUpdatedEventTriggered = true; + + // The Aggregate will not be updated + data.Entity.ConcurrencyStamp.ShouldBe(latestConcurrencyStamp); + data.Entity.LastModificationTime.ShouldBe(lastModificationTime); + return Task.CompletedTask; + }); + + // Test with value object + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.AppEntityWithValueObjectAddress = new AppEntityWithValueObjectAddress("Turkey"); + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + + // Test with one to one + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.OneToOne = new AppEntityWithNavigationChildOneToOne + { + ChildName = "ChildName" + }; + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + + // Test with one to many + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.OneToMany = new List() + { + new AppEntityWithNavigationChildOneToMany + { + AppEntityWithNavigationId = entity.Id, + ChildName = "ChildName1" + } + }; + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + + // Test with many to many + entityUpdatedEventTriggered = false; + await WithUnitOfWorkAsync(async () => + { + var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId); + entity.ManyToMany = new List() + { + new AppEntityWithNavigationChildManyToMany + { + ChildName = "ChildName1" + } + }; + await AppEntityWithNavigationsRepository.UpdateAsync(entity); + }); + entityUpdatedEventTriggered.ShouldBeTrue(); + } +} + +public class AbpEfCoreDomainEvents_UpdateAggregateRootWhenNavigationChanges_Tests : AbpEfCoreDomainEvents_Disable_UpdateAggregateRoot_Tests +{ + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.UpdateAggregateRootWhenNavigationChanges = false; + }); + + base.AfterAddApplication(services); + } +} + +public class AbpEfCoreDomainEvents_IgnoredUpdateAggregateRootSelectors_Test : AbpEfCoreDomainEvents_Disable_UpdateAggregateRoot_Tests +{ + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.IgnoredUpdateAggregateRootSelectors.Add("AppEntityWithValueObjectAddress", x => x == typeof(AppEntityWithNavigations)); + }); + + base.AfterAddApplication(services); + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs index 4c3b355367..2666695fd9 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/EfCoreAsyncQueryableProvider_Tests.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using Shouldly; using Volo.Abp.Domain.Repositories; using Volo.Abp.TestApp.Domain; @@ -55,4 +56,20 @@ public class EfCoreAsyncQueryableProvider_Tests : EntityFrameworkCoreTestBase await uow.CompleteAsync(); } } + + [Fact] + public async Task LastOrDefaultAsync_With_DefaultOrderBy() + { + using (var uow = _unitOfWorkManager.Begin()) + { + var lastOrDefault = await _personRepository.LastOrDefaultAsync(); + lastOrDefault.ShouldNotBeNull(); + + await Assert.ThrowsAsync(async () => + await (await _personRepository.GetQueryableAsync()).LastOrDefaultAsync() + ); + + await uow.CompleteAsync(); + } + } } diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonNewtonsoftTestModule.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonNewtonsoftTestModule.cs deleted file mode 100644 index 42559397da..0000000000 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonNewtonsoftTestModule.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Volo.Abp.Autofac; -using Volo.Abp.Json.Newtonsoft; -using Volo.Abp.Json.SystemTextJson; -using Volo.Abp.Modularity; - -namespace Volo.Abp.Json; - -[DependsOn( - typeof(AbpAutofacModule), - typeof(AbpJsonSystemTextJsonModule), - typeof(AbpTestBaseModule) -)] -public class AbpJsonSystemTextJsonTestModule : AbpModule -{ - -} - -[DependsOn( - typeof(AbpAutofacModule), - typeof(AbpJsonNewtonsoftModule), - typeof(AbpTestBaseModule) -)] -public class AbpJsonNewtonsoftTestModule : AbpModule -{ - -} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonSystemTextJsonTestBase.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonSystemTextJsonTestBase.cs deleted file mode 100644 index ebae706aca..0000000000 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonSystemTextJsonTestBase.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Volo.Abp.Testing; - -namespace Volo.Abp.Json; - -public abstract class AbpJsonSystemTextJsonTestBase : AbpIntegratedTest -{ - protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) - { - options.UseAutofac(); - } -} - -public abstract class AbpJsonNewtonsoftJsonTestBase : AbpIntegratedTest -{ - protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) - { - options.UseAutofac(); - } -} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs new file mode 100644 index 0000000000..e442ce48ad --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Concurrent; +using System.Reflection; +using Newtonsoft.Json; +using Volo.Abp.Json.Newtonsoft; +using Volo.Abp.Testing; + +namespace Volo.Abp.Json; + +public abstract class AbpJsonSystemTextJsonTestBase : AbpIntegratedTest +{ + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } +} + +public abstract class AbpJsonNewtonsoftJsonTestBase : AbpIntegratedTest +{ + protected AbpJsonNewtonsoftJsonTestBase() + { + var cache = typeof(AbpNewtonsoftJsonSerializer).GetField("JsonSerializerOptionsCache", BindingFlags.NonPublic | BindingFlags.Static); + if (cache != null) + { + var cacheValue = cache.GetValue(null)?.As>(); + cacheValue?.Clear(); + } + } + + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } +} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs new file mode 100644 index 0000000000..121ec62a85 --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.Json.Newtonsoft; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Json.SystemTextJson.JsonConverters; +using Volo.Abp.Json.SystemTextJson.Modifiers; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Json; + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpJsonSystemTextJsonModule), + typeof(AbpTestBaseModule) +)] +public class AbpJsonSystemTextJsonTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddOptions() + .Configure((options, rootServiceProvider) => + { + if (options.JsonSerializerOptions.TypeInfoResolver != null) + { + var modifiers = options.JsonSerializerOptions.TypeInfoResolver.As().Modifiers; + modifiers.RemoveAll(x => x.Target?.GetType() == typeof(AbpDateTimeConverterModifier)); + modifiers.Add(new AbpDateTimeConverterModifier( + rootServiceProvider.GetRequiredService(), + rootServiceProvider.GetRequiredService()).CreateModifyAction()); + } + }); + } +} + +[DependsOn( + typeof(AbpAutofacModule), + typeof(AbpJsonNewtonsoftModule), + typeof(AbpTestBaseModule) +)] +public class AbpJsonNewtonsoftTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddOptions() + .Configure((options, rootServiceProvider) => + { + options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver( + rootServiceProvider.GetRequiredService()); + }); + } +} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpNewtonsoftSerializerProviderTests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpNewtonsoftSerializerProviderTests.cs new file mode 100644 index 0000000000..9dc0c0afd3 --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpNewtonsoftSerializerProviderTests.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using Shouldly; +using Xunit; + +namespace Volo.Abp.Json; + +[Collection("AbpJsonNewtonsoftJsonTest")] +public class AbpNewtonsoftSerializerProviderTests : AbpJsonNewtonsoftJsonTestBase +{ + protected IJsonSerializer JsonSerializer; + + public AbpNewtonsoftSerializerProviderTests() + { + JsonSerializer = GetRequiredService(); + } + + public class File + { + public string FileName { get; set; } + + public Dictionary ExtraProperties { get; set; } + } + + [Fact] + public void Serialize_Deserialize_Test() + { + var defaultIndent = " "; // Default indent is 2 spaces + var newLine = Environment.NewLine; + var file = new File() + { + FileName = "abp", + ExtraProperties = new Dictionary() + { + { "One", 1 }, + { "Two", 2 } + } + }; + + var json = JsonSerializer.Serialize(file, camelCase: true); + json.ShouldBe("{\"fileName\":\"abp\",\"extraProperties\":{\"One\":1,\"Two\":2}}"); + + json = JsonSerializer.Serialize(file, camelCase: true, indented: true); + json.ShouldBe($"{{{newLine}{defaultIndent}\"fileName\": \"abp\",{newLine}{defaultIndent}\"extraProperties\": {{{newLine}{defaultIndent}{defaultIndent}\"One\": 1,{newLine}{defaultIndent}{defaultIndent}\"Two\": 2{newLine}{defaultIndent}}}{newLine}}}"); + + json = JsonSerializer.Serialize(file, camelCase: false); + json.ShouldBe("{\"FileName\":\"abp\",\"ExtraProperties\":{\"One\":1,\"Two\":2}}"); + + json = JsonSerializer.Serialize(file, camelCase: false, indented: true); + json.ShouldBe($"{{{newLine}{defaultIndent}\"FileName\": \"abp\",{newLine}{defaultIndent}\"ExtraProperties\": {{{newLine}{defaultIndent}{defaultIndent}\"One\": 1,{newLine}{defaultIndent}{defaultIndent}\"Two\": 2{newLine}{defaultIndent}}}{newLine}}}"); + } +} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpSystemTextJsonSerializerProvider_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpSystemTextJsonSerializerProvider_Tests.cs index e32df85d7f..49b321d46d 100644 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpSystemTextJsonSerializerProvider_Tests.cs +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpSystemTextJsonSerializerProvider_Tests.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Text.Json; using Microsoft.Extensions.DependencyInjection; using Shouldly; using Volo.Abp.Data; @@ -11,11 +13,11 @@ namespace Volo.Abp.Json; public abstract class AbpSystemTextJsonSerializerProviderTestBase : AbpJsonSystemTextJsonTestBase { - protected AbpSystemTextJsonSerializer JsonSerializer; + protected IJsonSerializer JsonSerializer; public AbpSystemTextJsonSerializerProviderTestBase() { - JsonSerializer = GetRequiredService(); + JsonSerializer = GetRequiredService(); } public class TestExtensibleObjectClass : ExtensibleObject @@ -23,6 +25,13 @@ public abstract class AbpSystemTextJsonSerializerProviderTestBase : AbpJsonSyste public string Name { get; set; } } + public class File + { + public string FileName { get; set; } + + public Dictionary ExtraProperties { get; set; } + } + public class FileWithBoolean { public string Name { get; set; } @@ -74,6 +83,34 @@ public abstract class AbpSystemTextJsonSerializerProviderTestBase : AbpJsonSyste public class AbpSystemTextJsonSerializerProviderTests : AbpSystemTextJsonSerializerProviderTestBase { + [Fact] + public void Serialize_Deserialize_Test() + { + var defaultIndent = " "; // Default indent is 2 spaces + var newLine = Environment.NewLine; + var file = new File() + { + FileName = "abp", + ExtraProperties = new Dictionary() + { + { "One", 1 }, + { "Two", 2 } + } + }; + + var json = JsonSerializer.Serialize(file, camelCase: true); + json.ShouldBe("{\"fileName\":\"abp\",\"extraProperties\":{\"One\":1,\"Two\":2}}"); + + json = JsonSerializer.Serialize(file, camelCase: true, indented: true); + json.ShouldBe($"{{{newLine}{defaultIndent}\"fileName\": \"abp\",{newLine}{defaultIndent}\"extraProperties\": {{{newLine}{defaultIndent}{defaultIndent}\"One\": 1,{newLine}{defaultIndent}{defaultIndent}\"Two\": 2{newLine}{defaultIndent}}}{newLine}}}"); + + json = JsonSerializer.Serialize(file, camelCase: false); + json.ShouldBe("{\"FileName\":\"abp\",\"ExtraProperties\":{\"One\":1,\"Two\":2}}"); + + json = JsonSerializer.Serialize(file, camelCase: false, indented: true); + json.ShouldBe($"{{{newLine}{defaultIndent}\"FileName\": \"abp\",{newLine}{defaultIndent}\"ExtraProperties\": {{{newLine}{defaultIndent}{defaultIndent}\"One\": 1,{newLine}{defaultIndent}{defaultIndent}\"Two\": 2{newLine}{defaultIndent}}}{newLine}}}"); + } + [Fact] public void Serialize_Deserialize_With_Boolean() { @@ -223,6 +260,8 @@ public class AbpSystemTextJsonSerializerProviderDateTimeFormatTests : AbpSystemT options.InputDateTimeFormats.Add("yyyy*MM*dd"); options.OutputDateTimeFormat = "yyyy*MM*dd HH*mm*ss"; }); + + base.AfterAddApplication(services); } [Fact] @@ -289,6 +328,8 @@ public class AbpSystemTextJsonSerializerProviderDatetimeKindUtcTests : AbpSystem { Kind = DateTimeKind.Utc; services.Configure(x => x.Kind = Kind); + + base.AfterAddApplication(services); } } @@ -298,6 +339,8 @@ public class AbpSystemTextJsonSerializerProviderDatetimeKindLocalTests : AbpSyst { Kind = DateTimeKind.Local; services.Configure(x => x.Kind = Kind); + + base.AfterAddApplication(services); } } diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/InputAndOutputDateTimeFormat_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/InputAndOutputDateTimeFormat_Tests.cs index cf6356477d..189a82cae0 100644 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/InputAndOutputDateTimeFormat_Tests.cs +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/InputAndOutputDateTimeFormat_Tests.cs @@ -31,6 +31,8 @@ public class InputAndOutputDateTimeFormatSystemTextJsonTests : AbpJsonSystemText { options.Kind = DateTimeKind.Utc; }); + + base.AfterAddApplication(services); } [Fact] @@ -59,6 +61,7 @@ public class InputAndOutputDateTimeFormatSystemTextJsonTests : AbpJsonSystemText } } +[Collection("AbpJsonNewtonsoftJsonTest")] public class InputAndOutputDateTimeFormatNewtonsoftTests : AbpJsonNewtonsoftJsonTestBase { private readonly IJsonSerializer _jsonSerializer; @@ -83,6 +86,8 @@ public class InputAndOutputDateTimeFormatNewtonsoftTests : AbpJsonNewtonsoftJson { options.Kind = DateTimeKind.Utc; }); + + base.AfterAddApplication(services); } [Fact] diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index e2328fdca3..524533f890 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs index e2ad9088cb..3df8699f6d 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using MongoDB.Driver.Linq; using Shouldly; +using Volo.Abp.Data; using Volo.Abp.Domain.Repositories; using Volo.Abp.TestApp; using Volo.Abp.TestApp.Domain; @@ -52,10 +53,12 @@ public class Repository_Basic_Tests : Repository_Basic_Tests p.PersonId == person.Id && p.Number == "1234567890").ShouldBeTrue(); + person.GetProperty("test-guid-property").ShouldBe(person.Id); + person.GetProperty("test-nullable-guid-property").ShouldBe(person.Id); } - + [Fact] public async Task Filter_Case_Insensitive() { (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "ISTANBUL").ShouldBeNull(); (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull(); (await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull(); - + (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "douglas").ShouldNotBeNull(); (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "DOUGLAS").ShouldNotBeNull(); (await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "Douglas").ShouldNotBeNull(); diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityCache_Tests.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityCache_Tests.cs index f1bd602102..679590ac31 100644 --- a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityCache_Tests.cs +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/EntityCache_Tests.cs @@ -70,6 +70,29 @@ public abstract class EntityCache_Tests : TestAppTestBase : TestAppTestBase where TStartupModule : IAbpModule { protected IRepository PersonRepository { get; } + protected ICityRepository CityRepository { get; } protected ILocalEventBus LocalEventBus { get; } protected IDistributedEventBus DistributedEventBus { get; } protected EntityChangeEvents_Tests() { PersonRepository = GetRequiredService>(); + CityRepository = GetRequiredService(); LocalEventBus = GetRequiredService(); DistributedEventBus = GetRequiredService(); } + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.IgnoredEventSelectors.Add(); + }); + } + [Fact] public async Task Complex_Event_Test() { @@ -62,7 +73,7 @@ public abstract class EntityChangeEvents_Tests : TestAppTestBase await uow.CompleteAsync(); } - + createdEventTriggered.ShouldBeTrue(); createdEtoTriggered.ShouldBeTrue(); } @@ -113,4 +124,33 @@ public abstract class EntityChangeEvents_Tests : TestAppTestBase updateEventCount.ShouldBe(1); updatedAge.ShouldBe(45); } + + [Fact] + public async Task Should_Not_Trigger_Event_If_Ignore_Event_Selector_Is_Configured() + { + var personCreatedEtoTriggered = false; + var cityCreatedEtoTriggered = false; + using (var uow = GetRequiredService().Begin()) + { + DistributedEventBus.Subscribe>(eto => + { + cityCreatedEtoTriggered = true; + return Task.CompletedTask; + }); + + DistributedEventBus.Subscribe>(eto => + { + personCreatedEtoTriggered = true; + return Task.CompletedTask; + }); + + await CityRepository.InsertAsync(new City(Guid.NewGuid(), "Istanbul")); + await PersonRepository.InsertAsync(new Person(Guid.NewGuid(), "John", 15)); + + await uow.CompleteAsync(); + } + + personCreatedEtoTriggered.ShouldBeTrue(); + cityCreatedEtoTriggered.ShouldBeFalse(); + } } diff --git a/framework/test/Volo.Abp.Timing.Tests/Volo.Abp.Timing.Tests.csproj b/framework/test/Volo.Abp.Timing.Tests/Volo.Abp.Timing.Tests.csproj new file mode 100644 index 0000000000..58bc261247 --- /dev/null +++ b/framework/test/Volo.Abp.Timing.Tests/Volo.Abp.Timing.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + net9.0 + + + + + + + + + + diff --git a/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/AbpTimingTestModule.cs b/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/AbpTimingTestModule.cs new file mode 100644 index 0000000000..c416477f53 --- /dev/null +++ b/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/AbpTimingTestModule.cs @@ -0,0 +1,14 @@ +using Volo.Abp.Modularity; + +namespace Volo.Abp.Timing; + +[DependsOn( + typeof(AbpTimingModule), + typeof(AbpTestBaseModule) +)] +public class AbpTimingTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + } +} diff --git a/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/Clock_Default_Tests.cs b/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/Clock_Default_Tests.cs new file mode 100644 index 0000000000..1904518180 --- /dev/null +++ b/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/Clock_Default_Tests.cs @@ -0,0 +1,110 @@ +using System; +using Shouldly; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.Timing; + +public class Clock_Default_Tests : AbpIntegratedTest +{ + private readonly IClock _clock; + private readonly ICurrentTimezoneProvider _currentTimezoneProvider; + + public Clock_Default_Tests() + { + _clock = GetRequiredService(); + _currentTimezoneProvider = GetRequiredService(); + } + + [Fact] + public void ConvertTo_Test() + { + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc); + var convertedDateTime = _clock.ConvertToUserTime(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Utc); + convertedDateTime.ToString("O").ShouldBe("2025-03-01T05:30:00.0000000Z"); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Local); + var convertedDateTime = _clock.ConvertToUserTime(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Local); + convertedDateTime.ToString("O").ShouldBe(dateTime.ToString("O")); + } + + using(_currentTimezoneProvider.Change(null)) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Local); + var convertedDateTime = _clock.ConvertToUserTime(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Local); + convertedDateTime.ToString("O").ShouldBe(dateTime.ToString("O")); + } + } + + [Fact] + public void ConvertTo_DateTimeOffset_Test() + { + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc), TimeSpan.Zero); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.Zero); + convertedDateTimeOffset.ShouldBe(dateTimeOffset); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified), TimeSpan.Zero); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.Zero); + convertedDateTimeOffset.ShouldBe(dateTimeOffset); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified), TimeSpan.FromHours(3)); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.FromHours(3)); + convertedDateTimeOffset.ShouldBe(dateTimeOffset); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified), TimeSpan.FromHours(8)); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.FromHours(8)); + convertedDateTimeOffset.ShouldBe(dateTimeOffset); + } + } + + [Fact] + public void ConvertFrom_Test() + { + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified); + var convertedDateTime = _clock.ConvertToUtc(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Unspecified); + convertedDateTime.ShouldBe(dateTime); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Local); + var convertedDateTime = _clock.ConvertToUtc(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Local); + convertedDateTime.ShouldBe(dateTime); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc); + var convertedDateTime = _clock.ConvertToUtc(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Utc); + convertedDateTime.ShouldBe(dateTime); + } + } +} diff --git a/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/Clock_Utc_Tests.cs b/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/Clock_Utc_Tests.cs new file mode 100644 index 0000000000..4ecbd0d4c6 --- /dev/null +++ b/framework/test/Volo.Abp.Timing.Tests/Volo/Abp/Timing/Clock_Utc_Tests.cs @@ -0,0 +1,132 @@ +using System; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.Timing; + +public class Clock_Utc_Tests : AbpIntegratedTest +{ + private readonly IClock _clock; + private readonly ICurrentTimezoneProvider _currentTimezoneProvider; + + public Clock_Utc_Tests() + { + _clock = GetRequiredService(); + _currentTimezoneProvider = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.Configure(options => + { + options.Kind = DateTimeKind.Utc; + }); + base.AfterAddApplication(services); + } + + [Fact] + public void ConvertTo_Test() + { + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc); + var convertedDateTime = _clock.ConvertToUserTime(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Unspecified); + convertedDateTime.ToString("O").ShouldBe("2025-03-01T08:30:00.0000000"); //Without Z + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + // ConvertTo will not convert the DateTimeKind.Local + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Local); + var convertedDateTime = _clock.ConvertToUserTime(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Local); + convertedDateTime.ToString("O").ShouldBe(dateTime.ToString("O")); + } + + using(_currentTimezoneProvider.Change(null)) + { + // ConvertTo will not convert if the timezone is not set + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Local); + var convertedDateTime = _clock.ConvertToUserTime(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Local); + convertedDateTime.ToString("O").ShouldBe(dateTime.ToString("O")); + } + } + + [Fact] + public void ConvertTo_DateTimeOffset_Test() + { + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc), TimeSpan.Zero); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.FromHours(3)); + convertedDateTimeOffset.ToString("O").ShouldBe("2025-03-01T08:30:00.0000000+03:00"); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified), TimeSpan.Zero); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.FromHours(3)); + convertedDateTimeOffset.ToString("O").ShouldBe("2025-03-01T08:30:00.0000000+03:00"); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified), TimeSpan.FromHours(3)); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.FromHours(3)); + convertedDateTimeOffset.ShouldBe(dateTimeOffset); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified), TimeSpan.FromHours(8)); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.FromHours(3)); + convertedDateTimeOffset.DateTime.ShouldBe(new DateTime(2025, 3, 1, 0, 30, 0, DateTimeKind.Unspecified)); + } + + using(_currentTimezoneProvider.Change(null)) + { + // ConvertTo will not convert if the timezone is not set + var dateTimeOffset = new DateTimeOffset(new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified), TimeSpan.FromHours(8)); + var convertedDateTimeOffset = _clock.ConvertToUserTime(dateTimeOffset); + convertedDateTimeOffset.Offset.ShouldBe(TimeSpan.FromHours(8)); + convertedDateTimeOffset.ShouldBe(dateTimeOffset); + } + } + + [Fact] + public void ConvertFrom_Test() + { + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Unspecified); + var convertedDateTime = _clock.ConvertToUtc(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Utc); + convertedDateTime.ToString("O").ShouldBe("2025-03-01T02:30:00.0000000Z"); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Local); + var convertedDateTime = _clock.ConvertToUtc(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Utc); + convertedDateTime.ToString("O").ShouldBe("2025-03-01T02:30:00.0000000Z"); + } + + using(_currentTimezoneProvider.Change("Europe/Istanbul")) + { + var dateTime = new DateTime(2025, 3, 1, 5, 30, 0, DateTimeKind.Utc); + var convertedDateTime = _clock.ConvertToUtc(dateTime); + convertedDateTime.Kind.ShouldBe(DateTimeKind.Utc); + convertedDateTime.ToString("O").ShouldBe("2025-03-01T05:30:00.0000000Z"); + } + } + +} diff --git a/latest-versions.json b/latest-versions.json index 340ed62653..da8c7b754d 100644 --- a/latest-versions.json +++ b/latest-versions.json @@ -1,5 +1,14 @@ [ - { + { + "version": "9.1.3", + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": "4.1.3" + } + }, + { "version": "9.1.1", "releaseDate": "", "type": "stable", diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs index c17eb1e28f..cef45c2f4f 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs @@ -75,7 +75,7 @@ public class LoginModel : AccountPageModel public virtual async Task OnGetAsync() { - LoginInput = new LoginInputModel(); + LoginInput ??= new LoginInputModel(); ExternalProviders = await GetExternalProviders(); diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml index 145fd82d0d..4b3d2a67dc 100644 --- a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.cshtml @@ -13,6 +13,11 @@ } + +@section styles { + +} + @if (!Model.ReturnUrl.IsNullOrWhiteSpace()) { @@ -31,8 +36,6 @@ @foreach (var group in Model.ProfileManagementPageCreationContext.Groups) { -

@group.DisplayName

-
@await Component.InvokeAsync(group.ComponentType, new { parameter = group.Parameter diff --git a/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.css b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.css new file mode 100644 index 0000000000..1493caceac --- /dev/null +++ b/modules/account/src/Volo.Abp.Account.Web/Pages/Account/Manage.css @@ -0,0 +1,3 @@ +#ProfileManagementWrapper .tab-content { + padding-top: 0 !important; +} \ No newline at end of file diff --git a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj index a33c1c74f8..1b9925261b 100644 --- a/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj +++ b/modules/audit-logging/test/Volo.Abp.AuditLogging.MongoDB.Tests/Volo.Abp.AuditLogging.MongoDB.Tests.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.analyze.json b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.analyze.json index f792712158..dda4d3a500 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.analyze.json +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo.Abp.BackgroundJobs.Domain.abppkg.analyze.json @@ -132,6 +132,11 @@ "namespace": "Volo.Abp.BackgroundJobs", "primaryKeyType": "Guid", "properties": [ + { + "type": "System.String", + "name": "ApplicationName", + "summary": "Application name that scheduled this job." + }, { "type": "System.String", "name": "JobName", @@ -230,6 +235,11 @@ "isPrivate": false, "isStatic": false, "parameters": [ + { + "type": "String", + "name": "applicationName", + "isOptional": false + }, { "type": "Int32", "name": "maxResultCount", diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj index a3f84bb18a..a1a1a47d2c 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.MongoDB.Tests/Volo.Abp.BackgroundJobs.MongoDB.Tests.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/modules/basic-theme/Volo.Abp.BasicTheme.sln b/modules/basic-theme/Volo.Abp.BasicTheme.sln index ac0ab4ed3b..66f19dad9a 100644 --- a/modules/basic-theme/Volo.Abp.BasicTheme.sln +++ b/modules/basic-theme/Volo.Abp.BasicTheme.sln @@ -1,5 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.35906.104 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED6D078F-B0A2-48E8-A09D-3B7CDF6CE3D1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{0BC55E3B-4964-48E3-A390-2ADD37980149}" @@ -65,6 +68,9 @@ Global {D02053D9-10EF-4717-A792-A53F83347816}.Release|Any CPU.ActiveCfg = Release|Any CPU {D02053D9-10EF-4717-A792-A53F83347816}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection GlobalSection(NestedProjects) = preSolution {C8068E7F-4A04-4755-8976-C2A4C0ADC708} = {ED6D078F-B0A2-48E8-A09D-3B7CDF6CE3D1} {655C0CF7-7BFA-45E4-A157-E868A97FB45B} = {ED6D078F-B0A2-48E8-A09D-3B7CDF6CE3D1} diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css index 881028a09d..d216a348af 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/wwwroot/libs/abp/css/theme.css @@ -82,10 +82,6 @@ div.dataTables_wrapper div.dataTables_length label { /* TEMP */ -.navbar-dark .navbar-nav .nav-link { - color: #000 !important; -} - .navbar-nav > .nav-item > .nav-link, .navbar-nav > .nav-item > .dropdown > .nav-link { color: #fff !important; diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml index 5f7298ca25..6c4aa7f3b8 100644 --- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml +++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Toolbar/LanguageSwitch/Default.cshtml @@ -9,7 +9,7 @@ @Model.CurrentLanguage.DisplayName - - \ No newline at end of file + + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpBadgeTagHelper)) \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml index 34ab545163..63bfbd519c 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Blockquotes.cshtml @@ -30,3 +30,6 @@ +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpBlockquoteTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml index 7473c84bb8..4f7a7a93b6 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Borders.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Border @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.BordersModel @{ ViewData["Title"] = "Borders"; @@ -196,3 +197,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpBorderTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml index 4c4164a823..f7e056ed3b 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Breadcrumbs.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.BreadcrumbsModel @{ ViewData["Title"] = "Breadcrumbs"; @@ -77,3 +78,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpBreadcrumbTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml index 94e0d7ee70..36f3f41be3 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ButtonGroups.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ButtonGroupsModel @{ ViewData["Title"] = "ButtonGroups"; @@ -268,4 +269,8 @@
- \ No newline at end of file + + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpButtonGroupTagHelper)) \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml index 08d1e0093a..ad6324614c 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ButtonsModel @{ ViewData["Title"] = "Buttons"; @@ -258,4 +259,8 @@ - \ No newline at end of file + + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpButtonTagHelper)) \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml index 2880f8b179..bfdf80e784 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml @@ -1,5 +1,7 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card +@using Volo.Abp.DependencyInjection @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CardsModel @{ ViewData["Title"] = "Cards"; @@ -41,7 +43,7 @@

-<div class="card" style="width: 18rem;">
+<div class="card mb-3" style="width: 18rem;">
   <img class="card-img-top" src=".../100px180/" alt="Card image cap">
   <div class="card-body">
     <h5 class="card-title">Card title</h5>
@@ -88,7 +90,7 @@
             
             
                 

-<div class="card" style="width: 18rem;">
+<div class="card mb-3" style="width: 18rem;">
   <div class="card-body">
     <h5 class="card-title">Card title</h5>
     <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
@@ -132,7 +134,7 @@
             
             
                 

-<div class="card" style="width: 18rem;">
+<div class="card mb-3" style="width: 18rem;">
   <ul class="list-group list-group-flush">
     <li class="list-group-item">Cras justo odio</li>
     <li class="list-group-item">Dapibus ac facilisis in</li>
@@ -174,7 +176,7 @@
             
             
                 

-<div class="card" style="width: 18rem;">
+<div class="card mb-3" style="width: 18rem;">
   <div class="card-header">
     Featured
   </div>
@@ -237,7 +239,7 @@
             
             
                 

-<div class="card" style="width: 18rem;">
+<div class="card mb-3" style="width: 18rem;">
   <img class="card-img-top" src=".../100px180/?text=Image cap" alt="Card image cap">
   <div class="card-body">
     <h5 class="card-title">Card title</h5>
@@ -290,7 +292,7 @@
             
             
                 

-<div class="card">
+<div class="card mb-3">
   <div class="card-header">
     Featured
   </div>
@@ -337,7 +339,7 @@
             
             
                 

-<div class="card">
+<div class="card mb-3">
   <div class="card-header">
     Quote
   </div>
@@ -586,4 +588,8 @@
             
         
     
-
\ No newline at end of file
+
+
+
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpCardTagHelper)) \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml.cs index 4a5d541668..01323da4d0 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml.cs +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Cards.cshtml.cs @@ -1,4 +1,10 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; +using System; +using System.Collections.Generic; +using System.Reflection; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.AspNetCore.Razor.TagHelpers; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers; +using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Card; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components; @@ -6,6 +12,6 @@ public class CardsModel : PageModel { public void OnGet() { - + } } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml index d1b6cbe0b1..9d44f19453 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CarouselsModel @{ ViewData["Title"] = "Carousels"; @@ -266,3 +267,6 @@ +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpCarouselTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml index 728afc0a1e..b8b01ec60e 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Collapse.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CollapseModel @{ ViewData["Title"] = "Collapse"; @@ -214,3 +215,28 @@ + +
+ + + + + +

abp-accordion

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpAccordionTagHelper)) + +
+ + + + +

abp-accordion-item

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpAccordionItemTagHelper)) + +
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml index b65eaf15be..800fc4bf36 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DatePicker.cshtml @@ -1,4 +1,4 @@ -@page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form.DatePicker @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.DatePickerModel

Date Picker & Date Range Picker

@@ -775,5 +775,7 @@ public class DatePickerModel : PageModel +
+@await Component.InvokeAsync("TagHelperProperties", typeof(AbpDatePickerTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml index 3f5717033d..c2d84593cf 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Dropdowns.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Dropdown @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.DropdownsModel @{ ViewData["Title"] = "Dropdowns"; @@ -735,4 +736,8 @@ - \ No newline at end of file + + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpDropdownTagHelper)) \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml index cbec1ee01c..ab44e878c7 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/DynamicForms.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form @model DynamicFormsModel @{ @@ -428,4 +429,8 @@ public class DynamicFormsModel : PageModel - \ No newline at end of file + + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpDynamicFormTagHelper)) \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml index e637aebfad..3ed17afd37 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/FormElements.cshtml @@ -1,6 +1,7 @@ @page -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components -@model FormElementsModel +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form +@model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.FormElementsModel @{ ViewData["Title"] = "Form Elements"; @@ -65,7 +66,7 @@ <input type="password" data-val="true" data-val-required="The Password field is required." id="MyModel_Password" name="MyModel.Password" class="form-control "> <span class="text-danger field-validation-valid" data-valmsg-for="MyModel.Password" data-valmsg-replace="true"></span> </div> -<div class="form-check"> +<div class="mb-2 form-check"> <input type="checkbox" data-val="true" data-val-required="The CheckMeOut field is required." id="MyModel_CheckMeOut" name="MyModel.CheckMeOut" value="true" class="form-check-input "><input name="MyModel.CheckMeOut" type="hidden" value="false"> <label class="form-check-label" for="MyModel_CheckMeOut">Check Me Out</label> </div> @@ -495,4 +496,30 @@ - \ No newline at end of file + + +
+ + + + +

abp-input

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpInputTagHelper)) + +
+ + + + +

abp-select

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpSelectTagHelper)) + +
+ + diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml index 0e33d39c59..37a9ad4428 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Grids.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.GridsModel @{ ViewData["Title"] = "Grids"; @@ -830,4 +831,38 @@
+ + + + +

abp-container

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpContainerTagHelper)) + +
+ + + + +

abp-row

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpRowTagHelper)) + +
+ + + + +

abp-column

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpColumnTagHelper)) + +
+ < back \ No newline at end of file diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml index ce66b8d5aa..71668d3496 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ListGroup.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.ListGroup @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ListGroupsModel @{ ViewData["Title"] = "List Groups"; @@ -347,3 +348,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpListGroupTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml index 9e51ef25a3..fa208cb0a8 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Modals.cshtml @@ -73,3 +73,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpModalTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml index ca9828d348..28d46eb59e 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Navs.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Nav @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.NavsModel @{ ViewData["Title"] = "Navs"; @@ -201,3 +202,31 @@ + +
+ + + + +

abp-nav-bar

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpNavBarTagHelper)) + +
+ + + + +

abp-nav-item

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpNavItemTagHelper)) + +
+ + + + diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml index 00666c091a..77fe1530a3 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Paginator.cshtml @@ -1,4 +1,6 @@ @page +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.PaginatorModel @{ ViewData["Title"] = "Paginator"; @@ -89,3 +91,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpPaginationTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml index ddc87ba66d..10fb759853 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Popovers.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.PopoversModel @{ ViewData["Title"] = "Popovers"; @@ -69,3 +70,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpPopoverTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml index 0390090e9a..3566c194db 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/ProgressBars.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.ProgressBar @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.ProgressBarsModel @{ ViewData["Title"] = "Progress Bars"; @@ -77,3 +78,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpProgressBarTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml index e39fe8cae3..f73a6d2ca5 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tables.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Table @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.TablesModel @{ ViewData["Title"] = "Tables"; @@ -449,3 +450,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpTableTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml index e9631ed179..a0efeb0c0a 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tabs.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.TabsModel @{ ViewData["Title"] = "Tabs"; @@ -293,4 +294,39 @@ - \ No newline at end of file + + +
+ + + + +

abp-tab

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpTabTagHelper)) + +
+ + + + +

abp-tab-link

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpTabLinkTagHelper)) + +
+ + + + +

abp-tab-dropdown

+
+
+ + @await Component.InvokeAsync("TagHelperProperties", typeof(AbpTabDropdownTagHelper)) + +
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml index f19161d515..7bbf1cd2da 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Tooltips.cshtml @@ -1,5 +1,6 @@ @page @using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tooltip @model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.TooltipsModel @{ ViewData["Title"] = "Tooltips"; @@ -84,3 +85,7 @@ + +
+ +@await Component.InvokeAsync("TagHelperProperties", typeof(AbpTooltipTagHelper)) diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenuContributor.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenuContributor.cs index e36f329306..625fb60a80 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenuContributor.cs +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenuContributor.cs @@ -25,6 +25,7 @@ public class BootstrapDemoMenuContributor : IMenuContributor { new ApplicationMenuItem(BootstrapDemoMenus.Components.Alerts, "Alerts", url: "/Components/Alerts"), new ApplicationMenuItem(BootstrapDemoMenus.Components.Badges, "Badges", url: "/Components/Badges"), + new ApplicationMenuItem(BootstrapDemoMenus.Components.Blockquotes, "Blockquotes", url: "/Components/Blockquotes"), new ApplicationMenuItem(BootstrapDemoMenus.Components.Borders, "Borders", url: "/Components/Borders"), new ApplicationMenuItem(BootstrapDemoMenus.Components.Breadcrumbs, "Breadcrumbs", url: "/Components/Breadcrumbs"), new ApplicationMenuItem(BootstrapDemoMenus.Components.Buttons, "Buttons", url: "/Components/Buttons"), diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenus.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenus.cs index 2f381221ed..7a758523af 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenus.cs +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Menus/BootstrapDemoMenus.cs @@ -11,6 +11,7 @@ public class BootstrapDemoMenus public const string Alerts = Root + ".Alerts"; public const string Badges = Root + ".Badges"; public const string Borders = Root + ".Borders"; + public const string Blockquotes = Root + ".Blockquotes"; public const string Breadcrumbs = Root + ".Breadcrumbs"; public const string ButtonGroups = Root + ".ButtonGroups"; public const string Buttons = Root + ".Buttons"; diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs index ad3a39c746..ac9601cda3 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs @@ -1,31 +1,42 @@ using System; -using System.IO; -using Microsoft.AspNetCore.Hosting; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; -using Serilog.Events; namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo; public class Program { - public static int Main(string[] args) + public async static Task Main(string[] args) { Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() //TODO: Should be configurable! - .MinimumLevel.Override("Microsoft", LogEventLevel.Information) + .MinimumLevel.Debug() .Enrich.FromLogContext() - .WriteTo.File("Logs/logs.txt") + .WriteTo.Async(c => c.Console()) .CreateLogger(); try { Log.Information("Starting web host."); - CreateHostBuilder(args).Build().Run(); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); return 0; } catch (Exception ex) { + if (ex is HostAbortedException) + { + throw; + } + Log.Fatal(ex, "Host terminated unexpectedly!"); return 1; } @@ -34,14 +45,4 @@ public class Program Log.CloseAndFlush(); } } - - - internal static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }) - .UseAutofac() - .UseSerilog(); } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json index 07a310a660..7ad9d24119 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json @@ -1,27 +1,12 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:51339", - "sslPort": 0 - } - }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Volo.AbpIo.Commercial.Web": { + "Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo": { "commandName": "Project", "launchBrowser": true, - "applicationUrl": "http://localhost:5000", + "applicationUrl": "https://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } -} \ No newline at end of file +} diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs deleted file mode 100644 index 838cf43402..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo; - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) - { - services.AddApplication(); - } - - public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) - { - app.InitializeApplication(); - } -} diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj index f8202b97ec..9aa8142fda 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj @@ -10,7 +10,7 @@ - + @@ -23,5 +23,5 @@ Always - + 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 07243c6b48..761ce4be75 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.2.0-rc.1", - "@abp/prismjs": "~9.2.0-rc.1", - "@abp/highlight.js": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared": "~9.2.0-rc.4", + "@abp/prismjs": "~9.2.0-rc.4", + "@abp/highlight.js": "~9.2.0-rc.4" } } 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 10c9152cc6..36daf84280 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,203 +2,203 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/clipboard@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.1.tgz#50069847848714fb155d35b656563f26f2fd870c" - integrity sha512-3lEUrQNje436F8t4nhTrIrFru1A1ZGJHgsYaXR6At50hNwWHcE1LtZKJnXm4am0dALJK/uwv4p7BfNT9Edo11A== +"@abp/clipboard@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.4.tgz#e91e8c9b9947cef648e31f17ac8050d342a88416" + integrity sha512-iUvCQK3YJKPflLWkXNsueXit+Ipez5+R5q4OdngcvTmVXIUoH8t+3iiM+Q7ohA0vRknsdEGPMUUS7TnDW9fVqA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" clipboard "^2.0.11" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/highlight.js@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.2.0-rc.1.tgz#2eabf8c5aa61a7dfa1462d87853cc37774e6b021" - integrity sha512-xmyUIB/ZNpObnZf2JeJaOgSSnowxqlkk8OUoVzjthmsVszWGJU3l8TABjWpReJclywFlrsXGZPqvg/LIuDN8tA== +"@abp/highlight.js@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.2.0-rc.4.tgz#34b5e4ac1c340b6da27a3f9f2c9d565f08a69438" + integrity sha512-Rwn6YUIbty5LuDm0PH5OM0j7Vk4OrZgWncgsubSekc/r8fh/ry6spoxdjuBB/AjwM8ZlJ0DWMQLw51K6Y18z7A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@highlightjs/cdn-assets" "~11.10.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/prismjs@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.1.tgz#623659c50c776bc8efcb7eacea70b2704ff87eec" - integrity sha512-QZ6NY4TXmWzrrZViN8v3CgH2l4fQUpEZLPsUaEmiRtq3+3meCaM3hxgNEOvcUg5IHZI7cPBRabQtVKoAPozcvQ== +"@abp/prismjs@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.4.tgz#5164e64fa04d2a852043e1f7d02952d54112748a" + integrity sha512-fUCqWhmmRMu5DgpDxyH7uyEHS6lCFk+BY+JuS22sTvyhu+Q9M4rYhFEl/E9S+cA2rfxSNAG5h7HPXUWTqHPLgg== dependencies: - "@abp/clipboard" "~9.2.0-rc.1" - "@abp/core" "~9.2.0-rc.1" + "@abp/clipboard" "~9.2.0-rc.4" + "@abp/core" "~9.2.0-rc.4" prismjs "^1.29.0" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== dependencies: just-compare "^2.3.0" diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/AbpAspNetCoreMvcUiThemeBasicDemoModule.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/AbpAspNetCoreMvcUiThemeBasicDemoModule.cs index 4ebeb18498..c887825b2b 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/AbpAspNetCoreMvcUiThemeBasicDemoModule.cs +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/AbpAspNetCoreMvcUiThemeBasicDemoModule.cs @@ -55,8 +55,8 @@ public class AbpAspNetCoreMvcUiThemeBasicDemoModule : AbpModule app.UseDeveloperExceptionPage(); } - app.MapAbpStaticAssets(); app.UseRouting(); + app.MapAbpStaticAssets(); app.UseConfiguredEndpoints(); } } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Program.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Program.cs index a27f797715..d2ca3053b8 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Program.cs +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Program.cs @@ -1,30 +1,42 @@ using System; -using Microsoft.AspNetCore.Hosting; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Serilog; -using Serilog.Events; namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo; public class Program { - public static int Main(string[] args) + public async static Task Main(string[] args) { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .Enrich.FromLogContext() - .WriteTo.Async(c => c.File("Logs/logs.txt")) .WriteTo.Async(c => c.Console()) .CreateLogger(); try { Log.Information("Starting web host."); - CreateHostBuilder(args).Build().Run(); + var builder = WebApplication.CreateBuilder(args); + builder.Host.AddAppSettingsSecretsJson() + .UseAutofac() + .UseSerilog(); + await builder.AddApplicationAsync(); + var app = builder.Build(); + await app.InitializeApplicationAsync(); + await app.RunAsync(); return 0; } catch (Exception ex) { + if (ex is HostAbortedException) + { + throw; + } + Log.Fatal(ex, "Host terminated unexpectedly!"); return 1; } @@ -33,14 +45,4 @@ public class Program Log.CloseAndFlush(); } } - - - internal static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }) - .UseAutofac() - .UseSerilog(); } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Properties/launchSettings.json b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Properties/launchSettings.json index 9bee4298ff..4ae3999794 100644 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Properties/launchSettings.json +++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Properties/launchSettings.json @@ -1,24 +1,9 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:61659", - "sslPort": 0 - } - }, "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo": { "commandName": "Project", "launchBrowser": true, - "applicationUrl": "http://localhost:5000", + "applicationUrl": "https://localhost:5001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Startup.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Startup.cs deleted file mode 100644 index a11ca855da..0000000000 --- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Startup.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo; - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) - { - services.AddApplication(); - } - - public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) - { - app.InitializeApplication(); - } -} 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 a20c06d000..16a8f597fc 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.2.0-rc.1", - "@abp/prismjs": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4", + "@abp/prismjs": "~9.2.0-rc.4" }, "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 908daa61ec..112d32cf1e 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,202 +2,202 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/clipboard@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.1.tgz#50069847848714fb155d35b656563f26f2fd870c" - integrity sha512-3lEUrQNje436F8t4nhTrIrFru1A1ZGJHgsYaXR6At50hNwWHcE1LtZKJnXm4am0dALJK/uwv4p7BfNT9Edo11A== +"@abp/clipboard@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.4.tgz#e91e8c9b9947cef648e31f17ac8050d342a88416" + integrity sha512-iUvCQK3YJKPflLWkXNsueXit+Ipez5+R5q4OdngcvTmVXIUoH8t+3iiM+Q7ohA0vRknsdEGPMUUS7TnDW9fVqA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" clipboard "^2.0.11" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/prismjs@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.1.tgz#623659c50c776bc8efcb7eacea70b2704ff87eec" - integrity sha512-QZ6NY4TXmWzrrZViN8v3CgH2l4fQUpEZLPsUaEmiRtq3+3meCaM3hxgNEOvcUg5IHZI7cPBRabQtVKoAPozcvQ== +"@abp/prismjs@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.4.tgz#5164e64fa04d2a852043e1f7d02952d54112748a" + integrity sha512-fUCqWhmmRMu5DgpDxyH7uyEHS6lCFk+BY+JuS22sTvyhu+Q9M4rYhFEl/E9S+cA2rfxSNAG5h7HPXUWTqHPLgg== dependencies: - "@abp/clipboard" "~9.2.0-rc.1" - "@abp/core" "~9.2.0-rc.1" + "@abp/clipboard" "~9.2.0-rc.4" + "@abp/core" "~9.2.0-rc.4" prismjs "^1.29.0" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== dependencies: just-compare "^2.3.0" diff --git a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj index 61c0d81d02..f5c1f561af 100644 --- a/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj +++ b/modules/blob-storing-database/test/Volo.Abp.BlobStoring.Database.MongoDB.Tests/Volo.Abp.BlobStoring.Database.MongoDB.Tests.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/modules/blogging/app/Volo.BloggingTestApp/package.json b/modules/blogging/app/Volo.BloggingTestApp/package.json index 4c612121de..092346326a 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.2.0-rc.1", - "@abp/blogging": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4", + "@abp/blogging": "~9.2.0-rc.4" } } diff --git a/modules/blogging/app/Volo.BloggingTestApp/yarn.lock b/modules/blogging/app/Volo.BloggingTestApp/yarn.lock index 63672215ea..03db0b59ea 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/yarn.lock +++ b/modules/blogging/app/Volo.BloggingTestApp/yarn.lock @@ -2,228 +2,228 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/blogging@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/blogging/-/blogging-9.2.0-rc.1.tgz#fb3a050d4919fbb5cb8ad5f48b183c4965f4d7d3" - integrity sha512-OMroH5AeH57D737ZFPTZcGSY2Bqoez/bQDgkHyBnxn1WYwXYJNtAm8HepPT5dqLmEFcSldg7lnmHbt28a1E52g== +"@abp/blogging@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/blogging/-/blogging-9.2.0-rc.4.tgz#e7d7b5dceb2bc82b4d9b5d8797da89e373cd965a" + integrity sha512-oVeiq9zFOKJihsRmQLCmIOWvgCxgnbxyZXgwgJhi2MzFaE54jg67JT+x3Pibw6LdpxHl58icdHMFuVXrqFM9aw== dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" - "@abp/owl.carousel" "~9.2.0-rc.1" - "@abp/prismjs" "~9.2.0-rc.1" - "@abp/tui-editor" "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" + "@abp/owl.carousel" "~9.2.0-rc.4" + "@abp/prismjs" "~9.2.0-rc.4" + "@abp/tui-editor" "~9.2.0-rc.4" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/clipboard@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.1.tgz#50069847848714fb155d35b656563f26f2fd870c" - integrity sha512-3lEUrQNje436F8t4nhTrIrFru1A1ZGJHgsYaXR6At50hNwWHcE1LtZKJnXm4am0dALJK/uwv4p7BfNT9Edo11A== +"@abp/clipboard@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.4.tgz#e91e8c9b9947cef648e31f17ac8050d342a88416" + integrity sha512-iUvCQK3YJKPflLWkXNsueXit+Ipez5+R5q4OdngcvTmVXIUoH8t+3iiM+Q7ohA0vRknsdEGPMUUS7TnDW9fVqA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" clipboard "^2.0.11" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/owl.carousel@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/owl.carousel/-/owl.carousel-9.2.0-rc.1.tgz#ed7cc4d3f806ea6ee15739446b114a040b93be6a" - integrity sha512-+NyE5hmJaaUBISrNgYt+Fg9R+tHC7i5WykL9dYoA0BcYP20sTovr6B3IA3jzZcLt8GGXt3HAzLfkSc21nOurSA== +"@abp/owl.carousel@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/owl.carousel/-/owl.carousel-9.2.0-rc.4.tgz#0e225bb0a5b0b9103dc9ec837f45c8dc71bb960d" + integrity sha512-SQFusBIWxYSBzkmjbQLXfd1qz7iIzT55lGcb5y8IhlBp19UwkbeyJq68Oj6maL6COyZT0O4lSBRqkGmIC1UR8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" owl.carousel "^2.3.4" -"@abp/prismjs@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.1.tgz#623659c50c776bc8efcb7eacea70b2704ff87eec" - integrity sha512-QZ6NY4TXmWzrrZViN8v3CgH2l4fQUpEZLPsUaEmiRtq3+3meCaM3hxgNEOvcUg5IHZI7cPBRabQtVKoAPozcvQ== +"@abp/prismjs@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.4.tgz#5164e64fa04d2a852043e1f7d02952d54112748a" + integrity sha512-fUCqWhmmRMu5DgpDxyH7uyEHS6lCFk+BY+JuS22sTvyhu+Q9M4rYhFEl/E9S+cA2rfxSNAG5h7HPXUWTqHPLgg== dependencies: - "@abp/clipboard" "~9.2.0-rc.1" - "@abp/core" "~9.2.0-rc.1" + "@abp/clipboard" "~9.2.0-rc.4" + "@abp/core" "~9.2.0-rc.4" prismjs "^1.29.0" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/tui-editor@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.2.0-rc.1.tgz#fdb0e13891da88a0da89dc2ee22f748b7bda7420" - integrity sha512-FVpaOF1yoox2X9ejbDQVRVDrm+5dElY5X7fxKPUthw7PUpCT+HCScVX4xtqkbF3GB3VYRdwQO2m1GdqIRC0Zlw== +"@abp/tui-editor@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.2.0-rc.4.tgz#dca06d694d7105a807887c4ddebc01c7f2a9c5f7" + integrity sha512-dpSrv1SYZh947AuN95GlrGyI61CeysJHnbsAKPmGsmZ5CH6VSDM5gpI9teo8SdhXsi9L5rtVBehCXBgDHSsiQQ== dependencies: - "@abp/jquery" "~9.2.0-rc.1" - "@abp/prismjs" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" + "@abp/prismjs" "~9.2.0-rc.4" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== dependencies: just-compare "^2.3.0" diff --git a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj index 7dcac50e69..c71d73c65d 100644 --- a/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj +++ b/modules/blogging/test/Volo.Blogging.MongoDB.Tests/Volo.Blogging.MongoDB.Tests.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/package.json index 319adb77e5..4795c5195d 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } diff --git a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock index 8524474dd3..682f82ae14 100644 --- a/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock +++ b/modules/client-simulation/demo/Volo.ClientSimulation.Demo/yarn.lock @@ -2,185 +2,185 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== dependencies: just-compare "^2.3.0" diff --git a/modules/cms-kit/angular/package.json b/modules/cms-kit/angular/package.json index 5a72096ceb..6b7c357c9a 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.2.0-rc.1", - "@abp/ng.identity": "~9.2.0-rc.1", - "@abp/ng.setting-management": "~9.2.0-rc.1", - "@abp/ng.tenant-management": "~9.2.0-rc.1", - "@abp/ng.theme.basic": "~9.2.0-rc.1", + "@abp/ng.account": "~9.2.0-rc.4", + "@abp/ng.identity": "~9.2.0-rc.4", + "@abp/ng.setting-management": "~9.2.0-rc.4", + "@abp/ng.tenant-management": "~9.2.0-rc.4", + "@abp/ng.theme.basic": "~9.2.0-rc.4", "@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 53ed83b2bd..a312a0ff35 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.2.0-rc.1", - "@abp/ng.theme.shared": ">=9.2.0-rc.1" + "@abp/ng.core": ">=9.2.0-rc.4", + "@abp/ng.theme.shared": ">=9.2.0-rc.4" }, "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 82bc8fc24c..cb48f8ff94 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock index 8524474dd3..682f82ae14 100644 --- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock +++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/yarn.lock @@ -2,185 +2,185 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== 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 ece4546430..367ececa5e 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } 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 8524474dd3..682f82ae14 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Host/yarn.lock +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Host/yarn.lock @@ -2,185 +2,185 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== 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 8d367f02e8..1134f3a375 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.2.0-rc.1", - "@abp/cms-kit": "9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4", + "@abp/cms-kit": "9.2.0-rc.4" } } 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 dea3820ce1..1f632241e5 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/yarn.lock @@ -2,293 +2,293 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/clipboard@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.1.tgz#50069847848714fb155d35b656563f26f2fd870c" - integrity sha512-3lEUrQNje436F8t4nhTrIrFru1A1ZGJHgsYaXR6At50hNwWHcE1LtZKJnXm4am0dALJK/uwv4p7BfNT9Edo11A== +"@abp/clipboard@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.4.tgz#e91e8c9b9947cef648e31f17ac8050d342a88416" + integrity sha512-iUvCQK3YJKPflLWkXNsueXit+Ipez5+R5q4OdngcvTmVXIUoH8t+3iiM+Q7ohA0vRknsdEGPMUUS7TnDW9fVqA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" clipboard "^2.0.11" -"@abp/cms-kit.admin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/cms-kit.admin/-/cms-kit.admin-9.2.0-rc.1.tgz#6965f9448e9968ae6b23c55d51873b8dbc0a3ba0" - integrity sha512-FsQlYUv6JYf7uccOabBY0bhprSOK6t6reRA3JFmU0M9LAEBN8XDl6qL8d/vcAznwOSm/nUAIo1VeKAKUjF6XWg== +"@abp/cms-kit.admin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/cms-kit.admin/-/cms-kit.admin-9.2.0-rc.4.tgz#0e83fbeac3fe1191b82defaeb8959c69c9458593" + integrity sha512-xpuaCV+/G9kgzTCWhIfLuEIwWTCq1W3B780eyJ4fnLmg+17BOv+LsP6ygGqARnmjsWYEX6wG1C3NdDkkNE4Dlg== dependencies: - "@abp/codemirror" "~9.2.0-rc.1" - "@abp/jstree" "~9.2.0-rc.1" - "@abp/markdown-it" "~9.2.0-rc.1" - "@abp/slugify" "~9.2.0-rc.1" - "@abp/tui-editor" "~9.2.0-rc.1" - "@abp/uppy" "~9.2.0-rc.1" + "@abp/codemirror" "~9.2.0-rc.4" + "@abp/jstree" "~9.2.0-rc.4" + "@abp/markdown-it" "~9.2.0-rc.4" + "@abp/slugify" "~9.2.0-rc.4" + "@abp/tui-editor" "~9.2.0-rc.4" + "@abp/uppy" "~9.2.0-rc.4" -"@abp/cms-kit.public@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/cms-kit.public/-/cms-kit.public-9.2.0-rc.1.tgz#055fd81cfbbbcf2dce6c006f53a3d9a8f634e729" - integrity sha512-4m0vAyQHaEaSyVaC/X8UPer4Wwz6XiBN87KXY1Mg7TbjNZNsjGtd6Kouct5EwGYV5R296W5VhxvLQBzqTivIww== +"@abp/cms-kit.public@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/cms-kit.public/-/cms-kit.public-9.2.0-rc.4.tgz#5d2f4bdf4db020c2fb60d58a67314c28dac953a0" + integrity sha512-WFRLfDQDL9WNRlvRgzOI2TWliGWkdk3hzVwnYcPint0p7tBjeVFkpEPVYBR33hkLYJJAKCgPKf1xnzPfLwfUgg== dependencies: - "@abp/highlight.js" "~9.2.0-rc.1" - "@abp/star-rating-svg" "~9.2.0-rc.1" + "@abp/highlight.js" "~9.2.0-rc.4" + "@abp/star-rating-svg" "~9.2.0-rc.4" -"@abp/cms-kit@9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/cms-kit/-/cms-kit-9.2.0-rc.1.tgz#63097f42539d6bcdc36ebab9bebea7bfc195f922" - integrity sha512-vfWy0Lrc9hRFZ87jtMUIi/soOuc00v5mwJgUVX6dDuIWr+dQ+MvffQ2WfCvM512q2XoQsdlRs7PTL6GIzaDfqg== +"@abp/cms-kit@9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/cms-kit/-/cms-kit-9.2.0-rc.4.tgz#008a367579f14ccc192eefe4e8f10a3e2835093d" + integrity sha512-nzCQ1k7gEsfBjdgF+vtU0w4NEKnSlEGhK0D3HlWeakqJYi5CuMNIpMYmJCijaHOBUrmT59BfL00hoz/BNcKHwA== dependencies: - "@abp/cms-kit.admin" "~9.2.0-rc.1" - "@abp/cms-kit.public" "~9.2.0-rc.1" + "@abp/cms-kit.admin" "~9.2.0-rc.4" + "@abp/cms-kit.public" "~9.2.0-rc.4" -"@abp/codemirror@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/codemirror/-/codemirror-9.2.0-rc.1.tgz#387c935361f8d434b9b9829c3b1e905e0461976f" - integrity sha512-KtLXu6LBo1v3pHqfm5i0+5DHddg9Wuc8iAeAu0TDyV9/D8nwVDYmVotOcVY8pLV1AWxJ1+X7fse7NH9QDlPUvg== +"@abp/codemirror@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/codemirror/-/codemirror-9.2.0-rc.4.tgz#69430d5882f60c6d2b76557c76ef31143cafaeff" + integrity sha512-uYcmMb5j/eDYY6GSOUZ/kdlrwY8QD5JAThFetzZpc2j/lfbnXwA7sA/JYLBOrud6ChwTCqE293wXpldtWbqm4A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" codemirror "^5.65.1" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/highlight.js@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.2.0-rc.1.tgz#2eabf8c5aa61a7dfa1462d87853cc37774e6b021" - integrity sha512-xmyUIB/ZNpObnZf2JeJaOgSSnowxqlkk8OUoVzjthmsVszWGJU3l8TABjWpReJclywFlrsXGZPqvg/LIuDN8tA== +"@abp/highlight.js@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/highlight.js/-/highlight.js-9.2.0-rc.4.tgz#34b5e4ac1c340b6da27a3f9f2c9d565f08a69438" + integrity sha512-Rwn6YUIbty5LuDm0PH5OM0j7Vk4OrZgWncgsubSekc/r8fh/ry6spoxdjuBB/AjwM8ZlJ0DWMQLw51K6Y18z7A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@highlightjs/cdn-assets" "~11.10.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/jstree@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jstree/-/jstree-9.2.0-rc.1.tgz#b2778864d8472d531c9acca4e300c1c788fcd712" - integrity sha512-8xuyLu1cxR6+9vQ83etxFCi3FUq17bCgE9Mjt4RXOpXAdEg2GV/pyL3skJfzfIF1sPVxmaxOrE5kaURCW0psLQ== +"@abp/jstree@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jstree/-/jstree-9.2.0-rc.4.tgz#352c40541706b9b49ac47eaad6253475086527d1" + integrity sha512-bkOL5Ip/ZiD1hjG7CC55sP/+79HcIYa/jVfVWj86ke6d/taA2IUhzmvVYcxJ2gABbK3nz0bVTrF7nqTBD9HaxA== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jstree "^3.3.17" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/markdown-it@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/markdown-it/-/markdown-it-9.2.0-rc.1.tgz#f3a34b9efbb957c802cbb0ddccce1cc16231fe01" - integrity sha512-o0S+irI1tQsODFh4cU6qtCmtTnjLOoeDdi/gzEke4nKhpVOIcvgiOawcsl/CoX1Gg7U1akque2WRL+bA3TIRnw== +"@abp/markdown-it@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/markdown-it/-/markdown-it-9.2.0-rc.4.tgz#f22ba1310cc23406706acb708d4a4953ff7bc2dc" + integrity sha512-Uz8Y8P0yn8vo8+WtlRD39wjJy1euz+Q+7DwaxY7GJE1fnLCdWMowK+umPihhgTE0hoXmsDuXHvE3ZxsgptayIA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" markdown-it "^14.1.0" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/prismjs@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.1.tgz#623659c50c776bc8efcb7eacea70b2704ff87eec" - integrity sha512-QZ6NY4TXmWzrrZViN8v3CgH2l4fQUpEZLPsUaEmiRtq3+3meCaM3hxgNEOvcUg5IHZI7cPBRabQtVKoAPozcvQ== +"@abp/prismjs@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.4.tgz#5164e64fa04d2a852043e1f7d02952d54112748a" + integrity sha512-fUCqWhmmRMu5DgpDxyH7uyEHS6lCFk+BY+JuS22sTvyhu+Q9M4rYhFEl/E9S+cA2rfxSNAG5h7HPXUWTqHPLgg== dependencies: - "@abp/clipboard" "~9.2.0-rc.1" - "@abp/core" "~9.2.0-rc.1" + "@abp/clipboard" "~9.2.0-rc.4" + "@abp/core" "~9.2.0-rc.4" prismjs "^1.29.0" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/slugify@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/slugify/-/slugify-9.2.0-rc.1.tgz#ed7e6d96a698b83fc11d49c4a4ed0ab892a00167" - integrity sha512-RmMpbQYR5h0Lnf2bXCxEsGKcRzQJYFfa5SRsY++KTi8geHI2oh/zckm7Rw10zVxbyMufn71Z4kyGYOtuUAZLFQ== +"@abp/slugify@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/slugify/-/slugify-9.2.0-rc.4.tgz#d20d6013182f15c6129f4b9bcbd2fb2f5abebfa8" + integrity sha512-247cvIVnAhiw+KOSrBdRjQoi/igBH8mcpf2wR3Ag2Mng9L0NWEnx+aqBP92/3nXQi2HDwIZ3N0TQUf6Q8BLU0Q== dependencies: slugify "^1.6.6" -"@abp/star-rating-svg@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/star-rating-svg/-/star-rating-svg-9.2.0-rc.1.tgz#1554b029341638247d73a1da48604498eb87344b" - integrity sha512-DNo1QyvB7yNF7eCGq0JTWLMRj2gvMT3I/c162ZJ2ZuOe4WBt6P5eS61DGXW9Sde3+JlUSh5mvYYDMJuR/WbARA== +"@abp/star-rating-svg@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/star-rating-svg/-/star-rating-svg-9.2.0-rc.4.tgz#af32f85a2b74ac2d1debc2cb4eeb74c3b577d77c" + integrity sha512-3SdcXMbPzRWlCzuALUwYmdAYptHuVjVOD6trvw8WuZ4X2ix0S0UZ2vaQFeX+mrVZoPHnp5PruoZhcnm8t+N9rw== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" star-rating-svg "^3.5.0" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/tui-editor@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.2.0-rc.1.tgz#fdb0e13891da88a0da89dc2ee22f748b7bda7420" - integrity sha512-FVpaOF1yoox2X9ejbDQVRVDrm+5dElY5X7fxKPUthw7PUpCT+HCScVX4xtqkbF3GB3VYRdwQO2m1GdqIRC0Zlw== +"@abp/tui-editor@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/tui-editor/-/tui-editor-9.2.0-rc.4.tgz#dca06d694d7105a807887c4ddebc01c7f2a9c5f7" + integrity sha512-dpSrv1SYZh947AuN95GlrGyI61CeysJHnbsAKPmGsmZ5CH6VSDM5gpI9teo8SdhXsi9L5rtVBehCXBgDHSsiQQ== dependencies: - "@abp/jquery" "~9.2.0-rc.1" - "@abp/prismjs" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" + "@abp/prismjs" "~9.2.0-rc.4" -"@abp/uppy@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/uppy/-/uppy-9.2.0-rc.1.tgz#4f05e7f1db4fac6662c315fe7b51634564e12488" - integrity sha512-XlG4qc4QrUjlL+o41expGJU4ESs5S4BMYRMYBP/6YhJrDC15tG0+bQp8OP8qNWP8PPTu9tQ4/U+C5qvckvyjng== +"@abp/uppy@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/uppy/-/uppy-9.2.0-rc.4.tgz#a2241128f0e2ada9ae667aa45ba29ac08c4c97ef" + integrity sha512-hIrmltycYeDINFixb3AjnU7UiOdZ/uIIYx9Na4K2Zk2Gc3gyChsAtQ35UIH0UpRYBDf/+4r1G2GddP8TQ2nwQw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" uppy "^4.4.1" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== dependencies: just-compare "^2.3.0" diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/Index.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/Index.cshtml index d15396f33d..788ae3f682 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/Index.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/Index.cshtml @@ -35,7 +35,7 @@ -
+
diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/index.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/index.js index f8aa2ba80d..587e7f77ec 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/index.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Approve/index.js @@ -6,15 +6,8 @@ moment()._locale.preparse = (string) => string; moment()._locale.postformat = (string) => string; - var getFormattedDate = function ($datePicker) { - if (!$datePicker.val()) { - return null; - } - var momentDate = moment($datePicker.val(), $datePicker.data('daterangepicker').locale.format); - return momentDate.isValid() ? momentDate.toISOString() : null; - }; - - $('.singledatepicker').daterangepicker({ + var singleDatePicker = $('#CmsKitCommentsApproveWrapper .singledatepicker'); + singleDatePicker.daterangepicker({ "singleDatePicker": true, "showDropdowns": true, "autoUpdateInput": false, @@ -23,22 +16,19 @@ "drops": "auto" }); - $('.singledatepicker').attr('autocomplete', 'off'); + singleDatePicker.attr('autocomplete', 'off'); - $('.singledatepicker').on('apply.daterangepicker', function (ev, picker) { + singleDatePicker.on('apply.daterangepicker', function (ev, picker) { $(this).val(picker.startDate.format('l')); }); var filterForm = $('#CmsKitCommentsFilterForm'); var getFilter = function () { - var filterObj = filterForm.serializeFormToObject(); - - filterObj.creationStartDate = getFormattedDate($('#CreationStartDate')); - filterObj.creationEndDate = getFormattedDate($('#CreationEndDate')); - filterObj.commentApproveState = "Waiting"; - - return filterObj; + filterForm.handleDatepicker('.singledatepicker'); + var formObject = filterForm.serializeFormToObject(); + formObject.commentApproveState = "Waiting"; + return formObject; }; var _dataTable = $('#CommentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({ diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml index a73475bac2..a9d064235f 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/Details.cshtml @@ -33,7 +33,7 @@ } -
+
diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.js index 2d007b0983..33f0b9211c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/details.js @@ -8,15 +8,12 @@ $(function (){ if (commentRequireApprovement) { $('#IsApprovedSelectInput').show(); } - - var getFormattedDate = function ($datePicker) { - return $datePicker.data('date'); - }; - + moment.localeData().preparse = (s)=>s; moment.localeData().postformat = (s)=>s; - - $('.singledatepicker').daterangepicker({ + + var singleDatePicker = $('#CmsKitCommentsDetailsWrapper .singledatepicker'); + singleDatePicker.daterangepicker({ "singleDatePicker": true, "showDropdowns": true, "autoUpdateInput": false, @@ -27,9 +24,9 @@ $(function (){ "maxYear": 2199, }); - $('.singledatepicker').attr('autocomplete', 'off'); + singleDatePicker.attr('autocomplete', 'off'); - $('.singledatepicker').on('apply.daterangepicker', function (ev, picker) { + singleDatePicker.on('apply.daterangepicker', function (ev, picker) { $(this).val(picker.startDate.format('l')); $(this).data('date', picker.startDate.locale('en').format('YYYY-MM-DD')); }); @@ -37,12 +34,9 @@ $(function (){ var filterForm = $('#CmsKitCommentsFilterForm'); var getFilter = function () { - var filterObj = filterForm.serializeFormToObject(); - - filterObj.creationStartDate = getFormattedDate($('#creationStartDate')); - filterObj.creationEndDate = getFormattedDate($('#creationEndDate')); - - return filterObj; + filterForm.handleDatepicker('.singledatepicker'); + var formObject = filterForm.serializeFormToObject(); + return formObject; }; var _dataTable = $('#CommentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({ diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.js b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.js index be652ce552..ad0b8049f6 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.js +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Web/Pages/CmsKit/Comments/index.js @@ -2,7 +2,6 @@ $(function () { var l = abp.localization.getResource("CmsKit"); var commentsService = volo.cmsKit.admin.comments.commentAdmin; - moment()._locale.preparse = (string) => string; moment()._locale.postformat = (string) => string; @@ -13,15 +12,8 @@ $(function () { $('#IsApprovedSelectInput').show(); } - var getFormattedDate = function ($datePicker) { - if (!$datePicker.val()) { - return null; - } - var momentDate = moment($datePicker.val(), $datePicker.data('daterangepicker').locale.format); - return momentDate.isValid() ? momentDate.toISOString() : null; - }; - - $('.singledatepicker').daterangepicker({ + var singleDatePicker = $('#CmsKitCommentsWrapper .singledatepicker'); + singleDatePicker.daterangepicker({ "singleDatePicker": true, "showDropdowns": true, "autoUpdateInput": false, @@ -30,21 +22,18 @@ $(function () { "drops": "auto" }); - $('.singledatepicker').attr('autocomplete', 'off'); + singleDatePicker.attr('autocomplete', 'off'); - $('.singledatepicker').on('apply.daterangepicker', function (ev, picker) { + singleDatePicker.on('apply.daterangepicker', function (ev, picker) { $(this).val(picker.startDate.format('l')); }); var filterForm = $('#CmsKitCommentsFilterForm'); var getFilter = function () { - var filterObj = filterForm.serializeFormToObject(); - - filterObj.creationStartDate = getFormattedDate($('#CreationStartDate')); - filterObj.creationEndDate = getFormattedDate($('#CreationEndDate')); - - return filterObj; + filterForm.handleDatepicker('.singledatepicker'); + var formObject = filterForm.serializeFormToObject(); + return formObject; }; var _dataTable = $('#CommentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({ diff --git a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj index 9c8dc44660..a537cf8943 100644 --- a/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj +++ b/modules/cms-kit/test/Volo.CmsKit.MongoDB.Tests/Volo.CmsKit.MongoDB.Tests.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/modules/docs/Volo.Docs.sln b/modules/docs/Volo.Docs.sln index 6bb8d84d0a..af9282dca3 100644 --- a/modules/docs/Volo.Docs.sln +++ b/modules/docs/Volo.Docs.sln @@ -63,6 +63,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.MongoDB.Tests", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.Installer", "src\Volo.Docs.Installer\Volo.Docs.Installer.csproj", "{50B9AC1D-C03E-47AA-9ED8-E7986BCFABA1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.Common.Application", "src\Volo.Docs.Common.Application\Volo.Docs.Common.Application.csproj", "{914EDEC4-EFCE-46D5-B6E0-A928B1907307}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.Common.Application.Contracts", "src\Volo.Docs.Common.Application.Contracts\Volo.Docs.Common.Application.Contracts.csproj", "{8CA19527-6870-4617-B6D1-EA8CAF224DF4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{F778B2C3-2E6D-4CF3-ACA7-10E21E6A7961}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.Common.HttpApi", "src\Volo.Docs.Common.HttpApi\Volo.Docs.Common.HttpApi.csproj", "{052C076D-56FF-4DFA-838B-48BD30A1DB0A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.Common.HttpApi.Client", "src\Volo.Docs.Common.HttpApi.Client\Volo.Docs.Common.HttpApi.Client.csproj", "{349C36A0-552D-44A3-AC74-03A4828D43AB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -165,6 +175,22 @@ Global {50B9AC1D-C03E-47AA-9ED8-E7986BCFABA1}.Debug|Any CPU.Build.0 = Debug|Any CPU {50B9AC1D-C03E-47AA-9ED8-E7986BCFABA1}.Release|Any CPU.ActiveCfg = Release|Any CPU {50B9AC1D-C03E-47AA-9ED8-E7986BCFABA1}.Release|Any CPU.Build.0 = Release|Any CPU + {914EDEC4-EFCE-46D5-B6E0-A928B1907307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {914EDEC4-EFCE-46D5-B6E0-A928B1907307}.Debug|Any CPU.Build.0 = Debug|Any CPU + {914EDEC4-EFCE-46D5-B6E0-A928B1907307}.Release|Any CPU.ActiveCfg = Release|Any CPU + {914EDEC4-EFCE-46D5-B6E0-A928B1907307}.Release|Any CPU.Build.0 = Release|Any CPU + {8CA19527-6870-4617-B6D1-EA8CAF224DF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CA19527-6870-4617-B6D1-EA8CAF224DF4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CA19527-6870-4617-B6D1-EA8CAF224DF4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CA19527-6870-4617-B6D1-EA8CAF224DF4}.Release|Any CPU.Build.0 = Release|Any CPU + {052C076D-56FF-4DFA-838B-48BD30A1DB0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {052C076D-56FF-4DFA-838B-48BD30A1DB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {052C076D-56FF-4DFA-838B-48BD30A1DB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {052C076D-56FF-4DFA-838B-48BD30A1DB0A}.Release|Any CPU.Build.0 = Release|Any CPU + {349C36A0-552D-44A3-AC74-03A4828D43AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {349C36A0-552D-44A3-AC74-03A4828D43AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {349C36A0-552D-44A3-AC74-03A4828D43AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {349C36A0-552D-44A3-AC74-03A4828D43AB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -197,6 +223,11 @@ Global {DBE846CD-1BED-4F2C-ABF2-94F6240BCB9B} = {A982A58E-1E92-4764-9F56-39E7AABB8556} {C5E2A2A3-D54D-4C2E-97BA-EA50A49ED7AD} = {59D430A9-AC61-4457-8338-5DA0705ABB5D} {50B9AC1D-C03E-47AA-9ED8-E7986BCFABA1} = {A982A58E-1E92-4764-9F56-39E7AABB8556} + {F778B2C3-2E6D-4CF3-ACA7-10E21E6A7961} = {42416152-5BAB-4706-93A6-57A19E71FE14} + {914EDEC4-EFCE-46D5-B6E0-A928B1907307} = {F778B2C3-2E6D-4CF3-ACA7-10E21E6A7961} + {8CA19527-6870-4617-B6D1-EA8CAF224DF4} = {F778B2C3-2E6D-4CF3-ACA7-10E21E6A7961} + {052C076D-56FF-4DFA-838B-48BD30A1DB0A} = {F778B2C3-2E6D-4CF3-ACA7-10E21E6A7961} + {349C36A0-552D-44A3-AC74-03A4828D43AB} = {F778B2C3-2E6D-4CF3-ACA7-10E21E6A7961} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {13691265-2547-4FFF-B757-E8FACB05679D} diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20241231072012_Initial.Designer.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250411070040_initial.Designer.cs similarity index 93% rename from modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20241231072012_Initial.Designer.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250411070040_initial.Designer.cs index ad7dfa9576..325052b498 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20241231072012_Initial.Designer.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250411070040_initial.Designer.cs @@ -13,8 +13,8 @@ using VoloDocs.EntityFrameworkCore; namespace Migrations { [DbContext(typeof(VoloDocsDbContext))] - [Migration("20241231072012_Initial")] - partial class Initial + [Migration("20250411070040_initial")] + partial class initial { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -22,11 +22,88 @@ namespace Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContainerId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .HasMaxLength(2147483647) + .HasColumnType("varbinary(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ContainerId"); + + b.HasIndex("TenantId", "ContainerId", "Name"); + + b.ToTable("AbpBlobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AbpBlobContainers", (string)null); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") @@ -1119,6 +1196,15 @@ namespace Migrations b.ToTable("DocsProjects", (string)null); }); + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.HasOne("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", null) + .WithMany() + .HasForeignKey("ContainerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20241231072012_Initial.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250411070040_initial.cs similarity index 93% rename from modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20241231072012_Initial.cs rename to modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250411070040_initial.cs index 25791fabf4..1c03234da9 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20241231072012_Initial.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250411070040_initial.cs @@ -6,11 +6,26 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace Migrations { /// - public partial class Initial : Migration + public partial class initial : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.CreateTable( + name: "AbpBlobContainers", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpBlobContainers", x => x.Id); + }); + migrationBuilder.CreateTable( name: "AbpClaimTypes", columns: table => new @@ -336,6 +351,29 @@ namespace Migrations table.PrimaryKey("PK_DocsProjects", x => x.Id); }); + migrationBuilder.CreateTable( + name: "AbpBlobs", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + ContainerId = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Content = table.Column(type: "varbinary(max)", maxLength: 2147483647, nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpBlobs", x => x.Id); + table.ForeignKey( + name: "FK_AbpBlobs_AbpBlobContainers_ContainerId", + column: x => x.ContainerId, + principalTable: "AbpBlobContainers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + migrationBuilder.CreateTable( name: "AbpOrganizationUnitRoles", columns: table => new @@ -520,6 +558,21 @@ namespace Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateIndex( + name: "IX_AbpBlobContainers_TenantId_Name", + table: "AbpBlobContainers", + columns: new[] { "TenantId", "Name" }); + + migrationBuilder.CreateIndex( + name: "IX_AbpBlobs_ContainerId", + table: "AbpBlobs", + column: "ContainerId"); + + migrationBuilder.CreateIndex( + name: "IX_AbpBlobs_TenantId_ContainerId_Name", + table: "AbpBlobs", + columns: new[] { "TenantId", "ContainerId", "Name" }); + migrationBuilder.CreateIndex( name: "IX_AbpLinkUsers_SourceUserId_SourceTenantId_TargetUserId_TargetTenantId", table: "AbpLinkUsers", @@ -668,6 +721,9 @@ namespace Migrations /// protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropTable( + name: "AbpBlobs"); + migrationBuilder.DropTable( name: "AbpClaimTypes"); @@ -725,6 +781,9 @@ namespace Migrations migrationBuilder.DropTable( name: "DocsProjects"); + migrationBuilder.DropTable( + name: "AbpBlobContainers"); + migrationBuilder.DropTable( name: "AbpOrganizationUnits"); diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250425082043_add_pdf_file.Designer.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250425082043_add_pdf_file.Designer.cs new file mode 100644 index 0000000000..c284a80f8b --- /dev/null +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250425082043_add_pdf_file.Designer.cs @@ -0,0 +1,1376 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; +using VoloDocs.EntityFrameworkCore; + +#nullable disable + +namespace Migrations +{ + [DbContext(typeof(VoloDocsDbContext))] + [Migration("20250425082043_add_pdf_file")] + partial class add_pdf_file + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("ProductVersion", "9.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContainerId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .HasMaxLength(2147483647) + .HasColumnType("varbinary(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ContainerId"); + + b.HasIndex("TenantId", "ContainerId", "Name"); + + b.ToTable("AbpBlobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AbpBlobContainers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime2"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetimeoffset"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[TenantId] IS NOT NULL"); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("bit"); + + b.Property("IsInherited") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Docs.Documents.Document", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("EditLink") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Format") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("LanguageCode") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("LastCachedTime") + .HasColumnType("datetime2"); + + b.Property("LastSignificantUpdateTime") + .HasColumnType("datetime2"); + + b.Property("LastUpdatedTime") + .HasColumnType("datetime2"); + + b.Property("LocalDirectory") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("RawRootUrl") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("RootUrl") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Version") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("DocsDocuments", (string)null); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.Property("DocumentId") + .HasColumnType("uniqueidentifier"); + + b.Property("Username") + .HasColumnType("nvarchar(450)"); + + b.Property("AvatarUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("CommitCount") + .HasColumnType("int"); + + b.Property("UserProfileUrl") + .HasColumnType("nvarchar(max)"); + + b.HasKey("DocumentId", "Username"); + + b.ToTable("DocsDocumentContributors", (string)null); + }); + + modelBuilder.Entity("Volo.Docs.Projects.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("DefaultDocumentName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("DocumentStoreType") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Format") + .HasColumnType("nvarchar(max)"); + + b.Property("LatestVersionBranchName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("MainWebsiteUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("MinimumVersion") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("NavigationDocumentName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParametersDocumentName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ShortName") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.HasKey("Id"); + + b.ToTable("DocsProjects", (string)null); + }); + + modelBuilder.Entity("Volo.Docs.Projects.ProjectPdfFile", b => + { + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("FileName") + .HasColumnType("nvarchar(450)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("LanguageCode") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("Version") + .HasColumnType("nvarchar(max)"); + + b.HasKey("ProjectId", "FileName"); + + b.ToTable("DocsProjectPdfFiles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.HasOne("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", null) + .WithMany() + .HasForeignKey("ContainerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Docs.Documents.DocumentContributor", b => + { + b.HasOne("Volo.Docs.Documents.Document", null) + .WithMany("Contributors") + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Docs.Projects.ProjectPdfFile", b => + { + b.HasOne("Volo.Docs.Projects.Project", null) + .WithMany("PdfFiles") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Docs.Documents.Document", b => + { + b.Navigation("Contributors"); + }); + + modelBuilder.Entity("Volo.Docs.Projects.Project", b => + { + b.Navigation("PdfFiles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250425082043_add_pdf_file.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250425082043_add_pdf_file.cs new file mode 100644 index 0000000000..2f9f296c25 --- /dev/null +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/20250425082043_add_pdf_file.cs @@ -0,0 +1,44 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Migrations +{ + /// + public partial class add_pdf_file : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "DocsProjectPdfFiles", + columns: table => new + { + ProjectId = table.Column(type: "uniqueidentifier", nullable: false), + FileName = table.Column(type: "nvarchar(450)", nullable: false), + Version = table.Column(type: "nvarchar(max)", nullable: true), + LanguageCode = table.Column(type: "nvarchar(max)", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + LastModificationTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_DocsProjectPdfFiles", x => new { x.ProjectId, x.FileName }); + table.ForeignKey( + name: "FK_DocsProjectPdfFiles_DocsProjects_ProjectId", + column: x => x.ProjectId, + principalTable: "DocsProjects", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "DocsProjectPdfFiles"); + } + } +} diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs index 17e18940bb..14f36cafb1 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/Migrations/VoloDocsDbContextModelSnapshot.cs @@ -19,11 +19,88 @@ namespace Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) - .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("ProductVersion", "9.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ContainerId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .HasMaxLength(2147483647) + .HasColumnType("varbinary(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ContainerId"); + + b.HasIndex("TenantId", "ContainerId", "Name"); + + b.ToTable("AbpBlobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AbpBlobContainers", (string)null); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => { b.Property("Id") @@ -1116,6 +1193,42 @@ namespace Migrations b.ToTable("DocsProjects", (string)null); }); + modelBuilder.Entity("Volo.Docs.Projects.ProjectPdfFile", b => + { + b.Property("ProjectId") + .HasColumnType("uniqueidentifier"); + + b.Property("FileName") + .HasColumnType("nvarchar(450)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("LanguageCode") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("Version") + .HasColumnType("nvarchar(max)"); + + b.HasKey("ProjectId", "FileName"); + + b.ToTable("DocsProjectPdfFiles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BlobStoring.Database.DatabaseBlob", b => + { + b.HasOne("Volo.Abp.BlobStoring.Database.DatabaseBlobContainer", null) + .WithMany() + .HasForeignKey("ContainerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => { b.HasOne("Volo.Abp.Identity.IdentityRole", null) @@ -1213,6 +1326,15 @@ namespace Migrations .IsRequired(); }); + modelBuilder.Entity("Volo.Docs.Projects.ProjectPdfFile", b => + { + b.HasOne("Volo.Docs.Projects.Project", null) + .WithMany("PdfFiles") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Navigation("Claims"); @@ -1240,6 +1362,11 @@ namespace Migrations { b.Navigation("Contributors"); }); + + modelBuilder.Entity("Volo.Docs.Projects.Project", b => + { + b.Navigation("PdfFiles"); + }); #pragma warning restore 612, 618 } } diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.csproj b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.csproj index 38f85e7541..f7a6f89231 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.csproj +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocs.EntityFrameworkCore.csproj @@ -13,6 +13,7 @@ + diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContext.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContext.cs index fb6aca4e19..08ca58dd72 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContext.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsDbContext.cs @@ -1,4 +1,5 @@ using Microsoft.EntityFrameworkCore; +using Volo.Abp.BlobStoring.Database.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.PermissionManagement.EntityFrameworkCore; @@ -23,6 +24,7 @@ namespace VoloDocs.EntityFrameworkCore modelBuilder.ConfigureSettingManagement(); modelBuilder.ConfigureIdentity(); modelBuilder.ConfigureDocs(); + modelBuilder.ConfigureBlobStoring(); } } } diff --git a/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsEntityFrameworkCoreModule.cs b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsEntityFrameworkCoreModule.cs index 44acea9a58..f94ec123bf 100644 --- a/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsEntityFrameworkCoreModule.cs +++ b/modules/docs/app/VoloDocs.EntityFrameworkCore/VoloDocsEntityFrameworkCoreModule.cs @@ -1,4 +1,5 @@ -using Volo.Abp.EntityFrameworkCore.SqlServer; +using Volo.Abp.BlobStoring.Database.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.SqlServer; using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement.EntityFrameworkCore; @@ -12,6 +13,7 @@ namespace VoloDocs.EntityFrameworkCore typeof(AbpIdentityEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), + typeof(BlobStoringDatabaseEntityFrameworkCoreModule), typeof(AbpEntityFrameworkCoreSqlServerModule))] public class VoloDocsEntityFrameworkCoreModule : AbpModule { diff --git a/modules/docs/app/VoloDocs.Migrator/appsettings.json b/modules/docs/app/VoloDocs.Migrator/appsettings.json index b554a47fed..9668adc1e2 100644 --- a/modules/docs/app/VoloDocs.Migrator/appsettings.json +++ b/modules/docs/app/VoloDocs.Migrator/appsettings.json @@ -1,3 +1,3 @@ { - "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;TrustServerCertificate=True" + "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;TrustServerCertificate=True", } \ No newline at end of file diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs index c335612ec4..512900e637 100644 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Options; using Volo.Docs; -using Volo.Docs.Projects; +using Volo.Docs.Common.Projects; namespace VoloDocs.Web.Pages { diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index 743944c6d3..5af8b1c129 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -32,10 +32,14 @@ using Localization.Resources.AbpUi; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Volo.Abp.Account; +using Volo.Abp.BlobStoring; +using Volo.Abp.BlobStoring.Database; using Volo.Abp.PermissionManagement.HttpApi; using Volo.Abp.Validation.Localization; using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Abp.Caching.StackExchangeRedis; +using Volo.Docs.Common.Documents; +using Volo.Docs.Projects.Pdf; namespace VoloDocs.Web { @@ -82,7 +86,7 @@ namespace VoloDocs.Web // options.SingleProjectMode.ProjectName = "abp"; // options.MultiLanguageMode = false; // }); - + Configure(options => { options.Enable = false; @@ -170,6 +174,22 @@ namespace VoloDocs.Web options.EnableGoogleProgrammableSearchEngine = true; options.GoogleSearchEngineId = "77c7266532da1427f"; }); + + Configure(options => + { + options.BaseUrl = configuration["App:SelfUrl"]; + options.IndexPagePath = "index.md"; + options.CalculatePdfFileTitle = project => project.ShortName == "abp" ? "ABP Documentation" : null; + options.DocumentContentNormalizer = content => content.Replace("", "No").Replace("", "Yes"); + }); + + Configure(options => + { + options.Containers.ConfigureDefault(container => + { + container.UseDatabase(); + }); + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) diff --git a/modules/docs/app/VoloDocs.Web/appsettings.json b/modules/docs/app/VoloDocs.Web/appsettings.json index 21a2883937..75d1b9890e 100644 --- a/modules/docs/app/VoloDocs.Web/appsettings.json +++ b/modules/docs/app/VoloDocs.Web/appsettings.json @@ -1,4 +1,7 @@ { + "App": { + "SelfUrl": "https://localhost:5001" + }, "Kestrel": { "EndPoints": { "Https": { diff --git a/modules/docs/app/VoloDocs.Web/package.json b/modules/docs/app/VoloDocs.Web/package.json index 14746df33a..e4a2f9b7ad 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.2.0-rc.1", - "@abp/docs": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4", + "@abp/docs": "~9.2.0-rc.4" } } diff --git a/modules/docs/app/VoloDocs.Web/yarn.lock b/modules/docs/app/VoloDocs.Web/yarn.lock index 2f406772a8..866cb958a5 100644 --- a/modules/docs/app/VoloDocs.Web/yarn.lock +++ b/modules/docs/app/VoloDocs.Web/yarn.lock @@ -2,229 +2,229 @@ # yarn lockfile v1 -"@abp/anchor-js@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/anchor-js/-/anchor-js-9.2.0-rc.1.tgz#bfc1f8045b85de351502fd5ec2d5711b74ca1c4a" - integrity sha512-ir3TyKMlFqJGPOKei+z251z/HzXxJVa3i2t26ll27+lbgM/+wfE1B5F6ys8zJSqAu/xjyo1nwGJdQoYEC4+IVg== +"@abp/anchor-js@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/anchor-js/-/anchor-js-9.2.0-rc.4.tgz#eba5e85a5ec3227e0c00a2f79974043ee84c0acd" + integrity sha512-GCO0WYUdVQiuX6efr3WdxqwYrtP6rcymcIurFSa1qqV2X4qIqlM4yzO6Q36JrEMeU8qOW7w3OuUvQkAOZC/j+g== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" anchor-js "^5.0.0" -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== - dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== - dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== + dependencies: + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== + dependencies: + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/clipboard@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.1.tgz#50069847848714fb155d35b656563f26f2fd870c" - integrity sha512-3lEUrQNje436F8t4nhTrIrFru1A1ZGJHgsYaXR6At50hNwWHcE1LtZKJnXm4am0dALJK/uwv4p7BfNT9Edo11A== +"@abp/clipboard@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/clipboard/-/clipboard-9.2.0-rc.4.tgz#e91e8c9b9947cef648e31f17ac8050d342a88416" + integrity sha512-iUvCQK3YJKPflLWkXNsueXit+Ipez5+R5q4OdngcvTmVXIUoH8t+3iiM+Q7ohA0vRknsdEGPMUUS7TnDW9fVqA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" clipboard "^2.0.11" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/docs@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/docs/-/docs-9.2.0-rc.1.tgz#040e3cd8b4c3979b082eadfdceb1f82091bd3f7b" - integrity sha512-ZtVlEH7Ze4MTYhk1YI4ddZ18kr6+Zc7s4bJXEoS5eHrBuljozmo4P0hypFmkvYkVz3KGMrK771t3nIQMB3PE/w== +"@abp/docs@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/docs/-/docs-9.2.0-rc.4.tgz#54196f7225245006fa56f3f4d1c20b5e90fa2525" + integrity sha512-rYpTDOoa7ruI7+bUFlfX+4W6NPCSiKqRMMRFvTkWqR5Y/DsbjElOJdHPQ0S8sfNIuXpG+RMuR5/KMlzbX0iLbA== dependencies: - "@abp/anchor-js" "~9.2.0-rc.1" - "@abp/clipboard" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/popper.js" "~9.2.0-rc.1" - "@abp/prismjs" "~9.2.0-rc.1" + "@abp/anchor-js" "~9.2.0-rc.4" + "@abp/clipboard" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/popper.js" "~9.2.0-rc.4" + "@abp/prismjs" "~9.2.0-rc.4" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/popper.js@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/popper.js/-/popper.js-9.2.0-rc.1.tgz#cf506a8a1987407ce3973d4523690ec023e1f9dd" - integrity sha512-d8EoIO9HrhhLHRXAAFt03BTjBSdoSwDVf9iOQJuA/a7Vz7EnkW7Fwge3T8pxL8VYZF0Hc3gdr991hkhZG8kufQ== +"@abp/popper.js@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/popper.js/-/popper.js-9.2.0-rc.4.tgz#25812c2f8033e667f03c580e1c8e2649ebb8da44" + integrity sha512-ASjq3wwY5Klkr/3iX7O9oW7cyxGE8I+IXU24uR3L2jpxMdh4knCZAU9333XQHdlVIn5Yvi5a5SZZgV5zOGJxMA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@popperjs/core" "^2.11.8" -"@abp/prismjs@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.1.tgz#623659c50c776bc8efcb7eacea70b2704ff87eec" - integrity sha512-QZ6NY4TXmWzrrZViN8v3CgH2l4fQUpEZLPsUaEmiRtq3+3meCaM3hxgNEOvcUg5IHZI7cPBRabQtVKoAPozcvQ== +"@abp/prismjs@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/prismjs/-/prismjs-9.2.0-rc.4.tgz#5164e64fa04d2a852043e1f7d02952d54112748a" + integrity sha512-fUCqWhmmRMu5DgpDxyH7uyEHS6lCFk+BY+JuS22sTvyhu+Q9M4rYhFEl/E9S+cA2rfxSNAG5h7HPXUWTqHPLgg== dependencies: - "@abp/clipboard" "~9.2.0-rc.1" - "@abp/core" "~9.2.0-rc.1" + "@abp/clipboard" "~9.2.0-rc.4" + "@abp/core" "~9.2.0-rc.4" prismjs "^1.29.0" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== dependencies: just-compare "^2.3.0" diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj index a49d9146db..796a4a83c4 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo.Docs.Admin.Application.Contracts.csproj @@ -18,6 +18,7 @@ + diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminApplicationContractsModule.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminApplicationContractsModule.cs index 0962a28aef..1e20041974 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminApplicationContractsModule.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminApplicationContractsModule.cs @@ -4,6 +4,7 @@ using Volo.Abp.Authorization.Permissions; using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; +using Volo.Docs.Common; using Volo.Docs.Localization; namespace Volo.Docs.Admin @@ -11,7 +12,8 @@ namespace Volo.Docs.Admin [DependsOn( typeof(DocsDomainSharedModule), typeof(AbpDddApplicationContractsModule), - typeof(AbpAuthorizationAbstractionsModule) + typeof(AbpAuthorizationAbstractionsModule), + typeof(DocsCommonApplicationContractsModule) )] public class DocsAdminApplicationContractsModule : AbpModule { diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs index 6f9bb6407e..0ce42e3143 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissionDefinitionProvider.cs @@ -14,6 +14,7 @@ namespace Volo.Docs.Admin projects.AddChild(DocsAdminPermissions.Projects.Update, L("Permission:Edit")); projects.AddChild(DocsAdminPermissions.Projects.Delete, L("Permission:Delete")); projects.AddChild(DocsAdminPermissions.Projects.Create, L("Permission:Create")); + projects.AddChild(DocsAdminPermissions.Projects.ManagePdfFiles, L("Permission:ManagePdfFiles")); group.AddPermission(DocsAdminPermissions.Documents.Default, L("Permission:Documents")); } diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs index e6043241ea..f5d9a94410 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/DocsAdminPermissions.cs @@ -12,6 +12,7 @@ namespace Volo.Docs.Admin public const string Delete = Default + ".Delete"; public const string Update = Default + ".Update"; public const string Create = Default + ".Create"; + public const string ManagePdfFiles = Default + ".ManagePdfFiles"; } public static class Documents diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ar.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ar.json index 458d1592f0..bd93067140 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ar.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ar.json @@ -57,6 +57,15 @@ "LastCachedTime": "وقت ذاكرة التخزين", "Project": "مشروع ", "AdvancedFilters": "مرشحات متقدمة", - "RemoveCacheAndReIndexConfirmation": "ستتم إزالة المستند \"{0}\" من ذاكرة التخزين المؤقت وإعادة فهرسته. هل تؤكد؟" + "RemoveCacheAndReIndexConfirmation": "ستتم إزالة المستند \"{0}\" من ذاكرة التخزين المؤقت وإعادة فهرسته. هل تؤكد؟", + "GeneratePdf": "توليد PDF", + "Generating": "يتم توليد...", + "Language": "اللغة", + "ForceToGenerateNewPdf": "قوة لتوليد PDF جديد", + "PdfGeneratedSuccessfully": "تم توليد PDF بنجاح", + "GenerateAndDownloadPdf": "توليد وتحميل PDF", + "PdfFileDeletionWarningMessage": "هل أنت متأكد أنك تريد حذف ملف PDF \"{0}\"?", + "ManagePdfFiles": "إدارة ملفات PDF", + "Permission:ManagePdfFiles": "إدارة ملفات PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/cs.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/cs.json index ff6c135a90..9543166ac4 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/cs.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/cs.json @@ -57,6 +57,15 @@ "LastCachedTime": "Čas uložení v mezipaměti", "Project": "Projekt", "AdvancedFilters": "Pokročilé filtry", - "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" bude odstraněn z mezipaměti a znovu zaindexován. Potvrzujete to?" + "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" bude odstraněn z mezipaměti a znovu zaindexován. Potvrzujete to?", + "GeneratePdf": "Generovat PDF", + "Generating": "Generování...", + "Language": "Jazyk", + "ForceToGenerateNewPdf": "Vynutit generování nového PDF", + "PdfGeneratedSuccessfully": "PDF generován úspěšně", + "GenerateAndDownloadPdf": "Generovat a stáhnout PDF", + "PdfFileDeletionWarningMessage": "Opravdu chcete odstranit soubor PDF \"{0}\"?", + "ManagePdfFiles": "Správa PDF souborů", + "Permission:ManagePdfFiles": "Správa PDF souborů" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de-DE.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de-DE.json index ce7c8cafb0..a69c9283ea 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de-DE.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de-DE.json @@ -56,6 +56,15 @@ "FileName": "Dateiname", "LastCachedTime": "Cache-Zeit", "Project": "Projekt", - "RemoveCacheAndReIndexConfirmation": "Das Dokument \"{0}\" wird aus dem Cache entfernt und neu indiziert. Können Sie das bestätigen?" + "RemoveCacheAndReIndexConfirmation": "Das Dokument \"{0}\" wird aus dem Cache entfernt und neu indiziert. Können Sie das bestätigen?", + "GeneratePdf": "PDF generieren", + "Generating": "Generieren...", + "Language": "Sprache", + "ForceToGenerateNewPdf": "Neues PDF erzwingen", + "PdfGeneratedSuccessfully": "PDF erfolgreich generiert", + "GenerateAndDownloadPdf": "PDF generieren und herunterladen", + "PdfFileDeletionWarningMessage": "Sind Sie sicher, dass Sie das PDF-Datei \"{0}\" löschen wollen?", + "ManagePdfFiles": "PDF-Dateien verwalten", + "Permission:ManagePdfFiles": "PDF-Dateien verwalten" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de.json index 0fd1c535b2..1278047f50 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/de.json @@ -57,6 +57,15 @@ "LastCachedTime": "Zwischenspeicher", "Project": "Projekt", "AdvancedFilters": "Erweiterte Filter", - "RemoveCacheAndReIndexConfirmation": "Das Dokument „{0}“ wird aus dem Cache entfernt und neu indiziert. Bestätigen Sie?" + "RemoveCacheAndReIndexConfirmation": "Das Dokument „{0}“ wird aus dem Cache entfernt und neu indiziert. Bestätigen Sie?", + "GeneratePdf": "PDF generieren", + "Generating": "Generieren...", + "Language": "Sprache", + "ForceToGenerateNewPdf": "Neues PDF erzwingen", + "PdfGeneratedSuccessfully": "PDF erfolgreich generiert", + "GenerateAndDownloadPdf": "PDF generieren und herunterladen", + "PdfFileDeletionWarningMessage": "Sind Sie sicher, dass Sie das PDF-Datei \"{0}\" löschen wollen?", + "ManagePdfFiles": "PDF-Dateien verwalten", + "Permission:ManagePdfFiles": "PDF-Dateien verwalten" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/el.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/el.json index c2a3f69a53..ae8108dfb5 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/el.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/el.json @@ -56,6 +56,15 @@ "FileName": "Όνομα αρχείου", "LastCachedTime": "Χρόνος προσωρινής αποθήκευσης", "Project": "Εργο", - "RemoveCacheAndReIndexConfirmation": "Το έγγραφο \"{0}\" θα αφαιρεθεί από την προσωρινή μνήμη και θα αναπροσαρμοστεί εκ νέου. Επιβεβαιώνετε;" + "RemoveCacheAndReIndexConfirmation": "Το έγγραφο \"{0}\" θα αφαιρεθεί από την προσωρινή μνήμη και θα αναπροσαρμοστεί εκ νέου. Επιβεβαιώνετε;", + "GeneratePdf": "Δημιουργία PDF", + "Generating": "Δημιουργία...", + "Language": "Γλώσσα", + "ForceToGenerateNewPdf": "Βάλτε το νέο PDF", + "PdfGeneratedSuccessfully": "Το PDF αναπροσαρμοστεί εκ νέου", + "GenerateAndDownloadPdf": "Δημιουργία και λήψη PDF", + "PdfFileDeletionWarningMessage": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το PDF αρχείο \"{0}\";", + "ManagePdfFiles": "Διαχείρηση PDF αρχείων", + "Permission:ManagePdfFiles": "Διαχείρηση PDF αρχείων" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en-GB.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en-GB.json index d72c523ef5..6ed2bb94cd 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en-GB.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en-GB.json @@ -56,6 +56,15 @@ "FileName": "File name", "LastCachedTime": "Cache time", "Project": "Project", - "AdvancedFilters": "Advanced Filters" + "AdvancedFilters": "Advanced Filters", + "GeneratePdf": "Generate PDF", + "Generating": "Generating...", + "Language": "Language", + "ForceToGenerateNewPdf": "Force to generate new PDF", + "PdfGeneratedSuccessfully": "PDF generated successfully", + "GenerateAndDownloadPdf": "Generate and download PDF", + "PdfFileDeletionWarningMessage": "Are you sure you want to delete the PDF file \"{0}\"?", + "ManagePdfFiles": "Manage PDF files", + "Permission:ManagePdfFiles": "Manage PDF files" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json index 5302cdcffb..bc606f7df7 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json @@ -57,6 +57,15 @@ "LastCachedTime": "Cache time", "Project": "Project", "AdvancedFilters": "Advanced Filters", - "RemoveCacheAndReIndexConfirmation": "The document \"{0}\" will be removed from the cache and re-indexed. Do you confirm?" + "RemoveCacheAndReIndexConfirmation": "The document \"{0}\" will be removed from the cache and re-indexed. Do you confirm?", + "GeneratePdf": "Generate PDF", + "Generating": "Generating...", + "Language": "Language", + "ForceToGenerateNewPdf": "Force to generate new PDF", + "PdfGeneratedSuccessfully": "PDF generated successfully", + "GenerateAndDownloadPdf": "Generate and download PDF", + "PdfFileDeletionWarningMessage": "Are you sure you want to delete the PDF file \"{0}\"?", + "ManagePdfFiles": "Manage PDF files", + "Permission:ManagePdfFiles": "Manage PDF files" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/es.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/es.json index 911fe2745a..79937b772d 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/es.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/es.json @@ -57,6 +57,15 @@ "LastCachedTime": "Última actualización de caché", "Project": "Proyecto", "AdvancedFilters": "Filtros avanzados", - "RemoveCacheAndReIndexConfirmation": "El documento \"{0}\" será eliminado de la caché y reindexado. ¿Lo confirma?" + "RemoveCacheAndReIndexConfirmation": "El documento \"{0}\" será eliminado de la caché y reindexado. ¿Lo confirma?", + "GeneratePdf": "Generar PDF", + "Generating": "Generando...", + "Language": "Idioma", + "ForceToGenerateNewPdf": "Forzar a generar un nuevo PDF", + "PdfGeneratedSuccessfully": "PDF generado correctamente", + "GenerateAndDownloadPdf": "Generar y descargar PDF", + "PdfFileDeletionWarningMessage": "¿Está seguro de querer eliminar el archivo PDF \"{0}\"?", + "ManagePdfFiles": "Administrar archivos PDF", + "Permission:ManagePdfFiles": "Administrar archivos PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fi.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fi.json index e3e826c1b7..d227037f32 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fi.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fi.json @@ -57,6 +57,15 @@ "LastCachedTime": "Välimuistin aika", "Project": "Projekti", "AdvancedFilters": "Edistyneet suodattimet", - "RemoveCacheAndReIndexConfirmation": "Dokumentti \"{0}\" poistetaan välimuistista ja indeksoidaan uudelleen. Vahvistatko?" + "RemoveCacheAndReIndexConfirmation": "Dokumentti \"{0}\" poistetaan välimuistista ja indeksoidaan uudelleen. Vahvistatko?", + "GeneratePdf": "Generoi PDF", + "Generating": "Generoiminen...", + "Language": "Kieli", + "ForceToGenerateNewPdf": "Vahvista uusi PDF", + "PdfGeneratedSuccessfully": "PDF generoidaan onnistuneesti", + "GenerateAndDownloadPdf": "Generoi ja lataa PDF", + "PdfFileDeletionWarningMessage": "Oletko varma, että haluat poistaa PDF-tiedoston \"{0}\"?", + "ManagePdfFiles": "Hallitse PDF-tiedostoja", + "Permission:ManagePdfFiles": "Hallitse PDF-tiedostoja" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fr.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fr.json index b2fdef8201..6efe4fe888 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fr.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/fr.json @@ -57,6 +57,15 @@ "LastCachedTime": "Temps de cache", "Project": "Projet", "AdvancedFilters": "Filtres avancés", - "RemoveCacheAndReIndexConfirmation": "Le document \"{0}\" sera supprimé du cache et réindexé. Confirmez-vous ?" + "RemoveCacheAndReIndexConfirmation": "Le document \"{0}\" sera supprimé du cache et réindexé. Confirmez-vous ?", + "GeneratePdf": "Générer PDF", + "Generating": "Génération...", + "Language": "Langue", + "ForceToGenerateNewPdf": "Forcer à générer un nouveau PDF", + "PdfGeneratedSuccessfully": "PDF généré avec succès", + "GenerateAndDownloadPdf": "Générer et télécharger PDF", + "PdfFileDeletionWarningMessage": "Êtes-vous sûr de vouloir supprimer le fichier PDF \"{0}\"?", + "ManagePdfFiles": "Gérer les fichiers PDF", + "Permission:ManagePdfFiles": "Gérer les fichiers PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hi.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hi.json index adad5e064f..cdca790f20 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hi.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hi.json @@ -57,6 +57,15 @@ "LastCachedTime": "कैश समय", "Project": "परियोजना", "AdvancedFilters": "उन्नत फ़िल्टर", - "RemoveCacheAndReIndexConfirmation": "दस्u200Dतावेज़ \"{0}\" को संचय से हटा दिया जाएगा और पुन: अनुक्रमित किया जाएगा। क्या आप पुष्टि करते हैं?" + "RemoveCacheAndReIndexConfirmation": "दस्तावेज़ \"{0}\" को संचय से हटा दिया जाएगा और पुन: अनुक्रमित किया जाएगा। क्या आप पुष्टि करते हैं?", + "GeneratePdf": "PDF उत्पन्न करें", + "Generating": "उत्पन्न कर रहा है...", + "Language": "भाषा", + "ForceToGenerateNewPdf": "नया PDF उत्पन्न करें", + "PdfGeneratedSuccessfully": "PDF सफलतापूर्वक उत्पन्न हो गया", + "GenerateAndDownloadPdf": "PDF उत्पन्न और डाउनलोड करें", + "PdfFileDeletionWarningMessage": "क्या आप वाकई \"{0}\" के PDF फ़ाइल को हटाना चाहते हैं?", + "ManagePdfFiles": "PDF फ़ाइलें प्रबंधित करें", + "Permission:ManagePdfFiles": "PDF फ़ाइलें प्रबंधित करें" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hr.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hr.json index cf0a31368f..547484a062 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hr.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hr.json @@ -57,6 +57,15 @@ "LastCachedTime": "Vrijeme predmemorije", "Project": "Projekt", "AdvancedFilters": "Napredni filtri", - "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" bit će uklonjen iz predmemorije i ponovno indeksiran. Potvrđujete li?" + "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" bit će uklonjen iz predmemorije i ponovno indeksiran. Potvrđujete li?", + "GeneratePdf": "Generiraj PDF", + "Generating": "Generiranje...", + "Language": "Jezik", + "ForceToGenerateNewPdf": "Prisili generiranje novog PDF-a", + "PdfGeneratedSuccessfully": "PDF generiran uspješno", + "GenerateAndDownloadPdf": "Generiraj i preuzmi PDF", + "PdfFileDeletionWarningMessage": "Jeste li sigurni da želite izbrisati PDF datoteku \"{0}\"?", + "ManagePdfFiles": "Upravljanje PDF datotekama", + "Permission:ManagePdfFiles": "Upravljanje PDF datotekama" } } diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hu.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hu.json index 587f67e72c..581910f9e9 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hu.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hu.json @@ -58,6 +58,15 @@ "LastCachedTime": "Cache idő", "Project": "Projekt", "AdvancedFilters": "Speciális szűrők", - "RemoveCacheAndReIndexConfirmation": "A \"{0}\" dokumentumot eltávolítjuk a gyorsítótárból és újraindexeljük. Megerősíti?" + "RemoveCacheAndReIndexConfirmation": "A \"{0}\" dokumentumot eltávolítjuk a gyorsítótárból és újraindexeljük. Megerősíti?", + "GeneratePdf": "PDF generálása", + "Generating": "Generálás...", + "Language": "Nyelv", + "ForceToGenerateNewPdf": "Új PDF generálása", + "PdfGeneratedSuccessfully": "PDF generálás sikeres", + "GenerateAndDownloadPdf": "Generálás és letöltés PDF-ben", + "PdfFileDeletionWarningMessage": "Biztosan törölni szeretné a \"{0}\" PDF fájlt?", + "ManagePdfFiles": "PDF fájlok kezelése", + "Permission:ManagePdfFiles": "PDF fájlok kezelése" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/is.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/is.json index c3e8fa957b..64b41ce3b7 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/is.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/is.json @@ -57,6 +57,15 @@ "LastCachedTime": "Tími geymt í skyndiminni", "Project": "Verkefni", "AdvancedFilters": "Ítarlegar síur", - "RemoveCacheAndReIndexConfirmation": "Skjalið \"{0}\" verður fjarlægt úr skyndiminni og endurtryggt. Staðfestir þú?" + "RemoveCacheAndReIndexConfirmation": "Skjalið \"{0}\" verður fjarlægt úr skyndiminni og endurtryggt. Staðfestir þú?", + "GeneratePdf": "Generate PDF", + "Generating": "Generating...", + "Language": "Language", + "ForceToGenerateNewPdf": "Force to generate new PDF", + "PdfGeneratedSuccessfully": "PDF generated successfully", + "GenerateAndDownloadPdf": "Generate and download PDF", + "PdfFileDeletionWarningMessage": "Are you sure you want to delete the PDF file \"{0}\"?", + "ManagePdfFiles": "Manage PDF files", + "Permission:ManagePdfFiles": "Manage PDF files" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/it.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/it.json index 40f94e8077..29e7d1ba80 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/it.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/it.json @@ -57,6 +57,15 @@ "LastCachedTime": "Tempo di cache", "Project": "Progetto", "AdvancedFilters": "Filtri avanzati", - "RemoveCacheAndReIndexConfirmation": "Il documento \"{0}\" verrà rimosso dalla cache e reindicizzato. Confermate?" + "RemoveCacheAndReIndexConfirmation": "Il documento \"{0}\" verrà rimosso dalla cache e reindicizzato. Confermate?", + "GeneratePdf": "Genera PDF", + "Generating": "Generazione...", + "Language": "Lingua", + "ForceToGenerateNewPdf": "Forza a generare un nuovo PDF", + "PdfGeneratedSuccessfully": "PDF generato con successo", + "GenerateAndDownloadPdf": "Genera e scarica PDF", + "PdfFileDeletionWarningMessage": "Sei sicuro di voler eliminare il file PDF \"{0}\"?", + "ManagePdfFiles": "Gestione file PDF", + "Permission:ManagePdfFiles": "Gestione file PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/nl.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/nl.json index 201d7c5da0..6f43a26ac8 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/nl.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/nl.json @@ -57,6 +57,15 @@ "LastCachedTime": "Cache tijd", "Project": "Project", "AdvancedFilters": "Geavanceerde filters", - "RemoveCacheAndReIndexConfirmation": "Het document \"{0}\" wordt uit de cache verwijderd en opnieuw geïndexeerd. Bevestigt u?" + "RemoveCacheAndReIndexConfirmation": "Het document \"{0}\" wordt uit de cache verwijderd en opnieuw geïndexeerd. Bevestigt u?", + "GeneratePdf": "PDF genereren", + "Generating": "Genereren...", + "Language": "Taal", + "ForceToGenerateNewPdf": "Forceer nieuwe PDF te genereren", + "PdfGeneratedSuccessfully": "PDF succesvol gegenereerd", + "GenerateAndDownloadPdf": "PDF genereren en downloaden", + "PdfFileDeletionWarningMessage": "Weet u zeker dat u het PDF-bestand \"{0}\" wilt verwijderen?", + "ManagePdfFiles": "PDF-bestanden beheren", + "Permission:ManagePdfFiles": "PDF-bestanden beheren" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl-PL.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl-PL.json index ec9de0de07..a93ee2bd0f 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl-PL.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pl-PL.json @@ -57,6 +57,15 @@ "LastCachedTime": "Czas w pamięci podręcznej", "Project": "Projekt", "AdvancedFilters": "Zaawansowane filtry", - "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" zostanie usunięty z pamięci podręcznej i ponownie zaindeksowany. Czy potwierdzasz?" + "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" zostanie usunięty z pamięci podręcznej i ponownie zaindeksowany. Czy potwierdzasz?", + "GeneratePdf": "Generuj PDF", + "Generating": "Generowanie...", + "Language": "Język", + "ForceToGenerateNewPdf": "Wymuś generowanie nowego PDF", + "PdfGeneratedSuccessfully": "PDF został pomyślnie wygenerowany", + "GenerateAndDownloadPdf": "Generuj i pobierz PDF", + "PdfFileDeletionWarningMessage": "Czy na pewno chcesz usunąć plik PDF \"{0}\"?", + "ManagePdfFiles": "Zarządzanie plikami PDF", + "Permission:ManagePdfFiles": "Zarządzanie plikami PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json index b34ab4b9ef..ff8be45830 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/pt-BR.json @@ -57,6 +57,15 @@ "LastCachedTime": "Tempo de cache", "Project": "Projeto", "AdvancedFilters": "Filtros Avançados", - "RemoveCacheAndReIndexConfirmation": "O documento \"{0}\" será removido do cache e indexado novamente. Você confirma?" + "RemoveCacheAndReIndexConfirmation": "O documento \"{0}\" será removido do cache e indexado novamente. Você confirma?", + "GeneratePdf": "Gerar PDF", + "Generating": "Gerando...", + "Language": "Idioma", + "ForceToGenerateNewPdf": "Forçar para gerar um novo PDF", + "PdfGeneratedSuccessfully": "PDF gerado com sucesso", + "GenerateAndDownloadPdf": "Gerar e baixar PDF", + "PdfFileDeletionWarningMessage": "Tem certeza de que deseja excluir o arquivo PDF \"{0}\"?", + "ManagePdfFiles": "Gerenciar arquivos PDF", + "Permission:ManagePdfFiles": "Gerenciar arquivos PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ro-RO.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ro-RO.json index f055110a2f..68f40183d8 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ro-RO.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ro-RO.json @@ -57,6 +57,15 @@ "LastCachedTime": "Durată cache", "Project": "Proiect", "AdvancedFilters": "Filtre avansate", - "RemoveCacheAndReIndexConfirmation": "Documentul \"{0}\" va fi eliminat din memoria cache și va fi reindexat. Confirmați?" + "RemoveCacheAndReIndexConfirmation": "Documentul \"{0}\" va fi eliminat din memoria cache și va fi reindexat. Confirmați?", + "GeneratePdf": "Generare PDF", + "Generating": "Generare...", + "Language": "Limba", + "ForceToGenerateNewPdf": "Forțați generarea unui nou PDF", + "PdfGeneratedSuccessfully": "PDF generat cu succes", + "GenerateAndDownloadPdf": "Generare și descărcare PDF", + "PdfFileDeletionWarningMessage": "Sunteți sigur(ă) că doriți să ștergeți fișierul PDF \"{0}\"?", + "ManagePdfFiles": "Gestionare fișiere PDF", + "Permission:ManagePdfFiles": "Gestionare fișiere PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ru.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ru.json index 5f9836d957..bc2691121d 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ru.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ru.json @@ -57,6 +57,15 @@ "LastCachedTime": "Время кеширования", "Project": "Проект", "AdvancedFilters": "Расширенные фильтры", - "RemoveCacheAndReIndexConfirmation": "Документ \"{0}\" будет удален из кэша и переиндексирован. Вы подтверждаете?" + "RemoveCacheAndReIndexConfirmation": "Документ \"{0}\" будет удален из кэша и переиндексирован. Вы подтверждаете?", + "GeneratePdf": "Генерировать PDF", + "Generating": "Генерация...", + "Language": "Язык", + "ForceToGenerateNewPdf": "Принудительное создание нового PDF", + "PdfGeneratedSuccessfully": "PDF успешно сгенерирован", + "GenerateAndDownloadPdf": "Сгенерировать и скачать PDF", + "PdfFileDeletionWarningMessage": "Вы уверены, что хотите удалить файл PDF \"{0}\"?", + "ManagePdfFiles": "Управление файлами PDF", + "Permission:ManagePdfFiles": "Управление файлами PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sk.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sk.json index 53578e22dd..8b06da0e82 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sk.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sk.json @@ -57,6 +57,15 @@ "LastCachedTime": "Čas vyrovnávacej pamäte", "Project": "Projekt", "AdvancedFilters": "Pokročilé filtre", - "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" sa odstráni z vyrovnávacej pamäte a znovu sa zaindexuje. Potvrdzujete?" + "RemoveCacheAndReIndexConfirmation": "Dokument \"{0}\" sa odstráni z vyrovnávacej pamäte a znovu sa zaindexuje. Potvrdzujete?", + "GeneratePdf": "Generovať PDF", + "Generating": "Generovanie...", + "Language": "Jazyk", + "ForceToGenerateNewPdf": "Vynútiť generovanie nového PDF", + "PdfGeneratedSuccessfully": "PDF generovaný úspešne", + "GenerateAndDownloadPdf": "Generovať a stiahnuť PDF", + "PdfFileDeletionWarningMessage": "Ste si istý, že chcete odstrániť súbor PDF \"{0}\"?", + "ManagePdfFiles": "Správa PDF súborov", + "Permission:ManagePdfFiles": "Správa PDF súborov" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sl.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sl.json index 3bcfcd4e85..0fe64f8903 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sl.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sl.json @@ -57,6 +57,15 @@ "LastCachedTime": "Čas pred pomnilnika", "Project": "Projekt", "AdvancedFilters": "Napredni filtri", - "RemoveCacheAndReIndexConfirmation": "Dokument »{0}« bo odstranjen iz predpomnilnika in ponovno indeksiran. Ali potrjuješ?" + "RemoveCacheAndReIndexConfirmation": "Dokument »{0}« bo odstranjen iz predpomnilnika in ponovno indeksiran. Ali potrjuješ?", + "GeneratePdf": "Generiraj PDF", + "Generating": "Generiranje...", + "Language": "Jezik", + "ForceToGenerateNewPdf": "Prisili generiranje novega PDF", + "PdfGeneratedSuccessfully": "PDF generiran uspešno", + "GenerateAndDownloadPdf": "Generiraj in prenesi PDF", + "PdfFileDeletionWarningMessage": "Ali ste prepričani, da želite izbrisati datoteko PDF »{0}«?", + "ManagePdfFiles": "Upravljanje datotek PDF", + "Permission:ManagePdfFiles": "Upravljanje datotek PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sv.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sv.json index cbde97c756..db67ecb79b 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sv.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/sv.json @@ -57,6 +57,15 @@ "LastCachedTime": "Cache-tid", "Project": "Projekt", "AdvancedFilters": "Avancerade filter", - "RemoveCacheAndReIndexConfirmation": "Dokumentet \"{0}\" kommer att tas bort från cacheminnet och indexeras på nytt. Kan du bekräfta detta?" + "RemoveCacheAndReIndexConfirmation": "Dokumentet \"{0}\" kommer att tas bort från cacheminnet och indexeras på nytt. Kan du bekräfta detta?", + "GeneratePdf": "Generera PDF", + "Generating": "Genererar...", + "Language": "Språk", + "ForceToGenerateNewPdf": "Force to generate new PDF", + "PdfGeneratedSuccessfully": "PDF generated successfully", + "GenerateAndDownloadPdf": "Generate and download PDF", + "PdfFileDeletionWarningMessage": "Are you sure you want to delete the PDF file \"{0}\"?", + "ManagePdfFiles": "Manage PDF files", + "Permission:ManagePdfFiles": "Manage PDF files" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json index ab600c1db5..42283a4b89 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/tr.json @@ -57,6 +57,15 @@ "LastCachedTime": "Önbellek süresi", "Project": "Proje", "AdvancedFilters": "Gelişmiş Filtre", - "RemoveCacheAndReIndexConfirmation": "\"{0}\" belgesi önbellekten kaldırılacak ve yeniden indekslenecektir. Onaylıyor musunuz?" + "RemoveCacheAndReIndexConfirmation": "\"{0}\" belgesi önbellekten kaldırılacak ve yeniden indekslenecektir. Onaylıyor musunuz?", + "GeneratePdf": "PDF oluştur", + "Generating": "Oluşturuluyor...", + "Language": "Dil", + "ForceToGenerateNewPdf": "Yeni bir PDF oluştur", + "PdfGeneratedSuccessfully": "PDF başarıyla oluşturuldu", + "GenerateAndDownloadPdf": "PDF oluştur ve indir", + "PdfFileDeletionWarningMessage": "{0} PDF dosyasını silmek istediğinizden emin misiniz?", + "ManagePdfFiles": "PDF dosyalarını yönet", + "Permission:ManagePdfFiles": "PDF dosyalarını yönet" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.json index 9b47a049a9..176b427e59 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/vi.json @@ -57,6 +57,15 @@ "LastCachedTime": "Thời gian lưu vào bộ nhớ đệm", "Project": "Dự án", "AdvancedFilters": "Bộ lọc nâng cao", - "RemoveCacheAndReIndexConfirmation": "Tài liệu "{0}" sẽ bị xóa khỏi bộ đệm và được lập chỉ mục lại. Bạn có xác nhận không?" + "RemoveCacheAndReIndexConfirmation": "Tài liệu "{0}" sẽ bị xóa khỏi bộ đệm và được lập chỉ mục lại. Bạn có xác nhận không?", + "GeneratePdf": "Tạo PDF", + "Generating": "Đang tạo...", + "Language": "Ngôn ngữ", + "ForceToGenerateNewPdf": "Tạo PDF mới", + "PdfGeneratedSuccessfully": "PDF đã được tạo thành công", + "GenerateAndDownloadPdf": "Tạo và tải xuống PDF", + "PdfFileDeletionWarningMessage": "Bạn có chắc chắn muốn xóa tệp PDF \"{0}\" không?", + "ManagePdfFiles": "Quản lý tệp PDF", + "Permission:ManagePdfFiles": "Quản lý tệp PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hans.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hans.json index e5bb9f15b6..137e42e4ae 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hans.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hans.json @@ -57,6 +57,15 @@ "LastCachedTime": "缓存项", "Project": "项目", "AdvancedFilters": "高级过滤器", - "RemoveCacheAndReIndexConfirmation": "文档“{0}”将从缓存中删除并重新编制索引。 你确认吗?" + "RemoveCacheAndReIndexConfirmation": "文档“{0}”将从缓存中删除并重新编制索引。 你确认吗?", + "GeneratePdf": "生成PDF", + "Generating": "生成中...", + "Language": "语言", + "ForceToGenerateNewPdf": "强制生成新PDF", + "PdfGeneratedSuccessfully": "PDF生成成功", + "GenerateAndDownloadPdf": "生成并下载PDF", + "PdfFileDeletionWarningMessage": "你确定要删除PDF文件“{0}”吗?", + "ManagePdfFiles": "管理PDF文件", + "Permission:ManagePdfFiles": "管理PDF文件" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hant.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hant.json index c246a74646..bfa6e4ea97 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hant.json +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/zh-Hant.json @@ -55,8 +55,17 @@ "LanguageCode": "語言代碼", "FileName": "文檔名稱", "LastCachedTime": "緩存時間", - "Project": "项目", + "Project": "專案", "AdvancedFilters": "進階過濾器", - "RemoveCacheAndReIndexConfirmation": "文檔“{0}”將從緩存中刪除並重新編制索引。 你確認嗎?" + "RemoveCacheAndReIndexConfirmation": "文檔“{0}”將從緩存中刪除並重新編制索引。 你確認嗎?", + "GeneratePdf": "生成PDF", + "Generating": "生成中...", + "Language": "語言", + "ForceToGenerateNewPdf": "强制生成新PDF", + "PdfGeneratedSuccessfully": "PDF生成成功", + "GenerateAndDownloadPdf": "生成并下载PDF", + "PdfFileDeletionWarningMessage": "你確定要刪除PDF文件“{0}”嗎?", + "ManagePdfFiles": "管理PDF文件", + "Permission:ManagePdfFiles": "管理PDF文件" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/DeletePdfFileInput.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/DeletePdfFileInput.cs new file mode 100644 index 0000000000..6e8e30e57c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/DeletePdfFileInput.cs @@ -0,0 +1,12 @@ +using System; + +namespace Volo.Docs.Admin.Projects; + +public class DeletePdfFileInput +{ + public Guid ProjectId { get; set; } + + public string Version { get; set; } + + public string LanguageCode { get; set; } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/GetPdfFilesInput.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/GetPdfFilesInput.cs new file mode 100644 index 0000000000..f8a371dd57 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/GetPdfFilesInput.cs @@ -0,0 +1,9 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Volo.Docs.Admin.Projects; + +public class GetPdfFilesInput : PagedAndSortedResultRequestDto +{ + public Guid ProjectId { get; set; } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs index 6f3d503f44..41b309f308 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/IProjectAdminAppService.cs @@ -22,5 +22,9 @@ namespace Volo.Docs.Admin.Projects Task ReindexAllAsync(); Task> GetListWithoutDetailsAsync(); + + Task> GetPdfFilesAsync(GetPdfFilesInput input); + + Task DeletePdfFileAsync(DeletePdfFileInput input); } } diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/ProjectPdfFileDto.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/ProjectPdfFileDto.cs new file mode 100644 index 0000000000..4f2d012475 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Projects/ProjectPdfFileDto.cs @@ -0,0 +1,14 @@ +using System; + +namespace Volo.Docs.Admin.Projects; + +[Serializable] +public class ProjectPdfFileDto +{ + public virtual Guid ProjectId { get; set; } + public virtual string FileName { get; set; } + public virtual string Version { get; set; } + public virtual string LanguageCode { get; set; } + public virtual DateTime CreationTime { get; set; } + public virtual DateTime? LastModificationTime { get; set; } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo.Docs.Admin.Application.csproj b/modules/docs/src/Volo.Docs.Admin.Application/Volo.Docs.Admin.Application.csproj index 3d947ead5e..7279eeee67 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo.Docs.Admin.Application.csproj +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo.Docs.Admin.Application.csproj @@ -12,6 +12,7 @@ + diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs index 01a7250ce5..366c0ab27b 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationAutoMapperProfile.cs @@ -16,6 +16,7 @@ namespace Volo.Docs.Admin CreateMap(); CreateMap(); CreateMap(); + CreateMap(); } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationModule.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationModule.cs index 0b78c53973..7e6983d65e 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationModule.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/DocsAdminApplicationModule.cs @@ -3,12 +3,14 @@ using Volo.Abp.Application; using Volo.Abp.AutoMapper; using Volo.Abp.Caching; using Volo.Abp.Modularity; +using Volo.Docs.Common; namespace Volo.Docs.Admin { [DependsOn( typeof(DocsDomainModule), typeof(DocsAdminApplicationContractsModule), + typeof(DocsCommonApplicationModule), typeof(AbpCachingModule), typeof(AbpAutoMapperModule), typeof(AbpDddApplicationModule) diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs index 3142b821d2..abbb26abe5 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Projects/ProjectAdminAppService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Options; using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Services; using Volo.Abp.Data; @@ -11,6 +12,7 @@ using Volo.Docs.Documents; using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.Localization; using Volo.Docs.Projects; +using Volo.Docs.Projects.Pdf; namespace Volo.Docs.Admin.Projects { @@ -21,12 +23,14 @@ namespace Volo.Docs.Admin.Projects private readonly IDocumentRepository _documentRepository; private readonly IDocumentFullSearch _elasticSearchService; private readonly IGuidGenerator _guidGenerator; + private readonly IProjectPdfFileStore _projectPdfFileStore; public ProjectAdminAppService( IProjectRepository projectRepository, IDocumentRepository documentRepository, IDocumentFullSearch elasticSearchService, - IGuidGenerator guidGenerator) + IGuidGenerator guidGenerator, + IProjectPdfFileStore projectPdfFileStore) { ObjectMapperContext = typeof(DocsAdminApplicationModule); LocalizationResource = typeof(DocsResource); @@ -35,6 +39,7 @@ namespace Volo.Docs.Admin.Projects _documentRepository = documentRepository; _elasticSearchService = elasticSearchService; _guidGenerator = guidGenerator; + _projectPdfFileStore = projectPdfFileStore; } public virtual async Task> GetListAsync(PagedAndSortedResultRequestDto input) @@ -176,5 +181,25 @@ namespace Volo.Docs.Admin.Projects var projects = await _projectRepository.GetListWithoutDetailsAsync(); return ObjectMapper.Map, List>(projects); } + + [Authorize(DocsAdminPermissions.Projects.ManagePdfFiles)] + public virtual async Task> GetPdfFilesAsync(GetPdfFilesInput input) + { + var project = await _projectRepository.GetAsync(input.ProjectId, includeDetails: true); + + var pdfFiles = project.PdfFiles.Skip(input.SkipCount).Take(input.MaxResultCount).ToList(); + + return new PagedResultDto( + project.PdfFiles.Count, + ObjectMapper.Map, List>(pdfFiles) + ); + } + + [Authorize(DocsAdminPermissions.Projects.ManagePdfFiles)] + public virtual async Task DeletePdfFileAsync(DeletePdfFileInput input) + { + var project = await _projectRepository.GetAsync(input.ProjectId, includeDetails: true); + await _projectPdfFileStore.DeleteAsync(project, input.Version, input.LanguageCode); + } } } diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/Volo/Docs/Admin/ProjectsAdminClientProxy.Generated.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/Volo/Docs/Admin/ProjectsAdminClientProxy.Generated.cs index 54f1ec22d5..9437ee487d 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/Volo/Docs/Admin/ProjectsAdminClientProxy.Generated.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/Volo/Docs/Admin/ProjectsAdminClientProxy.Generated.cs @@ -68,6 +68,22 @@ public partial class ProjectsAdminClientProxy : ClientProxyBase>(nameof(GetListWithoutDetailsAsync)); } + public virtual async Task> GetPdfFilesAsync(GetPdfFilesInput input) + { + return await RequestAsync>(nameof(GetPdfFilesAsync), new ClientProxyRequestTypeValue + { + { typeof(GetPdfFilesInput), input } + }); + } + + public virtual async Task DeletePdfFileAsync(DeletePdfFileInput input) + { + await RequestAsync(nameof(DeletePdfFileAsync), new ClientProxyRequestTypeValue + { + { typeof(DeletePdfFileInput), input } + }); + } + public virtual async Task ReindexAsync(ReindexInput input) { await RequestAsync(nameof(ReindexAsync), new ClientProxyRequestTypeValue diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/docs-admin-generate-proxy.json b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/docs-admin-generate-proxy.json new file mode 100644 index 0000000000..636c7b6d25 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi.Client/ClientProxies/docs-admin-generate-proxy.json @@ -0,0 +1,1199 @@ +{ + "modules": { + "docs-admin": { + "rootPath": "docs-admin", + "remoteServiceName": "AbpDocsAdmin", + "controllers": { + "Volo.Docs.Admin.DocumentsAdminController": { + "controllerName": "DocumentsAdmin", + "controllerGroupName": "DocumentsAdmin", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.Docs.Admin.DocumentsAdminController", + "interfaces": [ + { + "type": "Volo.Docs.Admin.Documents.IDocumentAdminAppService", + "name": "IDocumentAdminAppService", + "methods": [ + { + "name": "ClearCacheAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.ClearCacheInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.ClearCacheInput", + "typeSimple": "Volo.Docs.Admin.Documents.ClearCacheInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "PullAllAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.PullAllDocumentInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.PullAllDocumentInput", + "typeSimple": "Volo.Docs.Admin.Documents.PullAllDocumentInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "PullAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.PullDocumentInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.PullDocumentInput", + "typeSimple": "Volo.Docs.Admin.Documents.PullDocumentInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "GetAllAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.GetAllInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.GetAllInput", + "typeSimple": "Volo.Docs.Admin.Documents.GetAllInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + } + }, + { + "name": "RemoveFromCacheAsync", + "parametersOnMethod": [ + { + "name": "documentId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "ReindexAsync", + "parametersOnMethod": [ + { + "name": "documentId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "GetFilterItemsAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Documents.DocumentInfoDto]" + } + }, + { + "name": "GetProjectsAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Projects.ProjectWithoutDetailsDto]" + } + } + ] + } + ], + "actions": { + "ClearCacheAsyncByInput": { + "uniqueName": "ClearCacheAsyncByInput", + "name": "ClearCacheAsync", + "httpMethod": "POST", + "url": "api/docs/admin/documents/ClearCache", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.ClearCacheInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.ClearCacheInput", + "typeSimple": "Volo.Docs.Admin.Documents.ClearCacheInput", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.Docs.Admin.Documents.ClearCacheInput", + "typeSimple": "Volo.Docs.Admin.Documents.ClearCacheInput", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "PullAllAsyncByInput": { + "uniqueName": "PullAllAsyncByInput", + "name": "PullAllAsync", + "httpMethod": "POST", + "url": "api/docs/admin/documents/PullAll", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.PullAllDocumentInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.PullAllDocumentInput", + "typeSimple": "Volo.Docs.Admin.Documents.PullAllDocumentInput", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.Docs.Admin.Documents.PullAllDocumentInput", + "typeSimple": "Volo.Docs.Admin.Documents.PullAllDocumentInput", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "PullAsyncByInput": { + "uniqueName": "PullAsyncByInput", + "name": "PullAsync", + "httpMethod": "POST", + "url": "api/docs/admin/documents/Pull", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.PullDocumentInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.PullDocumentInput", + "typeSimple": "Volo.Docs.Admin.Documents.PullDocumentInput", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.Docs.Admin.Documents.PullDocumentInput", + "typeSimple": "Volo.Docs.Admin.Documents.PullDocumentInput", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "GetAllAsyncByInput": { + "uniqueName": "GetAllAsyncByInput", + "name": "GetAllAsync", + "httpMethod": "GET", + "url": "api/docs/admin/documents/GetAll", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Documents.GetAllInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Documents.GetAllInput", + "typeSimple": "Volo.Docs.Admin.Documents.GetAllInput", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "ProjectId", + "jsonName": null, + "type": "System.Guid?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Name", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Version", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LanguageCode", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "FileName", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Format", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "CreationTimeMin", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "CreationTimeMax", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LastUpdatedTimeMin", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LastUpdatedTimeMax", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LastSignificantUpdateTimeMin", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LastSignificantUpdateTimeMax", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LastCachedTimeMin", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LastCachedTimeMax", + "jsonName": null, + "type": "System.DateTime?", + "typeSimple": "string?", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Sorting", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "SkipCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "MaxResultCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "RemoveFromCacheAsyncByDocumentId": { + "uniqueName": "RemoveFromCacheAsyncByDocumentId", + "name": "RemoveFromCacheAsync", + "httpMethod": "PUT", + "url": "api/docs/admin/documents/RemoveDocumentFromCache", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "documentId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "documentId", + "name": "documentId", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "ReindexAsyncByDocumentId": { + "uniqueName": "ReindexAsyncByDocumentId", + "name": "ReindexAsync", + "httpMethod": "PUT", + "url": "api/docs/admin/documents/ReindexDocument", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "documentId", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "documentId", + "name": "documentId", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "GetFilterItemsAsync": { + "uniqueName": "GetFilterItemsAsync", + "name": "GetFilterItemsAsync", + "httpMethod": "GET", + "url": "api/docs/admin/documents/GetFilterItems", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Documents.DocumentInfoDto]" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + }, + "GetProjectsAsync": { + "uniqueName": "GetProjectsAsync", + "name": "GetProjectsAsync", + "httpMethod": "GET", + "url": "api/docs/admin/documents/GetProjects", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Projects.ProjectWithoutDetailsDto]" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Documents.IDocumentAdminAppService" + } + } + }, + "Volo.Docs.Admin.ProjectsAdminController": { + "controllerName": "ProjectsAdmin", + "controllerGroupName": "ProjectsAdmin", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.Docs.Admin.ProjectsAdminController", + "interfaces": [ + { + "type": "Volo.Docs.Admin.Projects.IProjectAdminAppService", + "name": "IProjectAdminAppService", + "methods": [ + { + "name": "GetListAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto, Volo.Abp.Ddd.Application.Contracts", + "type": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + } + }, + { + "name": "GetAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Docs.Admin.Projects.ProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.ProjectDto" + } + }, + { + "name": "CreateAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.CreateProjectDto, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.CreateProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.CreateProjectDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Docs.Admin.Projects.ProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.ProjectDto" + } + }, + { + "name": "UpdateAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.UpdateProjectDto, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.UpdateProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.UpdateProjectDto", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Docs.Admin.Projects.ProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.ProjectDto" + } + }, + { + "name": "DeleteAsync", + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "ReindexAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.ReindexInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.ReindexInput", + "typeSimple": "Volo.Docs.Admin.Projects.ReindexInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "ReindexAllAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + }, + { + "name": "GetListWithoutDetailsAsync", + "parametersOnMethod": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Projects.ProjectWithoutDetailsDto]" + } + }, + { + "name": "GetPdfFilesAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.GetPdfFilesInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.GetPdfFilesInput", + "typeSimple": "Volo.Docs.Admin.Projects.GetPdfFilesInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + } + }, + { + "name": "DeletePdfFileAsync", + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.DeletePdfFileInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.DeletePdfFileInput", + "typeSimple": "Volo.Docs.Admin.Projects.DeletePdfFileInput", + "isOptional": false, + "defaultValue": null + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + } + } + ] + } + ], + "actions": { + "GetListAsyncByInput": { + "uniqueName": "GetListAsyncByInput", + "name": "GetListAsync", + "httpMethod": "GET", + "url": "api/docs/admin/projects", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto, Volo.Abp.Ddd.Application.Contracts", + "type": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedAndSortedResultRequestDto", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "Sorting", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "SkipCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "MaxResultCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "GetAsyncById": { + "uniqueName": "GetAsyncById", + "name": "GetAsync", + "httpMethod": "GET", + "url": "api/docs/admin/projects/{id}", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.Docs.Admin.Projects.ProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.ProjectDto" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "CreateAsyncByInput": { + "uniqueName": "CreateAsyncByInput", + "name": "CreateAsync", + "httpMethod": "POST", + "url": "api/docs/admin/projects", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.CreateProjectDto, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.CreateProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.CreateProjectDto", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.Docs.Admin.Projects.CreateProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.CreateProjectDto", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.Docs.Admin.Projects.ProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.ProjectDto" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "UpdateAsyncByIdAndInput": { + "uniqueName": "UpdateAsyncByIdAndInput", + "name": "UpdateAsync", + "httpMethod": "PUT", + "url": "api/docs/admin/projects/{id}", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + }, + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.UpdateProjectDto, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.UpdateProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.UpdateProjectDto", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": [], + "bindingSourceId": "Path", + "descriptorName": "" + }, + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.Docs.Admin.Projects.UpdateProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.UpdateProjectDto", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "Volo.Docs.Admin.Projects.ProjectDto", + "typeSimple": "Volo.Docs.Admin.Projects.ProjectDto" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "DeleteAsyncById": { + "uniqueName": "DeleteAsyncById", + "name": "DeleteAsync", + "httpMethod": "DELETE", + "url": "api/docs/admin/projects", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "id", + "typeAsString": "System.Guid, System.Private.CoreLib", + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "id", + "name": "id", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "ReindexAllAsync": { + "uniqueName": "ReindexAllAsync", + "name": "ReindexAllAsync", + "httpMethod": "POST", + "url": "api/docs/admin/projects/ReindexAll", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "GetListWithoutDetailsAsync": { + "uniqueName": "GetListWithoutDetailsAsync", + "name": "GetListWithoutDetailsAsync", + "httpMethod": "GET", + "url": "api/docs/admin/projects/GetListProjectWithoutDetailsAsync", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "System.Collections.Generic.List", + "typeSimple": "[Volo.Docs.Admin.Projects.ProjectWithoutDetailsDto]" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "GetPdfFilesAsyncByInput": { + "uniqueName": "GetPdfFilesAsyncByInput", + "name": "GetPdfFilesAsync", + "httpMethod": "GET", + "url": "api/docs/admin/projects/PdfFiles", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.GetPdfFilesInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.GetPdfFilesInput", + "typeSimple": "Volo.Docs.Admin.Projects.GetPdfFilesInput", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "ProjectId", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Sorting", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "SkipCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "MaxResultCount", + "jsonName": null, + "type": "System.Int32", + "typeSimple": "number", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + } + ], + "returnValue": { + "type": "Volo.Abp.Application.Dtos.PagedResultDto", + "typeSimple": "Volo.Abp.Application.Dtos.PagedResultDto" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "DeletePdfFileAsyncByInput": { + "uniqueName": "DeletePdfFileAsyncByInput", + "name": "DeletePdfFileAsync", + "httpMethod": "DELETE", + "url": "api/docs/admin/projects/DeletePdfFile", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.DeletePdfFileInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.DeletePdfFileInput", + "typeSimple": "Volo.Docs.Admin.Projects.DeletePdfFileInput", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "ProjectId", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Version", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "LanguageCode", + "jsonName": null, + "type": "System.String", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + }, + "ReindexAsyncByInput": { + "uniqueName": "ReindexAsyncByInput", + "name": "ReindexAsync", + "httpMethod": "POST", + "url": "api/docs/admin/projects/Reindex", + "supportedVersions": [], + "parametersOnMethod": [ + { + "name": "input", + "typeAsString": "Volo.Docs.Admin.Projects.ReindexInput, Volo.Docs.Admin.Application.Contracts", + "type": "Volo.Docs.Admin.Projects.ReindexInput", + "typeSimple": "Volo.Docs.Admin.Projects.ReindexInput", + "isOptional": false, + "defaultValue": null + } + ], + "parameters": [ + { + "nameOnMethod": "input", + "name": "input", + "jsonName": null, + "type": "Volo.Docs.Admin.Projects.ReindexInput", + "typeSimple": "Volo.Docs.Admin.Projects.ReindexInput", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "Body", + "descriptorName": "" + } + ], + "returnValue": { + "type": "System.Void", + "typeSimple": "System.Void" + }, + "allowAnonymous": null, + "implementFrom": "Volo.Docs.Admin.Projects.IProjectAdminAppService" + } + } + } + } + } + }, + "types": {} +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.csproj b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.csproj index 6d718f03bb..25a0be0294 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.csproj +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo.Docs.Admin.HttpApi.csproj @@ -12,6 +12,7 @@ + diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocsAdminHttpApiModule.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocsAdminHttpApiModule.cs index ed62f35e6f..ba7f1f7fbb 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocsAdminHttpApiModule.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocsAdminHttpApiModule.cs @@ -4,12 +4,14 @@ using Volo.Abp.Localization; using Volo.Abp.Modularity; using Volo.Docs.Localization; using Microsoft.Extensions.DependencyInjection; +using Volo.Docs.Common; namespace Volo.Docs.Admin { [DependsOn( typeof(DocsAdminApplicationContractsModule), - typeof(AbpAspNetCoreMvcModule) + typeof(AbpAspNetCoreMvcModule), + typeof(DocsCommonHttpApiModule) )] public class DocsAdminHttpApiModule : AbpModule { diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs index 5b1cffeae1..e020486887 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/ProjectsAdminController.cs @@ -70,6 +70,20 @@ namespace Volo.Docs.Admin return _projectAppService.GetListWithoutDetailsAsync(); } + [HttpGet] + [Route("PdfFiles")] + public Task> GetPdfFilesAsync(GetPdfFilesInput input) + { + return _projectAppService.GetPdfFilesAsync(input); + } + + [HttpDelete] + [Route("DeletePdfFile")] + public Task DeletePdfFileAsync(DeletePdfFileInput input) + { + return _projectAppService.DeletePdfFileAsync(input); + } + [HttpPost] [Route("Reindex")] public Task ReindexAsync(ReindexInput input) diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.js b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.js index 395ef8587e..91b3770c6f 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.js +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.js @@ -6,10 +6,11 @@ $(function () { return $datePicker.data('date'); }; - moment.localeData().preparse = (s)=>s; + moment.localeData().preparse = (s)=>s; moment.localeData().postformat = (s)=>s; - - $('.singledatepicker').daterangepicker({ + + var singleDatePicker = $('#DocumentsContainer .singledatepicker'); + singleDatePicker.daterangepicker({ "singleDatePicker": true, "showDropdowns": true, "autoUpdateInput": false, @@ -20,16 +21,16 @@ $(function () { "maxYear": 2199, }); - $('.singledatepicker').attr('autocomplete', 'off'); + singleDatePicker.attr('autocomplete', 'off'); - $('.singledatepicker').on('apply.daterangepicker', function (ev, picker) { + singleDatePicker.on('apply.daterangepicker', function (ev, picker) { $(this).val(picker.startDate.format('l')); $(this).data('date', picker.startDate.locale('en').format('YYYY-MM-DD')); }); var comboboxItems = []; - + service.getFilterItems() .then(function (result) { comboboxItems = result; @@ -44,13 +45,13 @@ $(function () { $projectId.on('change', function () { fillOptions(); }); - + var comboboxs = { version: $('#Version'), languageCode: $('#LanguageCode'), format: $('#Format') }; - + for (var key in comboboxs) { comboboxs[key].on('change', function () { fillOptions(); @@ -65,7 +66,7 @@ $(function () { comboboxs[key].empty(); } } - + function getSelectedItem() { var item = {}; for (var key in comboboxs) { @@ -73,13 +74,13 @@ $(function () { } return item; } - + function SetComboboxsValues(item) { for (var key in comboboxs) { comboboxs[key].val(item[key]); } } - + function addComboboxsEmptyItem() { for (var key in comboboxs) { comboboxs[key].append($('
public static int MaxVersionNameLength { get; set; } = 128; + + public static string Latest = "latest"; } } diff --git a/modules/docs/src/Volo.Docs.Web/Utils/UrlHelper.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Utils/UrlHelper.cs similarity index 100% rename from modules/docs/src/Volo.Docs.Web/Utils/UrlHelper.cs rename to modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Utils/UrlHelper.cs diff --git a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj index 5f2c9b6206..e57312e16b 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj +++ b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj @@ -20,7 +20,11 @@ - + + + + + @@ -28,6 +32,7 @@ + diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs index ff6bd56ee4..1e8463fe6c 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs @@ -3,5 +3,6 @@ public class DocsDomainConsts { public static string LanguageConfigFileName = "docs-langs.json"; + public static string PdfDocumentToHtmlConverterPrefix = "pdf-"; } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs index 6e6b222351..502b2f9065 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs @@ -1,10 +1,11 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Volo.Abp; using Volo.Abp.AutoMapper; +using Volo.Abp.BlobStoring; +using Volo.Abp.Caching; using Volo.Abp.Domain; using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Localization; @@ -16,15 +17,19 @@ using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.FileSystem.Documents; using Volo.Docs.GitHub; using Volo.Docs.GitHub.Documents; +using Volo.Docs.HtmlConverting; using Volo.Docs.Localization; using Volo.Docs.Projects; +using Volo.Docs.Projects.Pdf.Markdig; namespace Volo.Docs { [DependsOn( typeof(DocsDomainSharedModule), typeof(AbpDddDomainModule), - typeof(AbpAutoMapperModule) + typeof(AbpAutoMapperModule), + typeof(AbpBlobStoringModule), + typeof(AbpCachingModule) )] public class DocsDomainModule : AbpModule { @@ -76,6 +81,11 @@ namespace Volo.Docs { client.Timeout = TimeSpan.FromMilliseconds(15000); }); + + Configure(options => + { + options.Converters[DocsDomainConsts.PdfDocumentToHtmlConverterPrefix + MarkdigPdfDocumentToHtmlConverter.Type] = typeof(MarkdigPdfDocumentToHtmlConverter); + }); } public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs index e16f81d2c9..ca5c1221ad 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs @@ -32,7 +32,8 @@ namespace Volo.Docs.FileSystem.Documents localDirectory = documentName.Substring(0, documentName.LastIndexOf('/')); } - version = File.GetLastWriteTime(path).ToString("yyyyMMddHHmmss"); + // The version is intentionally set to "1.0.0" as part of the versioning strategy for file system documents. + version = "1.0.0"; return new Document(GuidGenerator.Create(), project.Id, diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ar.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ar.json index 6e01a9af72..f7d3533653 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ar.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ar.json @@ -38,6 +38,7 @@ "Search": "بحث", "SearchResults": "نتائج البحث", "SearchInTheAllDocuments": "البحث في جميع الوثائق", - "GoogleTranslate": "ترجمة جوجل" + "GoogleTranslate": "ترجمة جوجل", + "DownloadPDF": "تحميل PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json index c8e6d3d19b..ed6c8767b8 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/cs.json @@ -38,6 +38,7 @@ "Search": "Vyhledávání", "SearchResults": "Výsledky vyhledávání", "SearchInTheAllDocuments": "Hledejte ve všech dokumentech", - "GoogleTranslate": "Přeložit do češtiny" + "GoogleTranslate": "Přeložit do češtiny", + "DownloadPDF": "Stáhnout PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/de.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/de.json index 343db45f12..6a614441eb 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/de.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/de.json @@ -38,6 +38,7 @@ "Search": "Suchen", "SearchResults": "Suchergebnisse", "SearchInTheAllDocuments": "Durchsuchen Sie alle Dokumente", - "GoogleTranslate": "Ins Deutsche übersetzen" + "GoogleTranslate": "Ins Deutsche übersetzen", + "DownloadPDF": "PDF herunterladen" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/el.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/el.json index 21bc61b7e5..2a1a72dca2 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/el.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/el.json @@ -37,6 +37,7 @@ "Preview": "προεπισκόπηση", "Search": "Αναζήτηση", "SearchResults": "Αποτελέσματα αναζήτησης", - "GoogleTranslate": "Μετάφραση στα ελληνικά" + "GoogleTranslate": "Μετάφραση στα ελληνικά", + "DownloadPDF": "Κατέβασμα PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en-GB.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en-GB.json index ba33bd31d6..d56e8da6df 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en-GB.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en-GB.json @@ -35,6 +35,7 @@ "UpdatedExplanation": "Updated in the last two weeks.", "Volo.Docs.Domain:010002": "ShortName {ShortName} already exists.", "Preview": "preview", - "GoogleTranslate": "Google Translate" + "GoogleTranslate": "Google Translate", + "DownloadPDF": "Download PDF" } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json index b4414be0ea..6715146b50 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json @@ -43,6 +43,8 @@ "ProjectDeletionWarningMessage": "Project will be deleted.", "Docs_Page_Title": "ABP Documentation", "Docs_Page_Description": "Access comprehensive guides and API references in the ABP Documentation, aiding in development and troubleshooting.", - "GoogleTranslate": "Google Translate" + "GoogleTranslate": "Google Translate", + "DownloadPDF": "Download PDF", + "PdfFileGeneratedSuccessfully": "The PDF file is generated successfully." } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json index 624d56d631..3dcd97e7fe 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json @@ -38,6 +38,7 @@ "Search": "Buscar", "SearchResults": "Resultados de la búsqueda", "SearchInTheAllDocuments": "Buscar en todos los documentos", - "GoogleTranslate": "Traducir con Google" + "GoogleTranslate": "Traducir con Google", + "DownloadPDF": "Descargar PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fi.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fi.json index 543803bec4..db74d481a0 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fi.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fi.json @@ -38,6 +38,7 @@ "Search": "Hae", "SearchResults": "Hakutulokset", "SearchInTheAllDocuments": "Hae kaikista asiakirjoista", - "GoogleTranslate": "Google-käännös" + "GoogleTranslate": "Google-käännös", + "DownloadPDF": "Lataa PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fr.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fr.json index 6e8ccfffab..1bab402f73 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fr.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/fr.json @@ -38,6 +38,7 @@ "Search": "Rechercher", "SearchResults": "Résultats de recherche", "SearchInTheAllDocuments": "Rechercher dans tous les documents", - "GoogleTranslate": "Google Traduction" + "GoogleTranslate": "Google Traduction", + "DownloadPDF": "Télécharger PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hi.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hi.json index b79c38b9b8..2ba78ec460 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hi.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hi.json @@ -38,6 +38,7 @@ "Search": "खोज", "SearchResults": "खोज परिणाम", "SearchInTheAllDocuments": "सभी दस्तावेज़ों में खोजें", - "GoogleTranslate": "गूगल अनुवाद" + "GoogleTranslate": "गूगल अनुवाद", + "DownloadPDF": "PDF डाउनलोड करें" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hr.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hr.json index bf71b7faed..1061dee7ab 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hr.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hr.json @@ -38,6 +38,7 @@ "Search": "Pretraga", "SearchResults": "Rezultati pretrage", "SearchInTheAllDocuments": "Traži u svim dokumentima", - "GoogleTranslate": "Google prevoditelj" + "GoogleTranslate": "Google prevoditelj", + "DownloadPDF": "Preuzmi PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hu.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hu.json index 1624b1b2d1..b8dee63ca4 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hu.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hu.json @@ -38,6 +38,7 @@ "Search": "Keresés", "SearchResults": "Keresési eredmények", "SearchInTheAllDocuments": "Keressen az összes dokumentumban", - "GoogleTranslate": "Google Fordító" + "GoogleTranslate": "Google Fordító", + "DownloadPDF": "PDF letöltése" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/is.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/is.json index 5d96a2fac5..62235d3f62 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/is.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/is.json @@ -38,6 +38,7 @@ "Search": "Leit", "SearchResults": "Leitar niðurstöður", "SearchInTheAllDocuments": "Leitaðu í öllum skjölum", - "GoogleTranslate": "Google þýðing" + "GoogleTranslate": "Google þýðing", + "DownloadPDF": "Sækja PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/it.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/it.json index 3983154519..91ef732c01 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/it.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/it.json @@ -38,6 +38,7 @@ "Search": "Ricerca", "SearchResults": "Risultati della ricerca", "SearchInTheAllDocuments": "Cerca in tutti i documenti", - "GoogleTranslate": "Traduci con Google" + "GoogleTranslate": "Traduci con Google", + "DownloadPDF": "Scarica PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/nl.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/nl.json index f126886009..48a82699d7 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/nl.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/nl.json @@ -38,6 +38,7 @@ "Search": "Zoeken", "SearchResults": "Zoekresultaten", "SearchInTheAllDocuments": "Zoek in alle documenten", - "GoogleTranslate": "Google Vertalen" + "GoogleTranslate": "Google Vertalen", + "DownloadPDF": "PDF downloaden" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl-PL.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl-PL.json index 5d5c58ea3f..35ae3e6801 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl-PL.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pl-PL.json @@ -38,6 +38,7 @@ "Search": "Szukaj", "SearchResults": "Wyniki wyszukiwania", "SearchInTheAllDocuments": "Szukaj we wszystkich dokumentach", - "GoogleTranslate": "Tłumaczenie na polski" + "GoogleTranslate": "Tłumaczenie na polski", + "DownloadPDF": "Pobierz PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json index 0e4143f9ac..497f0c93e2 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/pt-BR.json @@ -38,6 +38,7 @@ "Search": "Procurar", "SearchResults": "Procurar Resultados", "SearchInTheAllDocuments": "Pesquise em todos os documentos", - "GoogleTranslate": "Traduzir com Google" + "GoogleTranslate": "Traduzir com Google", + "DownloadPDF": "Baixar PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ro-RO.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ro-RO.json index eaf9016463..155dad0754 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ro-RO.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ro-RO.json @@ -38,6 +38,7 @@ "Search": "Caută", "SearchResults": "Rezultatele căutării", "SearchInTheAllDocuments": "Căutați în toate documentele", - "GoogleTranslate": "Traducere Google" + "GoogleTranslate": "Traducere Google", + "DownloadPDF": "Descărcare PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ru.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ru.json index ae4b2a564d..2b5a200187 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ru.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ru.json @@ -38,6 +38,7 @@ "Search": "Поиск", "SearchResults": "результаты поиска", "SearchInTheAllDocuments": "Искать во всех документах", - "GoogleTranslate": "Google Translate" + "GoogleTranslate": "Google Translate", + "DownloadPDF": "Скачать PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sk.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sk.json index 54f981e98f..8f0f246a16 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sk.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sk.json @@ -38,6 +38,7 @@ "Search": "Vyhľadať", "SearchResults": "Výsledky vyhľadávania", "SearchInTheAllDocuments": "Vyhľadajte vo všetkých dokumentoch", - "GoogleTranslate": "Google preklad" + "GoogleTranslate": "Google preklad", + "DownloadPDF": "Stiahnuť PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sl.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sl.json index 3d326a5127..c182e66b3e 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sl.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sl.json @@ -38,6 +38,7 @@ "Search": "Iskanje", "SearchResults": "Rezultati iskanja", "SearchInTheAllDocuments": "Poiščite v vseh dokumentih", - "GoogleTranslate": "Google prevajalnik" + "GoogleTranslate": "Google prevajalnik", + "DownloadPDF": "Prenesi PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sv.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sv.json index 2ec28362f0..29db42be57 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sv.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/sv.json @@ -43,6 +43,7 @@ "ProjectDeletionWarningMessage": "Projektet kommer att raderas.", "Docs_Page_Title": "ABP-dokumentation", "Docs_Page_Description": "Få tillgång till omfattande guider och API-referenser i ABP Documentation, vilket underlättar utveckling och felsökning.", - "GoogleTranslate": "Google Översätt" + "GoogleTranslate": "Google Översätt", + "DownloadPDF": "Ladda ner PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json index 0e9619ce4d..35b08c6a62 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/tr.json @@ -37,6 +37,7 @@ "Preview": "ön izleme", "Search": "Arama", "SearchResults": "Arama Sonuçları", - "GoogleTranslate": "Google Çeviri" + "GoogleTranslate": "Google Çeviri", + "DownloadPDF": "PDF İndir" } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json index 612bcad36a..d6916d05ad 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/vi.json @@ -38,6 +38,7 @@ "Search": "Tìm kiếm", "SearchResults": "kết quả tìm kiếm", "SearchInTheAllDocuments": "Tìm kiếm trong tất cả các tài liệu", - "GoogleTranslate": "Dịch Google" + "GoogleTranslate": "Dịch Google", + "DownloadPDF": "Tải xuống PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json index 4aaac66120..d214b9b4a6 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json @@ -38,6 +38,7 @@ "Search": "搜索", "SearchResults": "搜索结果", "SearchInTheAllDocuments": "在所有文档中搜索", - "GoogleTranslate": "谷歌翻译" + "GoogleTranslate": "谷歌翻译", + "DownloadPDF": "下载PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json index 8f2a6ea86e..ee4a291b61 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json @@ -38,6 +38,7 @@ "Search": "搜索", "SearchResults": "搜索結果", "SearchInTheAllDocuments": "在所有文件中搜尋", - "GoogleTranslate": "谷歌翻譯" + "GoogleTranslate": "谷歌翻譯", + "DownloadPDF": "下載PDF" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs index db13ea2c8a..9d7443c5b2 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/IProjectRepository.cs @@ -8,7 +8,7 @@ namespace Volo.Docs.Projects { public interface IProjectRepository : IBasicRepository { - Task> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default); + Task> GetListAsync(string sorting, int maxResultCount, int skipCount,bool includeDetails = false, CancellationToken cancellationToken = default); Task> GetListWithoutDetailsAsync(CancellationToken cancellationToken = default); Task GetByShortNameAsync(string shortName, CancellationToken cancellationToken = default); diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/BlobProjectPdfFileStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/BlobProjectPdfFileStore.cs new file mode 100644 index 0000000000..315d89c49c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/BlobProjectPdfFileStore.cs @@ -0,0 +1,74 @@ +using System.IO; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Volo.Abp.BlobStoring; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Timing; + +namespace Volo.Docs.Projects.Pdf; + +public class BlobProjectPdfFileStore : IProjectPdfFileStore, ITransientDependency +{ + protected IBlobContainer BlobContainer { get; } + protected IOptions Options { get; } + protected IProjectRepository ProjectRepository { get; } + protected IClock Clock { get; } + + public BlobProjectPdfFileStore( + IBlobContainer blobContainer, + IOptions options, + IClock clock, IProjectRepository projectRepository) + { + BlobContainer = blobContainer; + Options = options; + Clock = clock; + ProjectRepository = projectRepository; + } + + public virtual async Task SetAsync(Project project, string version, string languageCode, Stream stream) + { + var fileName = Options.Value.CalculatePdfFileName(project, version, languageCode); + await BlobContainer.SaveAsync(fileName, stream, true); + + var pdfFile = project.FindPdfFile(fileName); + if(pdfFile == null) + { + project.AddPdfFile(project.Id, fileName, version, languageCode); + } + else + { + pdfFile.LastModificationTime = Clock.Now; + } + + await ProjectRepository.UpdateAsync(project); + } + + public virtual async Task GetOrNullAsync(Project project, string version, string languageCode) + { + var fileName = Options.Value.CalculatePdfFileName(project, version, languageCode); + + var pdfFile = project.FindPdfFile(fileName); + if (pdfFile == null) + { + return null; + } + + var lastModificationTime = pdfFile.LastModificationTime ?? pdfFile.CreationTime; + if(lastModificationTime.Add(Options.Value.PdfFileCacheExpiration) <= Clock.Now) + { + return null; + } + + return await BlobContainer.GetOrNullAsync(Options.Value.CalculatePdfFileName(project, version, languageCode)); + } + + public virtual async Task DeleteAsync(Project project, string version, string languageCode) + { + var fileName = Options.Value.CalculatePdfFileName(project, version, languageCode); + + await BlobContainer.DeleteAsync(fileName); + project.RemovePdfFile(fileName); + await ProjectRepository.UpdateAsync(project); + + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/DocsProjectPdfContainer.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/DocsProjectPdfContainer.cs new file mode 100644 index 0000000000..554ed42601 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/DocsProjectPdfContainer.cs @@ -0,0 +1,9 @@ +using Volo.Abp.BlobStoring; + +namespace Volo.Docs.Projects.Pdf; + +[BlobContainerName("docs-document-pdf")] +public class DocsProjectPdfContainer +{ + +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/DocsProjectPdfGeneratorOptions.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/DocsProjectPdfGeneratorOptions.cs new file mode 100644 index 0000000000..ef24e6ffd7 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/DocsProjectPdfGeneratorOptions.cs @@ -0,0 +1,120 @@ +using System; +using Scriban.Syntax; + +namespace Volo.Docs.Projects.Pdf; + +public class DocsProjectPdfGeneratorOptions +{ + public const string StylePlaceholder = "{{style-placeholder}}"; + public const string ContentPlaceholder = "{{content-placeholder}}"; + + /// + /// The HTML layout for the PDF document. + /// + public string HtmlLayout { get; set; } + + /// + /// The HTML style for the PDF document. + /// + public string HtmlStyle { get; set; } + + /// + /// The base URL for the PDF document. + /// Used for resolving relative links and images. + /// + public string BaseUrl { get; set; } + + /// + /// The path to the index page of the documentation. + /// + public string IndexPagePath { get; set; } + + /// + /// PDF file cache expiration time. + /// Default value is 24 hours. + /// + public TimeSpan PdfFileCacheExpiration { get; set; } = TimeSpan.FromHours(24); + + /// + /// The function to calculate the PDF file name. + /// Default is "{project.ShortName}-{version}-{languageCode}.pdf". + /// + public Func CalculatePdfFileName { get; set; } + + /// + /// The function to calculate the PDF file title. + /// + public Func CalculatePdfFileTitle { get; set; } + + public Func HtmlContentNormalizer { get; set; } + + public Func DocumentContentNormalizer { get; set; } + + public DocsProjectPdfGeneratorOptions() + { + HtmlLayout = $@" + + + + + + + {ContentPlaceholder} + + "; + + HtmlStyle = @" + body { margin: 15px; line-height: 1.5; font-family: Arial, sans-serif;} + a { text-decoration: none; word-break: break-all; overflow-wrap: break-word;} + li { word-break: break-all; overflow-wrap: break-word; } + .page { + page-break-after: always; + margin-bottom: 30px; + padding: 15px; + } + img { + max-width: 100%; + max-height: 850px; + object-fit: contain; + display: block; + } + code, pre { + background: #f8fafc; + white-space: pre-wrap; + word-wrap: break-word; + } + pre code { padding: 0; border: none; } + code { + padding: 2px 6px; + border-radius: 4px; + border: 1px solid #e2e8f0; + font-family: Consolas, monospace; + } + pre { + position: relative; + padding: 16px; + border-radius: 8px; + border: 1px solid #e2e8f0; + } + blockquote { + border-left: 4px solid #e2e8f0; + margin: 20px 0; + padding: 10px 20px; + background: #f8fafc; + } + table { width: 100%; border-collapse: collapse; table-layout: fixed; } + table img { width: 100% !important; height: auto; display: block; } + th { font-weight: bold; background-color: #f5f5f5; } + th, td { + border: 1px solid #333; + padding: 6px 10px; + word-break: break-all; + overflow-wrap: break-word; + width: 100%; + }"; + + CalculatePdfFileName = (project, version, languageCode) => $"{project.ShortName}-{version}-{languageCode}.pdf"; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IHtmlToPdfRenderer.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IHtmlToPdfRenderer.cs new file mode 100644 index 0000000000..c17908af51 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IHtmlToPdfRenderer.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace Volo.Docs.Projects.Pdf; + +public interface IHtmlToPdfRenderer +{ + Task RenderAsync(string title, string html, List documents); +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IProjectPdfFileStore.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IProjectPdfFileStore.cs new file mode 100644 index 0000000000..4f11d9cad2 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IProjectPdfFileStore.cs @@ -0,0 +1,13 @@ +using System.IO; +using System.Threading.Tasks; + +namespace Volo.Docs.Projects.Pdf; + +public interface IProjectPdfFileStore +{ + Task SetAsync(Project project, string version, string languageCode, Stream stream); + + Task GetOrNullAsync(Project project, string version, string languageCode); + + Task DeleteAsync(Project project, string version, string languageCode); +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IProjectPdfGenerator.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IProjectPdfGenerator.cs new file mode 100644 index 0000000000..af685659fa --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IProjectPdfGenerator.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; +using Volo.Abp.Content; + +namespace Volo.Docs.Projects.Pdf; + +public interface IProjectPdfGenerator +{ + Task GenerateAsync(Project project, string version, string languageCode); +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IText/HtmlIdTagWorkerFactory.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IText/HtmlIdTagWorkerFactory.cs new file mode 100644 index 0000000000..17483a7605 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IText/HtmlIdTagWorkerFactory.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using iText.Html2pdf.Attach; +using iText.Html2pdf.Attach.Impl; +using iText.Kernel.Pdf.Navigation; +using iText.StyledXmlParser.Node; + +namespace Volo.Docs.Projects.Pdf.IText; + +public class HtmlIdTagWorkerFactory : DefaultTagWorkerFactory +{ + private readonly iText.Kernel.Pdf.PdfDocument _pdfDocument; + private readonly Dictionary _pageDestinations = new(); + + public HtmlIdTagWorkerFactory(iText.Kernel.Pdf.PdfDocument pdfDocument) + { + _pdfDocument = pdfDocument; + } + + public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context) + { + var tagClass = tag.GetAttribute("class"); + if (tag.Name().Equals("div") && tagClass =="page") + { + var id = tag.GetAttribute("id"); + _pageDestinations[id] = _pdfDocument.GetNumberOfPages() + 1; + } + + return base.GetCustomTagWorker(tag, context); + } + + public void AddNamedDestinations() + { + foreach (var pageDestination in _pageDestinations) + { + var page = _pdfDocument.GetPage(pageDestination.Value); + var destination = PdfExplicitDestination.CreateFit(page); + _pdfDocument.AddNamedDestination(pageDestination.Key, destination.GetPdfObject()); + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IText/ITextHtmlToPdfRenderer.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IText/ITextHtmlToPdfRenderer.cs new file mode 100644 index 0000000000..1ee6b679e3 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/IText/ITextHtmlToPdfRenderer.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using iText.Html2pdf; +using iText.Kernel.Pdf; +using iText.Kernel.Pdf.Action; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Docs.Utils; +using ITextDocument = iText.Layout.Document; + +namespace Volo.Docs.Projects.Pdf.IText; + +public class ITextHtmlToPdfRenderer : IHtmlToPdfRenderer ,ITransientDependency +{ + protected IOptions Options { get; } + + public ITextHtmlToPdfRenderer(IOptions options) + { + Options = options; + } + + public virtual Task RenderAsync(string title, string html, List documents) + { + var pdfStream = new MemoryStream(); + var pdfWrite = new PdfWriter(pdfStream); + var pdfDocument = new iText.Kernel.Pdf.PdfDocument(pdfWrite); + pdfDocument.GetDocumentInfo().SetTitle(title); + var textDocument = new ITextDocument(pdfDocument); + pdfWrite.SetCloseStream(false); + + var converter = new ConverterProperties(); + var tagWorkerFactory = new HtmlIdTagWorkerFactory(pdfDocument); + converter.SetTagWorkerFactory(tagWorkerFactory); + + HtmlConverter.ConvertToDocument(html, pdfDocument, converter); + + tagWorkerFactory.AddNamedDestinations(); + var pdfOutlines = pdfDocument.GetOutlines(false); + BuildPdfOutlines(pdfOutlines, documents); + + textDocument.Close(); + pdfStream.Position = 0; + return Task.FromResult(pdfStream); + } + + private void BuildPdfOutlines(PdfOutline parentOutline, List pdfDocumentNodes) + { + foreach (var pdfDocumentNode in pdfDocumentNodes) + { + if (pdfDocumentNode.IgnoreOnOutline) + { + continue; + } + + var outline = parentOutline.AddOutline(pdfDocumentNode.Title); + if (!pdfDocumentNode.Id.IsNullOrWhiteSpace()) + { + outline.AddAction(UrlHelper.IsExternalLink(pdfDocumentNode.Id) ? PdfAction.CreateURI(pdfDocumentNode.Id) : PdfAction.CreateGoTo(pdfDocumentNode.Id)); + } + + if (pdfDocumentNode.HasChildren) + { + BuildPdfOutlines(outline, pdfDocumentNode.Children); + } + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/AnchorLinkRenderer.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/AnchorLinkRenderer.cs new file mode 100644 index 0000000000..33fd2fd83a --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/AnchorLinkRenderer.cs @@ -0,0 +1,62 @@ +using System; +using System.Linq; +using Markdig.Renderers; +using Markdig.Renderers.Html.Inlines; +using Markdig.Syntax.Inlines; +using Volo.Docs.Utils; + +namespace Volo.Docs.Projects.Pdf.Markdig; + +public class AnchorLinkRenderer : LinkInlineRenderer +{ + private readonly PdfDocument _document; + + public AnchorLinkRenderer(PdfDocument document) + { + _document = document; + } + + protected override void Write(HtmlRenderer renderer, LinkInline link) + { + if (UrlHelper.IsExternalLink(link.Url) || link.Url.IsNullOrWhiteSpace() || link.IsImage) + { + base.Write(renderer, link); + return; + } + + var anchor = ResolveRelativeMarkdownPath(_document.Document.Name, link.Url) + .Replace(".md",string.Empty).Replace("/","-").Replace(" ", "-").ToLower(); + + renderer.Write(""); + renderer.Write(link.FirstChild?.ToString() ?? anchor); + renderer.Write(""); + } + + private string ResolveRelativeMarkdownPath(string currentPath, string relativePath) + { + currentPath = currentPath.EnsureStartsWith('/'); + relativePath = relativePath.EnsureStartsWith('/'); + + var currentDir = currentPath.Substring(0, currentPath.LastIndexOf('/')); + + var baseParts = currentDir.Split('/', StringSplitOptions.RemoveEmptyEntries).ToList(); + var relativeParts = relativePath.Split('/', StringSplitOptions.RemoveEmptyEntries); + + foreach (var part in relativeParts) + { + if (part == "..") + { + if (baseParts.Count > 0) + { + baseParts.RemoveAt(baseParts.Count - 1); + } + } + else if (part != ".") + { + baseParts.Add(part); + } + } + + return string.Join("/", baseParts); + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/AnchorLinkResolverExtension.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/AnchorLinkResolverExtension.cs new file mode 100644 index 0000000000..38405da4d7 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/AnchorLinkResolverExtension.cs @@ -0,0 +1,27 @@ +using Markdig; +using Markdig.Renderers; +using Markdig.Renderers.Html.Inlines; + +namespace Volo.Docs.Projects.Pdf.Markdig; + +public class AnchorLinkResolverExtension : IMarkdownExtension +{ + private readonly PdfDocument _document; + + public AnchorLinkResolverExtension(PdfDocument document) + { + _document = document; + } + + public void Setup(MarkdownPipelineBuilder pipeline) + { + } + + public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) + { + if (renderer is HtmlRenderer htmlRenderer) + { + htmlRenderer.ObjectRenderers.Replace(new AnchorLinkRenderer(_document)); + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/MarkdigPdfDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/MarkdigPdfDocumentToHtmlConverter.cs new file mode 100644 index 0000000000..22c94b5930 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/Markdig/MarkdigPdfDocumentToHtmlConverter.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Web; +using Markdig; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Docs.Documents; +using Volo.Docs.HtmlConverting; +using Volo.Docs.Utils; + +namespace Volo.Docs.Projects.Pdf.Markdig; + +public class MarkdigPdfDocumentToHtmlConverter : IDocumentToHtmlConverter, ITransientDependency +{ + public const string Type = "md"; + protected IOptions Options { get; } + + public MarkdigPdfDocumentToHtmlConverter(IOptions options) + { + Options = options; + } + + public virtual string Convert(PdfDocumentToHtmlConverterContext converterContext) + { + var htmlContent = Markdown.ToHtml(NormalizeContent( + converterContext.Content, + converterContext.PdfDocument, + converterContext.DocumentParams), + GetPipeline(converterContext.PdfDocument)); + return NormalizeHtmlContent(htmlContent, converterContext.PdfDocument); + } + + protected virtual MarkdownPipeline GetPipeline(PdfDocument pdfDocument) + { + return new MarkdownPipelineBuilder() + .UseAdvancedExtensions() + .UseBootstrap() + .Use(new AnchorLinkResolverExtension(pdfDocument)) + .Build(); + } + + protected virtual string NormalizeContent(string content, PdfDocument pdfDocument, DocumentParams documentParams) + { + content = Regex.Replace(content, @"`{3,4}json\s*//\[doc-nav\][\s\S]*?`{3,4}", string.Empty, RegexOptions.IgnoreCase); + content = SetContentTitle(content, pdfDocument, documentParams); + if (Options.Value.DocumentContentNormalizer == null) + { + return content; + } + + return Options.Value.DocumentContentNormalizer(content); + } + + protected virtual string NormalizeHtmlContent(string htmlContent, PdfDocument pdfDocument) + { + htmlContent = WrapHtmlWithPageDiv(htmlContent, pdfDocument); + htmlContent = ReplaceRelativeImageUrls(htmlContent, pdfDocument); + if (Options.Value.HtmlContentNormalizer == null) + { + return htmlContent; + } + + return Options.Value.HtmlContentNormalizer(htmlContent); + } + + private string WrapHtmlWithPageDiv(string htmlContent, PdfDocument pdfDocument) + { + return $"
{htmlContent}
"; + } + + private string ReplaceRelativeImageUrls(string htmlContent, PdfDocument pdfDocument) + { + return Regex.Replace(htmlContent, @"(]*)src=""([^""]*)""([^>]*>)", delegate (Match match) + { + if (UrlHelper.IsExternalLink(match.Groups[2].Value)) + { + return match.Value; + } + + var rootUrl = UrlHelper.IsExternalLink(pdfDocument.Document.RawRootUrl) + ? pdfDocument.Document.RawRootUrl.EnsureEndsWith('/') + : Options.Value.BaseUrl.EnsureEndsWith('/') + pdfDocument.Document.RawRootUrl.TrimStart('/').EnsureEndsWith('/'); + var newImageSource = rootUrl + + (pdfDocument.Document.LocalDirectory.IsNullOrEmpty() ? "" : pdfDocument.Document.LocalDirectory.TrimStart('/').EnsureEndsWith('/')) + + match.Groups[2].Value.TrimStart('/'); + + return match.Groups[1] + " src=\"" + HttpUtility.HtmlEncode(newImageSource) + "\" " + match.Groups[3]; + + }, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Multiline); + } + + private static string SetContentTitle(string content, PdfDocument pdfDocument, DocumentParams documentParams) + { + if (pdfDocument.RenderParameters.IsNullOrEmpty()) + { + return content; + } + + var titleLine = content.Split(Environment.NewLine).FirstOrDefault(x => x.TrimStart().StartsWith("#")); + if (titleLine == null) + { + return content; + } + + var paramValues = pdfDocument.RenderParameters.Select(x => + { + var documentParam = documentParams.Parameters.FirstOrDefault(p => p.Name == x.Key); + return $"{documentParam?.Values[x.Value] ?? x.Value}"; + }); + + var newTitle = $"{titleLine.Trim()} ({string.Join(", ", paramValues)})"; + return content.Replace(titleLine, newTitle); + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/PdfDocument.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/PdfDocument.cs new file mode 100644 index 0000000000..a0aca0c710 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/PdfDocument.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Linq; +using Volo.Docs.Documents; +using Volo.Docs.Documents.Rendering; + +namespace Volo.Docs.Projects.Pdf; + +public class PdfDocument +{ + public Document Document { get; set; } + public string Title { get; set; } + public string Id { get; set; } + public List Children { get; set; } = []; + public DocumentRenderParameters RenderParameters { get; set; } + public bool HasChildren => Children.Any(); + public bool IgnoreOnOutline { get; set; } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/PdfDocumentToHtmlConverterContext.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/PdfDocumentToHtmlConverterContext.cs new file mode 100644 index 0000000000..5a99d46634 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/PdfDocumentToHtmlConverterContext.cs @@ -0,0 +1,18 @@ +using Volo.Docs.Documents; + +namespace Volo.Docs.Projects.Pdf; + +public class PdfDocumentToHtmlConverterContext +{ + public string Content { get; set; } + public PdfDocument PdfDocument { get; set; } + + public DocumentParams DocumentParams { get; set; } + + public PdfDocumentToHtmlConverterContext(string content, PdfDocument pdfDocument, DocumentParams documentParams) + { + Content = content; + PdfDocument = pdfDocument; + DocumentParams = documentParams; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/ProjectPdfGenerator.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/ProjectPdfGenerator.cs new file mode 100644 index 0000000000..c00973b3e8 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Pdf/ProjectPdfGenerator.cs @@ -0,0 +1,471 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Volo.Abp; +using Volo.Abp.Content; +using Volo.Abp.DependencyInjection; +using Volo.Docs.Documents; +using Volo.Docs.Documents.Rendering; +using Volo.Docs.HtmlConverting; +using Volo.Docs.Utils; +using Volo.Extensions; + +namespace Volo.Docs.Projects.Pdf; + +public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency +{ + protected IDocumentSourceFactory DocumentStoreFactory { get; } + protected IDocumentToHtmlConverterFactory DocumentToHtmlConverterFactory { get; } + protected IDocumentRepository DocumentRepository { get; } + protected IDocumentSectionRenderer DocumentSectionRenderer { get; } + protected IOptions Options { get; } + protected IProjectPdfFileStore ProjectPdfFileStore { get; } + protected IHtmlToPdfRenderer HtmlToPdfRenderer { get; } + protected ILogger Logger { get; set; } + protected IDocumentSource DocumentSource { get; set; } + protected DocumentParams DocumentParams { get; set; } + protected Project Project { get; set; } + protected List AllPdfDocuments { get; } = []; + + public ProjectPdfGenerator( + IDocumentSourceFactory documentStoreFactory, + IDocumentRepository documentRepository, + IOptions options, + IDocumentSectionRenderer documentSectionRenderer, + IProjectPdfFileStore projectPdfFileStore, + IHtmlToPdfRenderer htmlToPdfRenderer, + IDocumentToHtmlConverterFactory documentToHtmlConverterFactory) + { + DocumentStoreFactory = documentStoreFactory; + DocumentRepository = documentRepository; + Options = options; + DocumentSectionRenderer = documentSectionRenderer; + ProjectPdfFileStore = projectPdfFileStore; + HtmlToPdfRenderer = htmlToPdfRenderer; + DocumentToHtmlConverterFactory = documentToHtmlConverterFactory; + Logger = NullLogger.Instance; + } + + public virtual async Task GenerateAsync(Project project, string version, string languageCode) + { + var fileName = Options.Value.CalculatePdfFileName(project, version, languageCode); + var fileStream = await ProjectPdfFileStore.GetOrNullAsync(project, version, languageCode); + + if (fileStream != null) + { + return new RemoteStreamContent(fileStream, fileName, "application/pdf"); + } + + Project = project; + DocumentSource = DocumentStoreFactory.Create(project.DocumentStoreType); + DocumentParams = await GetDocumentParamsAsync(project, version, languageCode); + + var navigation = await GetNavigationAsync(project, version, languageCode); + await SetAllPdfDocumentsAsync(navigation.Items, project, version, languageCode); + + var html = await BuildHtmlAsync(); + var title = Options.Value.CalculatePdfFileTitle?.Invoke(project) ?? project.Name; + var pdfStream = await HtmlToPdfRenderer.RenderAsync(title, html, AllPdfDocuments); + + await ProjectPdfFileStore.SetAsync(project, version, languageCode, pdfStream); + + return new RemoteStreamContent(pdfStream, fileName, "application/pdf"); + } + + protected virtual async Task BuildHtmlAsync() + { + var htmlContent = await ConvertDocumentsToHtmlAsync(AllPdfDocuments); + + var htmlBuilder = new StringBuilder(); + htmlBuilder.Append(Options.Value.HtmlLayout); + htmlBuilder.Replace(DocsProjectPdfGeneratorOptions.StylePlaceholder, Options.Value.HtmlStyle); + htmlBuilder.Replace(DocsProjectPdfGeneratorOptions.ContentPlaceholder, htmlContent); + + return htmlBuilder.ToString(); + } + + protected virtual async Task ConvertDocumentsToHtmlAsync(List pdfDocuments) + { + var contentBuilder = new StringBuilder(); + + foreach (var pdfDocument in pdfDocuments) + { + if (pdfDocument.Document != null) + { + var renderedDocument = await RenderDocumentAsync(pdfDocument); + var documentToHtmlConverter = GetDocumentToHtmlConverter(Project, pdfDocument); + var htmlContent = documentToHtmlConverter.Convert(new PdfDocumentToHtmlConverterContext(renderedDocument, pdfDocument, DocumentParams)); + contentBuilder.AppendLine(htmlContent); + } + + if (pdfDocument.HasChildren) + { + contentBuilder.AppendLine(await ConvertDocumentsToHtmlAsync(pdfDocument.Children)); + } + } + + return contentBuilder.ToString(); + } + + protected virtual IDocumentToHtmlConverter GetDocumentToHtmlConverter(Project project, PdfDocument pdfDocument) + { + return DocumentToHtmlConverterFactory.Create(DocsDomainConsts.PdfDocumentToHtmlConverterPrefix +(pdfDocument.Document.Format ?? project.Format)); + } + + protected virtual async Task RenderDocumentAsync(PdfDocument pdfDocument) + { + var parameters = new DocumentRenderParameters(); + if (pdfDocument.RenderParameters != null) + { + foreach (var renderParameter in pdfDocument.RenderParameters) + { + var documentParam = DocumentParams.Parameters.FirstOrDefault(p => p.Name == renderParameter.Key); + parameters.Add(renderParameter.Key, renderParameter.Value); + parameters.Add(renderParameter.Key + "_Value",documentParam?.Values[renderParameter.Value] ?? renderParameter.Value); + } + } + + return await DocumentSectionRenderer.RenderAsync(pdfDocument.Document.Content, parameters); + } + + protected virtual async Task SetAllPdfDocumentsAsync( + List navigations, + Project project, + string version, + string languageCode, + PdfDocument parentPdfDocument = null) + { + var groupedCombinationsDocuments = new Dictionary>(); + + foreach (var navigation in navigations) + { + if (navigation.IgnoreOnDownload) + { + continue; + } + + try + { + var pdfDocument = new PdfDocument + { + Title = navigation.Text, + IgnoreOnOutline = navigation.Path == Options.Value.IndexPagePath, + Id = UrlHelper.IsExternalLink(navigation.Path) ? navigation.Path: null + }; + + if (!navigation.Path.IsNullOrWhiteSpace() && !UrlHelper.IsExternalLink(navigation.Path) && !navigation.HasChildItems) + { + await HandleLeafDocumentAsync( + navigation, + project, + version, + languageCode, + parentPdfDocument, + groupedCombinationsDocuments, + pdfDocument + ); + } + + if (!navigation.IsInSeries) + { + if (parentPdfDocument == null) + { + AllPdfDocuments.AddIfNotContains(pdfDocument); + } + else + { + parentPdfDocument.Children.AddIfNotContains(pdfDocument); + } + } + + if (navigation.HasChildItems) + { + AddParameterCombinationsDocuments(parentPdfDocument, groupedCombinationsDocuments); + await SetAllPdfDocumentsAsync(navigation.Items, project, version, languageCode, pdfDocument); + } + + if (!navigation.IsInSeries || navigation == navigations.Last()) + { + AddParameterCombinationsDocuments(parentPdfDocument, groupedCombinationsDocuments); + } + } + catch (Exception e) + { + Logger.LogWarning(e, $"Cannot get document for the path '{navigation.Path}' in the project {project.Name}."); + } + } + } + + private async Task HandleLeafDocumentAsync( + NavigationNode navigation, + Project project, + string version, + string languageCode, + PdfDocument parentPdfDocument, + Dictionary> groupedCombinationsDocuments, + PdfDocument leafDocument) + { + var document = await GetDocumentAsync(project, navigation.Path, version, languageCode); + var parameters = await DocumentSectionRenderer.GetAvailableParametersAsync(document.Content); + var parameterCombinations = GenerateAllParameterCombinations(parameters.Keys.ToList(), parameters); + var firstCombination = parameterCombinations.FirstOrDefault(); + + leafDocument.Document = document; + leafDocument.RenderParameters = firstCombination; + leafDocument.Id = GetDocumentId(document.Name, document.Format ?? project.Format, firstCombination, true); + leafDocument.Title = GetDocumentTitle(navigation.Text, firstCombination, DocumentParams); + + if (parameterCombinations.Count <= 1) + { + AddParameterCombinationsDocuments(parentPdfDocument, groupedCombinationsDocuments); + return; + } + + for (var i = 0; i < parameterCombinations.Count; i++) + { + var combination = parameterCombinations[i]; + var key = string.Join("-", combination.Select(x => $"{x.Key}_{x.Value}")); + + if (!groupedCombinationsDocuments.ContainsKey(key)) + { + groupedCombinationsDocuments[key] = []; + } + + var combinationDocument = i == 0 ? leafDocument : new PdfDocument + { + Document = document, + Id = GetDocumentId(document.Name, document.Format ?? project.Format, combination, false), + Title = GetDocumentTitle(navigation.Text, combination, DocumentParams), + RenderParameters = combination + }; + + groupedCombinationsDocuments[key].Add(combinationDocument); + } + } + + private void AddParameterCombinationsDocuments(PdfDocument parentPdfDocument, Dictionary> groupedCombinationsDocuments) + { + foreach (var combinations in groupedCombinationsDocuments) + { + if (parentPdfDocument == null) + { + AllPdfDocuments.AddIfNotContains(combinations.Value); + } + else + { + parentPdfDocument.Children.AddIfNotContains(combinations.Value); + } + } + + groupedCombinationsDocuments.Clear(); + } + + private async Task GetNavigationAsync( + Project project, + string version, + string languageCode) + { + var navigationDocument = await GetDocumentAsync(project, project.NavigationDocumentName, version, languageCode); + + if (!DocsJsonSerializerHelper.TryDeserialize(navigationDocument.Content, out var navigation)) + { + throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}."); + } + + if (!Options.Value.IndexPagePath.IsNullOrWhiteSpace()) + { + navigation.Items.Insert(0, new NavigationNode + { + Path = Options.Value.IndexPagePath + }); + } + + return navigation; + } + + private async Task GetDocumentParamsAsync( + Project project, + string version, + string languageCode) + { + if (project.ParametersDocumentName.IsNullOrWhiteSpace()) + { + return new DocumentParams(); + } + + try + { + var documentParamsDocument = await GetDocumentAsync(project, project.ParametersDocumentName, version, languageCode); + + if (!DocsJsonSerializerHelper.TryDeserialize(documentParamsDocument.Content, out var documentParams)) + { + throw new UserFriendlyException($"Cannot validate document params file '{project.ParametersDocumentName}' for the project {project.Name}."); + } + + return documentParams; + } + catch (Exception e) + { + Logger.LogError(e, $"Cannot get document params for the project {project.Name}.", e); + return new DocumentParams(); + } + } + + private async Task GetDocumentAsync( + Project project, + string documentName, + string version, + string languageCode) + { + version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version; + + Document document = null; + Exception firstException = null; + + var possibleNames = GetPossibleNames(documentName, project.Format); + document = await DocumentRepository.FindAsync(project.Id, possibleNames, languageCode, version); + if (document != null) + { + return document; + } + + foreach (var name in possibleNames) + { + try + { + document = await DocumentSource.GetDocumentAsync(project, name, languageCode, version); + await DocumentRepository.InsertAsync(document, true); + break; + } + catch (Exception ex) + { + firstException ??= ex; + } + } + + if(document == null) + { + throw firstException!; + } + + return document; + } + + private List GenerateAllParameterCombinations(List parameterKeys, Dictionary> parameters) + { + var parameterCombinations = new List(); + + if (parameters.Count <= 0) + { + return parameterCombinations; + } + + GenerateCombinations(0, new DocumentRenderParameters()); + return parameterCombinations; + + void GenerateCombinations(int keyIndex, DocumentRenderParameters currentCombination) + { + if (keyIndex == parameterKeys.Count) + { + parameterCombinations.Add(new DocumentRenderParameters(currentCombination)); + return; + } + + var currentKey = parameterKeys[keyIndex]; + foreach (var value in parameters[currentKey]) + { + currentCombination[currentKey] = value; + GenerateCombinations(keyIndex + 1, currentCombination); + } + } + } + + private static string GetDocumentId(string documentName, string format, DocumentRenderParameters parameters, bool isFirstCombinationDocument) + { + var id = documentName.Replace("." + format, string.Empty).Replace("/","-").Replace(" ", "-").ToLower(); + if (parameters != null && !isFirstCombinationDocument) + { + id = $"{id}{parameters.Select(x => $"{x.Key}_{x.Value}").JoinAsString("-")}"; + } + + return id; + } + + private static string GetDocumentTitle(string title, DocumentRenderParameters parameters, DocumentParams documentParams) + { + if (parameters == null || parameters.Count <= 0) + { + return title; + } + + var paramValues = parameters.Select(x => + { + var documentParam = documentParams.Parameters.FirstOrDefault(p => p.Name == x.Key); + return $"{documentParam?.DisplayName ?? x.Key} : {documentParam?.Values[x.Value] ?? x.Value}"; + }); + + return title.Trim() + $" ({string.Join(", ", paramValues)})"; + } + + private static List GetPossibleNames(string originalDocumentName, string format) + { + var extension = Path.GetExtension(originalDocumentName); + if (extension.IsNullOrWhiteSpace()) + { + extension = "." + format; + } + + if (!extension.Equals("." + format, StringComparison.OrdinalIgnoreCase)) + { + return [originalDocumentName]; + } + + var lowerCaseIndex = "index." + format; + var titleCaseIndex = "Index." + format; + var indexLength = lowerCaseIndex.Length; + + var possibleNames = new List {originalDocumentName}; + if (originalDocumentName.EndsWith("/" + lowerCaseIndex, StringComparison.OrdinalIgnoreCase) || originalDocumentName.Equals(lowerCaseIndex, StringComparison.OrdinalIgnoreCase)) + { + var indexPart = originalDocumentName.Right(indexLength); + + var documentNameWithoutIndex = originalDocumentName.Left(originalDocumentName.Length - lowerCaseIndex.Length); + + if(indexPart != lowerCaseIndex) + { + possibleNames.Add(documentNameWithoutIndex + lowerCaseIndex); + } + + if(indexPart != titleCaseIndex) + { + possibleNames.Add(documentNameWithoutIndex + titleCaseIndex); + } + } + else + { + var documentNameWithoutExtension = RemoveFileExtensionFromPath(originalDocumentName, format).EnsureEndsWith('/'); + possibleNames.Add(documentNameWithoutExtension + lowerCaseIndex); + possibleNames.Add(documentNameWithoutExtension + titleCaseIndex); + } + + return possibleNames; + } + + private static string RemoveFileExtensionFromPath(string path, string format) + { + if (path == null) + { + return null; + } + + return path.EndsWith("." + format) + ? path.Left(path.Length - format.Length - 1) + : path; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs index 48eb93d19e..69fa3a7056 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/Project.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using JetBrains.Annotations; using Volo.Abp; using Volo.Abp.Domain.Entities; @@ -47,9 +48,12 @@ namespace Volo.Docs.Projects public virtual string MainWebsiteUrl { get; set; } public virtual string LatestVersionBranchName { get; set; } + + public virtual List PdfFiles { get; set; } protected Project() { + PdfFiles = new List(); } public Project( @@ -103,5 +107,24 @@ namespace Volo.Docs.Projects { ShortName = ShortName.ToLower(); } + + public virtual ProjectPdfFile FindPdfFile(string fileName) + { + return PdfFiles.Find(x => x.FileName == fileName); + } + + public virtual void AddPdfFile(Guid projectId, string fileName, string version, string languageCode) + { + PdfFiles.Add(new ProjectPdfFile(projectId, fileName, version, languageCode)); + } + + public virtual void RemovePdfFile(string fileName) + { + var pdfFile = FindPdfFile(fileName); + if (pdfFile != null) + { + PdfFiles.Remove(pdfFile); + } + } } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/ProjectPdfFile.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/ProjectPdfFile.cs new file mode 100644 index 0000000000..135ca3b01e --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Projects/ProjectPdfFile.cs @@ -0,0 +1,38 @@ +using System; +using Volo.Abp.Auditing; +using Volo.Abp.Domain.Entities; + +namespace Volo.Docs.Projects; + +public class ProjectPdfFile : Entity, IHasCreationTime, IHasModificationTime +{ + public virtual Guid ProjectId { get; set; } + public virtual string FileName { get; set; } + public virtual string Version { get; set; } + public virtual string LanguageCode { get; set; } + public virtual DateTime CreationTime { get; set; } + public virtual DateTime? LastModificationTime { get; set; } + + protected ProjectPdfFile() + { + + } + + public ProjectPdfFile(Guid projectId, string fileName, string version, string languageCode) + { + ProjectId = projectId; + FileName = fileName; + Version = version; + LanguageCode = languageCode; + } + + public override object[] GetKeys() + { + return [ProjectId, FileName]; + } + + public virtual bool Equals(Guid projectId, string fileName) + { + return ProjectId == projectId && FileName == fileName; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs index 9ce0c59dc3..56b2204bc5 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContext.cs @@ -16,6 +16,8 @@ namespace Volo.Docs.EntityFrameworkCore public DbSet Documents { get; set; } public DbSet DocumentContributors { get; set; } + + public DbSet ProjectPdfFiles { get; set; } public DocsDbContext(DbContextOptions options) : base(options) diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs index 745b822f17..86f230164f 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs @@ -31,6 +31,10 @@ namespace Volo.Docs.EntityFrameworkCore b.Property(x => x.NavigationDocumentName).IsRequired().HasMaxLength(ProjectConsts.MaxNavigationDocumentNameLength); b.Property(x => x.ParametersDocumentName).IsRequired().HasMaxLength(ProjectConsts.MaxParametersDocumentNameLength); b.Property(x => x.LatestVersionBranchName).HasMaxLength(ProjectConsts.MaxLatestVersionBranchNameLength); + + b.HasMany(x => x.PdfFiles).WithOne() + .HasForeignKey(x => new { x.ProjectId }) + .IsRequired(); b.ApplyObjectExtensionMappings(); }); @@ -69,6 +73,17 @@ namespace Volo.Docs.EntityFrameworkCore b.ApplyObjectExtensionMappings(); }); + + builder.Entity(b => + { + b.ToTable(AbpDocsDbProperties.DbTablePrefix + "ProjectPdfFiles", AbpDocsDbProperties.DbSchema); + + b.ConfigureByConvention(); + + b.HasKey(x => new { x.ProjectId, x.FileName }); + + b.ApplyObjectExtensionMappings(); + }); builder.TryConfigureObjectExtensions(); } diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEfCoreQueryableExtensions.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEfCoreQueryableExtensions.cs index 0bd2e4fff8..89aff2cf3c 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEfCoreQueryableExtensions.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsEfCoreQueryableExtensions.cs @@ -1,6 +1,7 @@ using System.Linq; using Microsoft.EntityFrameworkCore; using Volo.Docs.Documents; +using Volo.Docs.Projects; namespace Volo.Docs.EntityFrameworkCore { @@ -10,5 +11,10 @@ namespace Volo.Docs.EntityFrameworkCore { return !include ? queryable : queryable.Include(x => x.Contributors); } + + public static IQueryable IncludeDetails(this IQueryable queryable, bool include = true) + { + return !include ? queryable : queryable.Include(x => x.PdfFiles); + } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs index e85f9b4aa5..69ab6f7b1d 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/IDocsDbContext.cs @@ -16,5 +16,7 @@ namespace Volo.Docs.EntityFrameworkCore DbSet Documents { get; } DbSet DocumentContributors { get; } + + DbSet ProjectPdfFiles { get; set; } } } diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs index cbdf4cec06..e7db47335c 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Projects/EfCoreProjectRepository.cs @@ -19,9 +19,14 @@ namespace Volo.Docs.Projects { } - public virtual async Task> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default) + public virtual async Task> GetListAsync( + string sorting, + int maxResultCount, + int skipCount, + bool includeDetails = false, + CancellationToken cancellationToken = default) { - var projects = await (await GetDbSetAsync()).OrderBy(sorting.IsNullOrEmpty() ? "Id desc" : sorting) + var projects = await (await GetDbSetAsync()).IncludeDetails(includeDetails).OrderBy(sorting.IsNullOrEmpty() ? "Id desc" : sorting) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -64,5 +69,10 @@ namespace Volo.Docs.Projects { return shortName.ToLower(); } + + public async override Task> WithDetailsAsync() + { + return (await GetQueryableAsync()).IncludeDetails(); + } } } diff --git a/modules/docs/src/Volo.Docs.HttpApi.Client/ClientProxies/docs-generate-proxy.json b/modules/docs/src/Volo.Docs.HttpApi.Client/ClientProxies/docs-generate-proxy.json index 13e9ebffb2..717e94c04f 100644 --- a/modules/docs/src/Volo.Docs.HttpApi.Client/ClientProxies/docs-generate-proxy.json +++ b/modules/docs/src/Volo.Docs.HttpApi.Client/ClientProxies/docs-generate-proxy.json @@ -4,206 +4,95 @@ "rootPath": "docs", "remoteServiceName": "AbpDocs", "controllers": { - "Volo.Docs.Projects.DocsProjectController": { - "controllerName": "DocsProject", - "controllerGroupName": "Project", + "Volo.Docs.Areas.Documents.DocumentNavigationController": { + "controllerName": "DocumentNavigation", + "controllerGroupName": "DocumentNavigation", "isRemoteService": true, "isIntegrationService": false, "apiVersion": null, - "type": "Volo.Docs.Projects.DocsProjectController", - "interfaces": [ - { - "type": "Volo.Docs.Projects.IProjectAppService", - "name": "IProjectAppService", - "methods": [ - { - "name": "GetListAsync", - "parametersOnMethod": [], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.ListResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" - } - }, - { - "name": "GetAsync", - "parametersOnMethod": [ - { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.Docs.Projects.ProjectDto", - "typeSimple": "Volo.Docs.Projects.ProjectDto" - } - }, - { - "name": "GetVersionsAsync", - "parametersOnMethod": [ - { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.ListResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" - } - }, - { - "name": "GetDefaultLanguageCodeAsync", - "parametersOnMethod": [ - { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, - { - "name": "version", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "System.String", - "typeSimple": "string" - } - }, - { - "name": "GetLanguageListAsync", - "parametersOnMethod": [ - { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - }, - { - "name": "version", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null - } - ], - "returnValue": { - "type": "Volo.Docs.Documents.LanguageConfig", - "typeSimple": "Volo.Docs.Documents.LanguageConfig" - } - } - ] - } - ], + "type": "Volo.Docs.Areas.Documents.DocumentNavigationController", + "interfaces": [], "actions": { - "GetListAsync": { - "uniqueName": "GetListAsync", - "name": "GetListAsync", - "httpMethod": "GET", - "url": "api/docs/projects", - "supportedVersions": [], - "parametersOnMethod": [], - "parameters": [], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.ListResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" - }, - "allowAnonymous": null, - "implementFrom": "Volo.Docs.Projects.IProjectAppService" - }, - "GetAsyncByShortName": { - "uniqueName": "GetAsyncByShortName", - "name": "GetAsync", + "GetNavigationAsyncByInput": { + "uniqueName": "GetNavigationAsyncByInput", + "name": "GetNavigationAsync", "httpMethod": "GET", - "url": "api/docs/projects/{shortName}", + "url": "docs/document-navigation", "supportedVersions": [], "parametersOnMethod": [ { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", + "name": "input", + "typeAsString": "Volo.Docs.Areas.Models.DocumentNavigation.GetNavigationNodeWithLinkModel, Volo.Docs.Web", + "type": "Volo.Docs.Areas.Models.DocumentNavigation.GetNavigationNodeWithLinkModel", + "typeSimple": "Volo.Docs.Areas.Models.DocumentNavigation.GetNavigationNodeWithLinkModel", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "shortName", - "name": "shortName", + "nameOnMethod": "input", + "name": "ProjectId", + "jsonName": null, + "type": "System.Guid", + "typeSimple": "string", + "isOptional": false, + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, + { + "nameOnMethod": "input", + "name": "Version", "jsonName": null, "type": "System.String", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" - } - ], - "returnValue": { - "type": "Volo.Docs.Projects.ProjectDto", - "typeSimple": "Volo.Docs.Projects.ProjectDto" - }, - "allowAnonymous": null, - "implementFrom": "Volo.Docs.Projects.IProjectAppService" - }, - "GetDefaultLanguageCodeAsyncByShortNameAndVersion": { - "uniqueName": "GetDefaultLanguageCodeAsyncByShortNameAndVersion", - "name": "GetDefaultLanguageCodeAsync", - "httpMethod": "GET", - "url": "api/docs/projects/{shortName}/defaultLanguage", - "supportedVersions": [], - "parametersOnMethod": [ + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", + "nameOnMethod": "input", + "name": "LanguageCode", + "jsonName": null, "type": "System.String", "typeSimple": "string", "isOptional": false, - "defaultValue": null + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" }, { - "name": "version", - "typeAsString": "System.String, System.Private.CoreLib", + "nameOnMethod": "input", + "name": "ProjectName", + "jsonName": null, "type": "System.String", "typeSimple": "string", "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { - "nameOnMethod": "shortName", - "name": "shortName", + "nameOnMethod": "input", + "name": "ProjectFormat", "jsonName": null, "type": "System.String", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" }, { - "nameOnMethod": "version", - "name": "version", + "nameOnMethod": "input", + "name": "RouteVersion", "jsonName": null, "type": "System.String", "typeSimple": "string", @@ -211,109 +100,99 @@ "defaultValue": null, "constraintTypes": null, "bindingSourceId": "ModelBinding", - "descriptorName": "" + "descriptorName": "input" } ], "returnValue": { - "type": "System.String", - "typeSimple": "string" + "type": "Volo.Docs.Documents.NavigationNode", + "typeSimple": "Volo.Docs.Documents.NavigationNode" }, "allowAnonymous": null, - "implementFrom": "Volo.Docs.Projects.IProjectAppService" - }, - "GetVersionsAsyncByShortName": { - "uniqueName": "GetVersionsAsyncByShortName", - "name": "GetVersionsAsync", + "implementFrom": "Volo.Docs.Areas.Documents.DocumentNavigationController" + } + } + }, + "Volo.Docs.Areas.Documents.DocumentResourceController": { + "controllerName": "DocumentResource", + "controllerGroupName": "DocumentResource", + "isRemoteService": true, + "isIntegrationService": false, + "apiVersion": null, + "type": "Volo.Docs.Areas.Documents.DocumentResourceController", + "interfaces": [], + "actions": { + "GetResourceByInput": { + "uniqueName": "GetResourceByInput", + "name": "GetResource", "httpMethod": "GET", - "url": "api/docs/projects/{shortName}/versions", + "url": "document-resources", "supportedVersions": [], "parametersOnMethod": [ { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", + "name": "input", + "typeAsString": "Volo.Docs.Documents.GetDocumentResourceInput, Volo.Docs.Application.Contracts", + "type": "Volo.Docs.Documents.GetDocumentResourceInput", + "typeSimple": "Volo.Docs.Documents.GetDocumentResourceInput", "isOptional": false, "defaultValue": null } ], "parameters": [ { - "nameOnMethod": "shortName", - "name": "shortName", + "nameOnMethod": "input", + "name": "ProjectId", "jsonName": null, - "type": "System.String", + "type": "System.Guid", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" - } - ], - "returnValue": { - "type": "Volo.Abp.Application.Dtos.ListResultDto", - "typeSimple": "Volo.Abp.Application.Dtos.ListResultDto" - }, - "allowAnonymous": null, - "implementFrom": "Volo.Docs.Projects.IProjectAppService" - }, - "GetLanguageListAsyncByShortNameAndVersion": { - "uniqueName": "GetLanguageListAsyncByShortNameAndVersion", - "name": "GetLanguageListAsync", - "httpMethod": "GET", - "url": "api/docs/projects/{shortName}/{version}/languageList", - "supportedVersions": [], - "parametersOnMethod": [ - { - "name": "shortName", - "typeAsString": "System.String, System.Private.CoreLib", - "type": "System.String", - "typeSimple": "string", - "isOptional": false, - "defaultValue": null + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" }, { - "name": "version", - "typeAsString": "System.String, System.Private.CoreLib", + "nameOnMethod": "input", + "name": "Name", + "jsonName": null, "type": "System.String", "typeSimple": "string", "isOptional": false, - "defaultValue": null - } - ], - "parameters": [ + "defaultValue": null, + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" + }, { - "nameOnMethod": "shortName", - "name": "shortName", + "nameOnMethod": "input", + "name": "Version", "jsonName": null, "type": "System.String", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" }, { - "nameOnMethod": "version", - "name": "version", + "nameOnMethod": "input", + "name": "LanguageCode", "jsonName": null, "type": "System.String", "typeSimple": "string", "isOptional": false, "defaultValue": null, - "constraintTypes": [], - "bindingSourceId": "Path", - "descriptorName": "" + "constraintTypes": null, + "bindingSourceId": "ModelBinding", + "descriptorName": "input" } ], "returnValue": { - "type": "Volo.Docs.Documents.LanguageConfig", - "typeSimple": "Volo.Docs.Documents.LanguageConfig" + "type": "Microsoft.AspNetCore.Mvc.FileResult", + "typeSimple": "Microsoft.AspNetCore.Mvc.FileResult" }, "allowAnonymous": null, - "implementFrom": "Volo.Docs.Projects.IProjectAppService" + "implementFrom": "Volo.Docs.Areas.Documents.DocumentResourceController" } } }, diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs index af54bd6bc5..95b2ed0244 100644 --- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs +++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Projects/MongoProjectRepository.cs @@ -20,7 +20,12 @@ namespace Volo.Docs.Projects { } - public virtual async Task> GetListAsync(string sorting, int maxResultCount, int skipCount, CancellationToken cancellationToken = default) + public virtual async Task> GetListAsync( + string sorting, + int maxResultCount, + int skipCount, + bool includeDetails = false, + CancellationToken cancellationToken = default) { var projects = await (await GetQueryableAsync(cancellationToken)).OrderBy(sorting.IsNullOrEmpty() ? "Id desc" : sorting).PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); diff --git a/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs b/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs index a4c4c7647e..e0a383e691 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsWebAutoMapperProfile.cs @@ -1,6 +1,4 @@ using AutoMapper; -using Volo.Abp.AutoMapper; -using Volo.Docs.Documents; namespace Volo.Docs { @@ -8,7 +6,6 @@ namespace Volo.Docs { public DocsWebAutoMapperProfile() { - } } } diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentPartialTemplateWithValuesDto.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentPartialTemplateWithValuesDto.cs deleted file mode 100644 index d3ea14921c..0000000000 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentPartialTemplateWithValuesDto.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Collections.Generic; - -namespace Volo.Docs.HtmlConverting -{ - public class DocumentPartialTemplateWithValuesDto - { - public string Path { get; set; } - - public Dictionary Parameters { get; set; } - } -} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentRenderParameters.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentRenderParameters.cs deleted file mode 100644 index 7d9f26832f..0000000000 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentRenderParameters.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Collections.Generic; - -namespace Volo.Docs.HtmlConverting -{ - public class DocumentRenderParameters : Dictionary - { - } -} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentToHtmlConverterContext.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentToHtmlConverterContext.cs new file mode 100644 index 0000000000..53a5c4d631 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentToHtmlConverterContext.cs @@ -0,0 +1,26 @@ +using Volo.Docs.Common.Projects; +using Volo.Docs.Documents; + +namespace Volo.Docs.HtmlConverting; + +public class DocumentToHtmlConverterContext +{ + public ProjectDto Project { get; set; } + public DocumentWithDetailsDto Document { get; set; } + public string Version { get; set; } + public string LanguageCode { get; set; } + public string ProjectShortName { get; set; } + + public DocumentToHtmlConverterContext(ProjectDto project, + DocumentWithDetailsDto document, + string version, + string languageCode, + string projectShortName = null) + { + Project = project; + Document = document; + Version = version; + LanguageCode = languageCode; + ProjectShortName = projectShortName; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentToHtmlConverterOptions.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentToHtmlConverterOptions.cs deleted file mode 100644 index f332f6f58a..0000000000 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/DocumentToHtmlConverterOptions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Volo.Docs.HtmlConverting -{ - public class DocumentToHtmlConverterOptions - { - public Dictionary Converters { get; set; } - - public DocumentToHtmlConverterOptions() - { - Converters = new Dictionary(); - } - } -} diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentSectionRenderer.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentSectionRenderer.cs deleted file mode 100644 index 73560a7273..0000000000 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentSectionRenderer.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; - -namespace Volo.Docs.HtmlConverting -{ - public interface IDocumentSectionRenderer: ITransientDependency - { - Task RenderAsync(string doucment, DocumentRenderParameters parameters = null, List partialTemplates = null); - - Task>> GetAvailableParametersAsync(string document); - - Task> GetPartialTemplatesInDocumentAsync(string documentContent); - - Task GetDocumentNavigationsAsync(string documentContent); - } -} diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverter.cs deleted file mode 100644 index efe145cac2..0000000000 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverter.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Volo.Docs.Documents; -using Volo.Docs.Projects; - -namespace Volo.Docs.HtmlConverting -{ - public interface IDocumentToHtmlConverter - { - string Convert(ProjectDto project, DocumentWithDetailsDto document, string version, string languageCode, string projectShortName = null); - } -} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverterFactory.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverterFactory.cs deleted file mode 100644 index 9cdca43a8f..0000000000 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IDocumentToHtmlConverterFactory.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Volo.Docs.HtmlConverting -{ - public interface IDocumentToHtmlConverterFactory - { - IDocumentToHtmlConverter Create(string format); - } -} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/IWebDocumentSectionRenderer.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/IWebDocumentSectionRenderer.cs new file mode 100644 index 0000000000..b485c7b132 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/HtmlConverting/IWebDocumentSectionRenderer.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Docs.Documents.Rendering; + +namespace Volo.Docs.HtmlConverting +{ + public interface IWebDocumentSectionRenderer: IDocumentSectionRenderer + { + Task> GetPartialTemplatesInDocumentAsync(string documentContent); + + Task GetDocumentNavigationsAsync(string documentContent); + } +} diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs deleted file mode 100644 index e8d0149cf8..0000000000 --- a/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs +++ /dev/null @@ -1,316 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Scriban; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Volo.Abp; -using Volo.Extensions; - -namespace Volo.Docs.HtmlConverting -{ - public class ScribanDocumentSectionRenderer : IDocumentSectionRenderer - { - private readonly static List DocsJsonSections = new List - { - new DocsJsonSection("````json", "````"), - new DocsJsonSection("```json", "```") - }; - private const string DocsParam = "//[doc-params]"; - private const string DocsTemplates = "//[doc-template]"; - private const string DocsNav = "//[doc-nav]"; - - public ILogger Logger { get; set; } - - public ScribanDocumentSectionRenderer() - { - Logger = NullLogger.Instance; - } - - public async Task RenderAsync(string document, DocumentRenderParameters parameters = null, List partialTemplates = null) - { - if (partialTemplates != null && partialTemplates.Any()) - { - document = SetPartialTemplates(document, partialTemplates); - } - - var scribanTemplate = Template.Parse(document); - - if (parameters == null) - { - return await scribanTemplate.RenderAsync(); - } - - var result = await scribanTemplate.RenderAsync(parameters); - - return RemoveOptionsJson(result, DocsParam, DocsNav); - } - - public Task>> GetAvailableParametersAsync(string document) - { - return GetSectionAsync>>(document, DocsParam); - } - - public Task GetDocumentNavigationsAsync(string documentContent) - { - return GetSectionAsync(documentContent, DocsNav); - } - - protected virtual async Task GetSectionAsync(string document, string sectionName) where T : new() - { - try - { - if (!HasJsonSection(document) || !document.Contains(sectionName)) - { - return new T(); - } - - var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection, _) = GetJsonBeginEndIndexesAndPureJson(document, sectionName); - - if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection)) - { - return new T(); - } - - var pureJson = insideJsonSection.Replace(sectionName, "").Trim(); - - if (!DocsJsonSerializerHelper.TryDeserialize(pureJson, out var section)) - { - throw new UserFriendlyException($"ERROR-20200327: Cannot validate JSON content for `{sectionName}`!"); - } - - return await Task.FromResult(section); - } - catch (Exception) - { - Logger.LogWarning("Unable to parse parameters of document."); - return new T(); - } - } - - private static string RemoveOptionsJson(string document, params string[] sectionNames) - { - - foreach (var sectionName in sectionNames) - { - var orgDocument = document; - - try - { - if (!HasJsonSection(document) || !document.Contains(sectionName)) - { - continue; - } - - var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection, jsonSection) = GetJsonBeginEndIndexesAndPureJson(document, sectionName); - - if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection)) - { - continue; - } - - document = document.Remove( - jsonBeginningIndex - jsonSection.Opener.Length, - (jsonEndingIndex + jsonSection.Closer.Length) - (jsonBeginningIndex - jsonSection.Opener.Length) - ); - } - catch (Exception) - { - document = orgDocument; - } - } - - return document; - } - - private static bool HasJsonSection(string document) - { - return DocsJsonSections.Any(section => document.Contains(section.Opener) && document.Contains(section.Closer)); - } - - private static (int, int, string, DocsJsonSection) GetJsonBeginEndIndexesAndPureJson(string document, string sectionName) - { - foreach (var section in DocsJsonSections) - { - var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection) = section.GetJsonBeginEndIndexesAndPureJson(document, sectionName); - - if (jsonBeginningIndex >= 0 && jsonEndingIndex > 0 && !string.IsNullOrWhiteSpace(insideJsonSection)) - { - return (jsonBeginningIndex, jsonEndingIndex, insideJsonSection, section); - } - } - - return (-1, -1, "", null); - } - - public async Task> GetPartialTemplatesInDocumentAsync(string documentContent) - { - var templates = new List(); - - foreach (var section in DocsJsonSections) - { - templates.AddRange(await section.GetPartialTemplatesInDocumentAsync(documentContent)); - } - - return templates; - } - - private static string SetPartialTemplates(string document, IReadOnlyCollection templates) - { - foreach (var section in DocsJsonSections) - { - document = section.SetPartialTemplates(document, templates); - } - - return document; - } - - private class DocsJsonSection - { - public string Opener { get; } - public string Closer { get; } - - public DocsJsonSection(string opener, string closer) - { - Opener = opener; - Closer = closer; - } - - public (int, int, string) GetJsonBeginEndIndexesAndPureJson(string document, string sectionName) - { - var searchedIndex = 0; - - while (searchedIndex < document.Length) - { - var jsonBeginningIndex = document.Substring(searchedIndex).IndexOf(Opener, StringComparison.Ordinal); - - if (jsonBeginningIndex < 0) - { - return (-1, -1, ""); - } - - jsonBeginningIndex += Opener.Length + searchedIndex; - - var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(Closer, StringComparison.Ordinal); - if (jsonEndingIndex < 0) - { - return (-1, -1, ""); - } - - jsonEndingIndex += jsonBeginningIndex; - var insideJsonSection = document[jsonBeginningIndex..jsonEndingIndex]; - - if (insideJsonSection.IndexOf(sectionName, StringComparison.Ordinal) < 0) - { - searchedIndex = jsonEndingIndex + Closer.Length; - continue; - } - - return (jsonBeginningIndex, jsonEndingIndex, insideJsonSection); - } - - return (-1, -1, ""); - } - - public async Task> GetPartialTemplatesInDocumentAsync( - string documentContent) - { - var templates = new List(); - - while (documentContent.Contains(Opener)) - { - var afterJsonOpener = documentContent.Substring( - documentContent.IndexOf(Opener, StringComparison.Ordinal) + Opener.Length - ); - - var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0, - afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) - ); - - documentContent = afterJsonOpener.Substring( - afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) + Closer.Length - ); - - if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates)) - { - continue; - } - - var json = betweenJsonOpenerAndCloser.Substring( - betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + - DocsTemplates.Length); - - if (!DocsJsonSerializerHelper.TryDeserialize(json, - out var template)) - { - throw new UserFriendlyException( - $"ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!"); - } - - templates.Add(template); - } - - return await Task.FromResult(templates); - } - - public string SetPartialTemplates(string document, - IReadOnlyCollection templates) - { - var newDocument = new StringBuilder(); - - while (document.Contains(Opener)) - { - var beforeJson = document.Substring(0, - document.IndexOf(Opener, StringComparison.Ordinal) + Opener.Length - ); - - var afterJsonOpener = document.Substring( - document.IndexOf(Opener, StringComparison.Ordinal) + Opener.Length - ); - - var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0, - afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) - ); - - if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates)) - { - document = afterJsonOpener.Substring( - afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) + Closer.Length - ); - - newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + Closer); - continue; - } - - var json = betweenJsonOpenerAndCloser.Substring( - betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + - DocsTemplates.Length - ); - - if (DocsJsonSerializerHelper.TryDeserialize(json, - out var documentPartialTemplateWithValuesDto)) - { - var template = - templates.FirstOrDefault(t => t.Path == documentPartialTemplateWithValuesDto.Path); - - var beforeTemplate = document.Substring(0, - document.IndexOf(Opener, StringComparison.Ordinal) - ); - - newDocument.Append(beforeTemplate + template?.Content + Closer); - - document = afterJsonOpener.Substring( - afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) + Closer.Length - ); - } - } - - newDocument.Append(document); - - return newDocument.ToString(); - } - } - } -} diff --git a/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanWebDocumentSectionRenderer.cs b/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanWebDocumentSectionRenderer.cs new file mode 100644 index 0000000000..e4a26b2df6 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanWebDocumentSectionRenderer.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Scriban; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp; +using Volo.Abp.ObjectMapping; +using Volo.Docs.Documents.Rendering; +using Volo.Extensions; + +namespace Volo.Docs.HtmlConverting +{ + public class ScribanWebDocumentSectionRenderer : ScribanDocumentSectionRenderer, IWebDocumentSectionRenderer + { + private IObjectMapper ObjectMapper { get; set; } + + public Task GetDocumentNavigationsAsync(string documentContent) + { + return GetSectionAsync(documentContent, DocsNav); + } + + public async Task> GetPartialTemplatesInDocumentAsync( + string documentContent) + { + var templates = new List(); + + foreach (var section in DocsJsonSections) + { + templates.AddRange(await section.GetPartialTemplatesInDocumentAsync(documentContent)); + } + + return templates; + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs index 55a9eacb37..54df0c4440 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs @@ -1,20 +1,16 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Net; using System.Text.RegularExpressions; -using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; +using Volo.Docs.Common.Projects; using Volo.Docs.Documents; using Volo.Docs.HtmlConverting; -using Volo.Docs.Pages.Documents.Project; -using Volo.Docs.Projects; using Volo.Docs.Utils; namespace Volo.Docs.Markdown { - public class MarkdownDocumentToHtmlConverter : IDocumentToHtmlConverter, ITransientDependency + public class MarkdownDocumentToHtmlConverter : IDocumentToHtmlConverter, ITransientDependency { public const string Type = "md"; @@ -34,20 +30,19 @@ namespace Volo.Docs.Markdown private const string MarkdownLinkRegExp = @"\[(.*?)\]\(((.*?)(\?(.*?))*?)\)"; private const string AnchorLinkRegExp = @"]+href=\""(.*?)\""[^>]*>(.*)?"; - public virtual string Convert(ProjectDto project, DocumentWithDetailsDto document, string version, - string languageCode, string projectShortName = null) + public virtual string Convert(DocumentToHtmlConverterContext context) { - if (document.Content.IsNullOrEmpty()) + if (context.Document.Content.IsNullOrEmpty()) { - return document.Content; + return context.Document.Content; } var content = NormalizeLinks( - document.Content, - _uiOptions.SingleProjectMode.Enable ? projectShortName : projectShortName ?? project.ShortName, - version, - document.LocalDirectory, - !_uiOptions.MultiLanguageMode ? languageCode : languageCode ?? document.LanguageCode + context.Document.Content, + _uiOptions.SingleProjectMode.Enable ? context.ProjectShortName : context.ProjectShortName ?? context.Project.ShortName, + context.Version, + context.Document.LocalDirectory, + !_uiOptions.MultiLanguageMode ? context.LanguageCode : context.LanguageCode ?? context.Document.LanguageCode ); var html = _markdownConverter.ConvertToHtml(content); diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs index 59f66f7b82..baa440dccd 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Options; -using Volo.Docs.Projects; +using Volo.Docs.Common.Projects; namespace Volo.Docs.Pages.Documents { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index fb1f232cb3..e6a6f8470a 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -71,6 +71,7 @@ + @@ -290,6 +291,14 @@ id="sidebar-scroll" class="nav nav-list"> + @if (Model.HasDownloadPdfPermission) + { + + } } diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 2bb7c82c21..471747fac1 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -10,15 +10,17 @@ using System.Web; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Volo.Abp.Application.Dtos; using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Authorization.Permissions; using Volo.Abp.Data; using Volo.Abp.Domain.Entities; using Volo.Abp.EventBus.Local; +using Volo.Docs.Common; +using Volo.Docs.Common.Projects; using Volo.Docs.Documents; +using Volo.Docs.Documents.Rendering; using Volo.Docs.HtmlConverting; using Volo.Docs.Models; using Volo.Docs.Projects; @@ -89,6 +91,8 @@ namespace Volo.Docs.Pages.Documents.Project public bool FullSearchEnabled { get; set; } public bool IsLatestVersion { get; private set; } + + public bool HasDownloadPdfPermission { get; set; } public DocumentNavigationsDto DocumentNavigationsDto { get; private set; } @@ -96,8 +100,9 @@ namespace Volo.Docs.Pages.Documents.Project private readonly IDocumentAppService _documentAppService; private readonly IDocumentToHtmlConverterFactory _documentToHtmlConverterFactory; private readonly IProjectAppService _projectAppService; - private readonly IDocumentSectionRenderer _documentSectionRenderer; + private readonly IWebDocumentSectionRenderer _webDocumentSectionRenderer; private readonly DocsUiOptions _uiOptions; + private readonly IPermissionChecker _permissionChecker; protected IDocsLinkGenerator DocsLinkGenerator => LazyServiceProvider.LazyGetRequiredService(); @@ -108,17 +113,18 @@ namespace Volo.Docs.Pages.Documents.Project IDocumentToHtmlConverterFactory documentToHtmlConverterFactory, IProjectAppService projectAppService, IOptions options, - IDocumentSectionRenderer documentSectionRenderer) + IWebDocumentSectionRenderer webDocumentSectionRenderer, + IPermissionChecker permissionChecker) { ObjectMapperContext = typeof(DocsWebModule); _documentAppService = documentAppService; _documentToHtmlConverterFactory = documentToHtmlConverterFactory; _projectAppService = projectAppService; - _documentSectionRenderer = documentSectionRenderer; + _webDocumentSectionRenderer = webDocumentSectionRenderer; + _permissionChecker = permissionChecker; _uiOptions = options.Value; - - + LocalizationResourceType = typeof(DocsResource); } @@ -136,7 +142,7 @@ namespace Volo.Docs.Pages.Documents.Project { return RedirectPermanent(redirectUrl); } - + return await SetPageAsync(); } @@ -146,7 +152,7 @@ namespace Volo.Docs.Pages.Documents.Project ShowProjectsCombobox = _uiOptions.ShowProjectsCombobox && !_uiOptions.SingleProjectMode.Enable; ShowProjectsComboboxLabel = ShowProjectsCombobox && _uiOptions.ShowProjectsComboboxLabel; FullSearchEnabled = await _documentAppService.FullSearchEnabledAsync(); - + HasDownloadPdfPermission = await _permissionChecker.IsGrantedAsync(DocsCommonPermissions.Projects.PdfGeneration); try { await SetProjectAsync(); @@ -561,11 +567,11 @@ namespace Volo.Docs.Pages.Documents.Project var partialTemplates = await GetDocumentPartialTemplatesAsync(); - DocumentNavigationsDto = await _documentSectionRenderer.GetDocumentNavigationsAsync(Document.Content); + DocumentNavigationsDto = await _webDocumentSectionRenderer.GetDocumentNavigationsAsync(Document.Content); try { - Document.Content = await _documentSectionRenderer.RenderAsync(Document.Content, UserPreferences, partialTemplates); + Document.Content = await _webDocumentSectionRenderer.RenderAsync(Document.Content, UserPreferences, partialTemplates); } catch (Exception e) { @@ -577,8 +583,8 @@ namespace Volo.Docs.Pages.Documents.Project DocumentNavigationsDto = new DocumentNavigationsDto(); } - var converter = _documentToHtmlConverterFactory.Create(Document.Format ?? Project.Format); - var content = converter.Convert(Project, Document, GetSpecificVersionOrLatest(), LanguageCode, ProjectName); + var converter = _documentToHtmlConverterFactory.Create(Document.Format ?? Project.Format); + var content = converter.Convert(new DocumentToHtmlConverterContext(Project, Document, GetSpecificVersionOrLatest(), LanguageCode, ProjectName)); content = HtmlNormalizer.ReplaceImageSources( content, @@ -619,7 +625,7 @@ namespace Volo.Docs.Pages.Documents.Project private async Task> GetDocumentPartialTemplatesAsync() { - var partialTemplatesInDocument = await _documentSectionRenderer.GetPartialTemplatesInDocumentAsync(Document.Content); + var partialTemplatesInDocument = await _webDocumentSectionRenderer.GetPartialTemplatesInDocumentAsync(Document.Content); if (!partialTemplatesInDocument?.Any(t => t.Parameters != null) ?? true) { @@ -772,7 +778,7 @@ namespace Volo.Docs.Pages.Documents.Project return; } - var availableParameters = await _documentSectionRenderer.GetAvailableParametersAsync(Document.Content); + var availableParameters = await _webDocumentSectionRenderer.GetAvailableParametersAsync(Document.Content); DocumentPreferences = new DocumentParametersDto { @@ -813,7 +819,7 @@ namespace Volo.Docs.Pages.Documents.Project { if (!DocumentPreferences?.Parameters?.Any() ?? true) { - return; + return; } AlternativeOptionLinkQueries = CollectAlternativeOptionLinksRecursively(); diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css index e8d0a035a0..dc720fba6d 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css @@ -45,4 +45,18 @@ body { outline: none; } +.docs-sidebar-footer { + border-block-start: 1px solid #aaa; + border-block-end: 1px solid #aaa; +} + +.download-pdf-btn { + text-align: left; + width: 100%; + color: #aaa; + background-color: #0000; + border-color:#0000; + font-size: 14px; +} + /*# sourceMappingURL=Index.css.map */ diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss index 426dec284c..9589b1fb73 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss @@ -6,9 +6,9 @@ } } -.input-group{ - .input-group-text{ - background-color: transparent!important; +.input-group { + .input-group-text { + background-color: transparent !important; } } @@ -16,10 +16,12 @@ .next-link, .prev-link { .desc { color: #0D6EFD; - .fa{ + + .fa { font-size: 12px; } } + .title { font-weight: 600; font-size: 18px; @@ -27,3 +29,46 @@ } } } + +body { + top: 0px !important; +} + +.skiptranslate { + iframe { + display: none !important; + } +} + +.google_translate_text { + color: #aaa; + font-family: var(--bs-body-font-family); + font-size: 10pt; + margin-left: 2px; + font-weight: 500; +} + +.goog-te-gadget { + white-space: break-spaces !important; +} + +.goog-te-combo { + &:focus-visible { + border: 0px; + outline: none; + } +} + +.docs-sidebar-footer { + border-block-start: 1px solid #aaa; + border-block-end: 1px solid #aaa; +} + +.download-pdf-btn { + text-align: left; + width: 100%; + color: #aaa; + background-color: transparent; + border-color: transparent; + font-size: 14px; +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs index 7be35394ae..ad60019b57 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs @@ -3,18 +3,15 @@ using System.Collections.Generic; using System.Linq; using System.Text.Encodings.Web; using System.Threading.Tasks; -using System.Web; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Options; using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination; using Volo.Abp.Data; +using Volo.Docs.Common.Projects; using Volo.Docs.Documents; using Volo.Docs.GitHub.Documents.Version; -using Volo.Docs.HtmlConverting; -using Volo.Docs.Models; using Volo.Docs.Projects; -using Volo.Docs.Utils; namespace Volo.Docs.Pages.Documents { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css index 32017cd466..36ca24e100 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css @@ -219,7 +219,7 @@ body.scrolledMore .alert-criteria p.alert-p { } .docs-page .docs-sidebar .docs-tree-list > ul { display: block; - height: calc(100vh - 310px); + height: calc(100vh - 350px); overflow-y: auto; margin-right: -4px !important; margin-top: 20px !important; diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss index 6c2c4c7627..deba3d39c3 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss @@ -268,7 +268,7 @@ body { > ul { display: block; - height: calc(100vh - 310px); + height: calc(100vh - 350px); overflow-y: auto; margin-right: -4px !important; margin-top: 20px !important; diff --git a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj index 1d6e0e1ace..2c36600107 100644 --- a/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj +++ b/modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj @@ -23,7 +23,7 @@ - + diff --git a/modules/docs/src/Volo.Docs.Web/wwwroot/client-proxies/docs-common-proxy.js b/modules/docs/src/Volo.Docs.Web/wwwroot/client-proxies/docs-common-proxy.js new file mode 100644 index 0000000000..014e357cba --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/wwwroot/client-proxies/docs-common-proxy.js @@ -0,0 +1,68 @@ +/* This file is automatically generated by ABP framework to use MVC Controllers from javascript. */ + + +// module docs-common + +(function(){ + + // controller volo.docs.documents.docsDocumentPdfGenerator + + (function(){ + + abp.utils.createNamespace(window, 'volo.docs.documents.docsDocumentPdfGenerator'); + + volo.docs.documents.docsDocumentPdfGenerator.generatePdf = function(input, ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/docs/documents/pdf' + abp.utils.buildQueryString([{ name: 'projectId', value: input.projectId }, { name: 'version', value: input.version }, { name: 'languageCode', value: input.languageCode }]) + '', + type: 'GET' + }, ajaxParams)); + }; + + })(); + + // controller volo.docs.projects.docsProject + + (function(){ + + abp.utils.createNamespace(window, 'volo.docs.projects.docsProject'); + + volo.docs.projects.docsProject.getList = function(ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/docs/projects', + type: 'GET' + }, ajaxParams)); + }; + + volo.docs.projects.docsProject.get = function(shortName, ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/docs/projects/' + shortName + '', + type: 'GET' + }, ajaxParams)); + }; + + volo.docs.projects.docsProject.getDefaultLanguageCode = function(shortName, version, ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/docs/projects/' + shortName + '/defaultLanguage' + abp.utils.buildQueryString([{ name: 'version', value: version }]) + '', + type: 'GET' + }, { dataType: 'text' }, ajaxParams)); + }; + + volo.docs.projects.docsProject.getVersions = function(shortName, ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/docs/projects/' + shortName + '/versions', + type: 'GET' + }, ajaxParams)); + }; + + volo.docs.projects.docsProject.getLanguageList = function(shortName, version, ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/docs/projects/' + shortName + '/' + version + '/languageList', + type: 'GET' + }, ajaxParams)); + }; + + })(); + +})(); + + diff --git a/modules/docs/src/Volo.Docs.Web/wwwroot/client-proxies/docs-proxy.js b/modules/docs/src/Volo.Docs.Web/wwwroot/client-proxies/docs-proxy.js index 3195d15cd6..32bcf101cb 100644 --- a/modules/docs/src/Volo.Docs.Web/wwwroot/client-proxies/docs-proxy.js +++ b/modules/docs/src/Volo.Docs.Web/wwwroot/client-proxies/docs-proxy.js @@ -5,43 +5,30 @@ (function(){ - // controller volo.docs.projects.docsProject + // controller volo.docs.areas.documents.documentNavigation (function(){ - abp.utils.createNamespace(window, 'volo.docs.projects.docsProject'); + abp.utils.createNamespace(window, 'volo.docs.areas.documents.documentNavigation'); - volo.docs.projects.docsProject.getList = function(ajaxParams) { + volo.docs.areas.documents.documentNavigation.getNavigation = function(input, ajaxParams) { return abp.ajax($.extend(true, { - url: abp.appPath + 'api/docs/projects', + url: abp.appPath + 'docs/document-navigation' + abp.utils.buildQueryString([{ name: 'projectId', value: input.projectId }, { name: 'version', value: input.version }, { name: 'languageCode', value: input.languageCode }, { name: 'projectName', value: input.projectName }, { name: 'projectFormat', value: input.projectFormat }, { name: 'routeVersion', value: input.routeVersion }]) + '', type: 'GET' }, ajaxParams)); }; - volo.docs.projects.docsProject.get = function(shortName, ajaxParams) { - return abp.ajax($.extend(true, { - url: abp.appPath + 'api/docs/projects/' + shortName + '', - type: 'GET' - }, ajaxParams)); - }; + })(); - volo.docs.projects.docsProject.getDefaultLanguageCode = function(shortName, version, ajaxParams) { - return abp.ajax($.extend(true, { - url: abp.appPath + 'api/docs/projects/' + shortName + '/defaultLanguage' + abp.utils.buildQueryString([{ name: 'version', value: version }]) + '', - type: 'GET' - }, { dataType: 'text' }, ajaxParams)); - }; + // controller volo.docs.areas.documents.documentResource - volo.docs.projects.docsProject.getVersions = function(shortName, ajaxParams) { - return abp.ajax($.extend(true, { - url: abp.appPath + 'api/docs/projects/' + shortName + '/versions', - type: 'GET' - }, ajaxParams)); - }; + (function(){ + + abp.utils.createNamespace(window, 'volo.docs.areas.documents.documentResource'); - volo.docs.projects.docsProject.getLanguageList = function(shortName, version, ajaxParams) { + volo.docs.areas.documents.documentResource.getResource = function(input, ajaxParams) { return abp.ajax($.extend(true, { - url: abp.appPath + 'api/docs/projects/' + shortName + '/' + version + '/languageList', + url: abp.appPath + 'document-resources' + abp.utils.buildQueryString([{ name: 'projectId', value: input.projectId }, { name: 'name', value: input.name }, { name: 'version', value: input.version }, { name: 'languageCode', value: input.languageCode }]) + '', type: 'GET' }, ajaxParams)); }; diff --git a/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs index 8f92c414c1..662db4c6aa 100644 --- a/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs +++ b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using Shouldly; -using Volo.Docs.Projects; +using Volo.Docs.Common.Projects; using Xunit; namespace Volo.Docs diff --git a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj index 90df72d01d..2087f2118c 100644 --- a/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj +++ b/modules/docs/test/Volo.Docs.MongoDB.Tests/Volo.Docs.MongoDB.Tests.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor index 77f5018e10..a55e1cb026 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor @@ -17,12 +17,14 @@ - @foreach (var group in Groups) - { - - @group.DisplayName - - } +
+ @foreach (var group in Groups) + { + + @group.DisplayName + + } +
@for (var i = 0; i < Groups.Count; i++) @@ -35,12 +37,12 @@ {
@{ - var disabled = IsDisabled(feature.Provider.Name); + var disabled = IsDisabled(feature); if (feature.ValueType is FreeTextStringValueType) { - @feature.DisplayName + @GetShownName(feature) @@ -56,8 +58,8 @@ var items = ((SelectionStringValueType)feature.ValueType).ItemSource.Items; var selectedValue = SelectionStringValues[feature.Name]; - @feature.DisplayName - @foreach (var item in items) { @@ -75,8 +77,8 @@ if (feature.ValueType is ToggleStringValueType) { - - @feature.DisplayName + + @GetShownName(feature) @if (feature.Description != null) { diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs index 0d0728db71..8a48db4b4a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs @@ -150,9 +150,19 @@ public partial class FeatureManagementModal return $"margin-left: {feature.Depth * 20}px"; } - protected virtual bool IsDisabled(string providerName) + protected virtual bool IsDisabled(FeatureDto feature) { - return providerName != ProviderName && providerName != DefaultValueFeatureValueProvider.ProviderName; + return feature.Value != null && + feature.Provider.Name != null && + feature.Provider.Name != ProviderName && + feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName; + } + + public virtual string GetShownName(FeatureDto featureDto) + { + return !IsDisabled(featureDto) + ? featureDto.DisplayName + : $"{featureDto.DisplayName} ({featureDto.Provider.Name})"; } protected virtual async Task OnFeatureValueChangedAsync(string value, FeatureDto feature) diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs index 9805f03752..c105779546 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/FeatureManager.cs @@ -152,7 +152,7 @@ public class FeatureManager : IFeatureManager, ISingletonDependency await using (await providers[0].HandleContextAsync(providerName, providerKey)) { var fallbackValue = await GetOrNullInternalAsync(name, providers[1].Name, null); - if (fallbackValue.Value == value) + if (string.Equals(fallbackValue.Value, value, StringComparison.OrdinalIgnoreCase)) { //Clear the value if it's same as it's fallback value value = null; diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/AngularInstallationInfo.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/AngularInstallationInfo.json new file mode 100644 index 0000000000..5f842bab58 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/AngularInstallationInfo.json @@ -0,0 +1,40 @@ +{ + "packages":[ + { + "name": "@abp/ng.feature-management", + "appRoutingModuleConfiguration":{ + "routes":[ + ] + }, + "appModuleConfiguration":{ + "imports":[ + { + "names":[ + "provideFeatureManagementConfig" + ], + "namespace": "@abp/ng.feature-management" + } + ], + "ngModuleImports":[ + ], + "providerNames":[ + "provideFeatureManagementConfig()" + ] + }, + "tsJsonPathRecordConfigurations":[ + { + "name": "@abp/ng.feature-management", + "paths": [ + "angular/projects/feature-management/src/public-api.ts" + ] + }, + { + "name": "@abp/ng.feature-management/proxy", + "paths": [ + "angular/projects/feature-management/proxy/src/public-api.ts" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/Volo.Abp.FeatureManagement.Installer.csproj b/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/Volo.Abp.FeatureManagement.Installer.csproj index ec1b57ffa1..7f9479e7ab 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/Volo.Abp.FeatureManagement.Installer.csproj +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Installer/Volo.Abp.FeatureManagement.Installer.csproj @@ -25,6 +25,8 @@ true content\ + + diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml index 9c3ceca88f..f9823e0e58 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml @@ -21,6 +21,7 @@ } + @@ -39,49 +40,45 @@

@featureGroup.DisplayName


-
+
@for (var j = 0; j < featureGroup.Features.Count; j++) { var feature = featureGroup.Features[j]; + var disabled = Model.IsDisabled(feature);
+ - @if (feature.ValueType is ToggleStringValueType) { - - @if (feature.Description != null) + type="checkbox" + class="d-inline" + abp-id-name="@Model.FeatureGroups[i].Features[j].BoolValue" + label="@Model.GetShownName(feature)" + disabled="disabled" + group-data-feature-name="@feature.Name" + group-data-parent-name="@(feature.ParentName ?? "")" + group-style="margin-inline-start: @(feature.Depth * 20)px"/> + if (feature.Description != null) {
@feature.Description
} - } @if (feature.ValueType is FreeTextStringValueType) { - var type = "text"; - if(feature.ValueType.Validator is NumericValueValidator) - { - type = "number"; - } - + var type = feature.ValueType.Validator is NumericValueValidator ? "number" : "text"; - @if (feature.Description != null) + label="@Model.GetShownName(feature)" + abp-id-name="@Model.FeatureGroups[i].Features[j].Value" + type="@type" + disabled="disabled" + group-data-feature-name="@feature.Name" + group-data-parent-name="@(feature.ParentName ?? "")" + group-style="margin-inline-start: @(feature.Depth * 25)px"/> + if (feature.Description != null) {
@feature.Description
} @@ -90,19 +87,12 @@ @if (feature.ValueType is SelectionStringValueType selectType) {
- - - @foreach (var item in selectType.ItemSource.Items) { - if (item.Value == feature.Value) - { - - } - else - { - - } + var selected = item.Value == feature.Value ? "selected=\"selected\"" : ""; + @CreateHtmlLocalizer(item.DisplayText.ResourceName).GetString(item.DisplayText.Name) } @if (feature.Description != null) @@ -111,8 +101,8 @@ }
} - +
}
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs index f08d42cfd2..eb27c63aae 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs @@ -25,9 +25,9 @@ public class FeatureManagementModal : AbpPageModel [HiddenInput] [BindProperty(SupportsGet = true)] public string ProviderKey { get; set; } - + [HiddenInput] - [BindProperty(SupportsGet = true)] + [BindProperty(SupportsGet = true)] public string ProviderKeyDisplayName { get; set; } [BindProperty] @@ -69,7 +69,7 @@ public class FeatureManagementModal : AbpPageModel { var features = new UpdateFeaturesDto { - Features = FeatureGroups.SelectMany(g => g.Features).Select(f => new UpdateFeatureDto + Features = FeatureGroups.SelectMany(g => g.Features).Where(x => !x.IsDisabled).Select(f => new UpdateFeatureDto { Name = f.Name, Value = f.Type == nameof(ToggleStringValueType) ? f.BoolValue.ToString() : f.Value @@ -85,6 +85,21 @@ public class FeatureManagementModal : AbpPageModel return NoContent(); } + public virtual bool IsDisabled(FeatureDto feature) + { + return feature.Value != null && + feature.Provider.Name != null && + feature.Provider.Name != ProviderName && + feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName; + } + + public virtual string GetShownName(FeatureDto featureDto) + { + return !IsDisabled(featureDto) + ? featureDto.DisplayName + : $"{featureDto.DisplayName} ({featureDto.Provider.Name})"; + } + public class FeatureGroupViewModel { public List Features { get; set; } @@ -92,6 +107,8 @@ public class FeatureManagementModal : AbpPageModel public class FeatureViewModel { + public bool IsDisabled { get; set; } + public string Name { get; set; } public string Value { get; set; } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/feature-management-modal.css b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/feature-management-modal.css new file mode 100644 index 0000000000..921a40b160 --- /dev/null +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/feature-management-modal.css @@ -0,0 +1,11 @@ +#FeaturesTabsContent { + padding-top: 0 !important; +} + +.custom-scroll-content { + max-height: 400px; +} + +.custom-scroll-container > .col-md-4 { + max-height: 500px; +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/feature-management-modal.js b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/feature-management-modal.js index fd9c654ae6..5595db7a47 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/feature-management-modal.js +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/feature-management-modal.js @@ -88,7 +88,7 @@ var abp = abp || {}; $('.custom-scroll-content').mCustomScrollbar({ theme: 'minimal-dark', }); - $('.custom-scroll-container > .col-4').mCustomScrollbar({ + $('.custom-scroll-container > .col-md-4').mCustomScrollbar({ theme: 'minimal-dark', }); }); diff --git a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj index 2f7f5ee7d0..d11f989f7d 100644 --- a/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj +++ b/modules/feature-management/test/Volo.Abp.FeatureManagement.MongoDB.Tests/Volo.Abp.FeatureManagement.MongoDB.Tests.csproj @@ -15,9 +15,9 @@ - - - + + + diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs index a56935424e..582d9ade42 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; @@ -58,7 +59,7 @@ public class IdentityUserAppService : IdentityAppServiceBase, IIdentityUserAppSe { //TODO: Should also include roles of the related OUs. - var roles = await UserRepository.GetRolesAsync(id); + var roles = (await UserRepository.GetRolesAsync(id)).OrderBy(x => x.Name).ToList(); return new ListResultDto( ObjectMapper.Map, List>(roles) @@ -68,9 +69,8 @@ public class IdentityUserAppService : IdentityAppServiceBase, IIdentityUserAppSe [Authorize(IdentityPermissions.Users.Default)] public virtual async Task> GetAssignableRolesAsync() { - var list = await RoleRepository.GetListAsync(); - return new ListResultDto( - ObjectMapper.Map, List>(list)); + var list = (await RoleRepository.GetListAsync()).OrderBy(x => x.Name).ToList(); + return new ListResultDto(ObjectMapper.Map, List>(list)); } [Authorize(IdentityPermissions.Users.Create)] diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json index 91b231665e..5f1e56d02d 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo.Abp.Identity.Domain.abppkg.analyze.json @@ -2747,6 +2747,45 @@ } ] }, + { + "returnType": "IdentityResult", + "namespace": "Volo.Abp.Identity", + "name": "CallValidateUserAsync", + "summary": null, + "isAsync": true, + "isPublic": true, + "isPrivate": false, + "isStatic": false, + "parameters": [ + { + "type": "IdentityUser", + "name": "user", + "isOptional": false + } + ] + }, + { + "returnType": "IdentityResult", + "namespace": "Volo.Abp.Identity", + "name": "CallValidatePasswordAsync", + "summary": null, + "isAsync": true, + "isPublic": true, + "isPrivate": false, + "isStatic": false, + "parameters": [ + { + "type": "IdentityUser", + "name": "user", + "isOptional": false + }, + { + "type": "String", + "name": "password", + "isOptional": false + } + ] + }, { "returnType": "IdentityUser", "namespace": "Volo.Abp.Identity", @@ -5029,6 +5068,11 @@ "name": "organizationUnitId", "isOptional": true }, + { + "type": "Nullable", + "name": "id", + "isOptional": true + }, { "type": "String", "name": "userName", @@ -5246,6 +5290,11 @@ "name": "organizationUnitId", "isOptional": true }, + { + "type": "Nullable", + "name": "id", + "isOptional": true + }, { "type": "String", "name": "userName", @@ -5920,6 +5969,11 @@ "name": "filter", "isOptional": true }, + { + "type": "Boolean", + "name": "includeChildren", + "isOptional": true + }, { "type": "Boolean", "name": "includeDetails", @@ -5947,6 +6001,11 @@ "name": "id", "isOptional": false }, + { + "type": "Boolean", + "name": "includeChildren", + "isOptional": true + }, { "type": "CancellationToken", "name": "cancellationToken", @@ -5974,6 +6033,11 @@ "name": "filter", "isOptional": true }, + { + "type": "Boolean", + "name": "includeChildren", + "isOptional": true + }, { "type": "CancellationToken", "name": "cancellationToken", @@ -6286,8 +6350,8 @@ }, { "defaultValue": "False", - "displayName": "Require confirmed email", - "description": "Whether a confirmed email address is required to sign in.", + "displayName": "Enforce email verification to sign in", + "description": "Users can create accounts but cannot sign in until they verify their email address.", "isVisibleToClient": true, "isInherited": true, "isEncrypted": false, @@ -6298,7 +6362,7 @@ { "defaultValue": "True", "displayName": "Allow users to confirm their phone number", - "description": "Whether the phoneNumber can be confirmed by the user.", + "description": "Users can verify their phone numbers. SMS integration required.", "isVisibleToClient": true, "isInherited": true, "isEncrypted": false, @@ -6308,8 +6372,19 @@ }, { "defaultValue": "False", - "displayName": "Require confirmed phone number", - "description": "Whether a confirmed telephone number is required to sign in.", + "displayName": "Enforce email verification to register", + "description": "User accounts will not be created unless they verify their email addresses.", + "isVisibleToClient": false, + "isInherited": true, + "isEncrypted": false, + "contentType": "setting", + "name": "Abp.Identity.SignIn.RequireEmailVerificationToRegister", + "summary": null + }, + { + "defaultValue": "False", + "displayName": "Enforce phone number verification to sign in", + "description": "Users can create accounts but cannot sign in until they verify their phone numbers.", "isVisibleToClient": true, "isInherited": true, "isEncrypted": false, diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs index 6051914adc..c0b5023386 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityDynamicClaimsPrincipalContributorCache.cs @@ -58,9 +58,9 @@ public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependen return emptyCacheItem; } - return await DynamicClaimCache.GetOrAddAsync(AbpDynamicClaimCacheItem.CalculateCacheKey(userId, tenantId), async () => + using (CurrentTenant.Change(tenantId)) { - using (CurrentTenant.Change(tenantId)) + return await DynamicClaimCache.GetOrAddAsync(AbpDynamicClaimCacheItem.CalculateCacheKey(userId, tenantId), async () => { Logger.LogDebug($"Filling dynamic claims cache for user: {userId}"); @@ -82,11 +82,11 @@ public class IdentityDynamicClaimsPrincipalContributorCache : ITransientDependen } return dynamicClaims; - } - }, () => new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = CacheOptions.Value.CacheAbsoluteExpiration - }); + }, () => new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = CacheOptions.Value.CacheAbsoluteExpiration + }); + } } public virtual async Task ClearAsync(Guid userId, Guid? tenantId = null) diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj index 311ee9fa69..f764dc3b93 100644 --- a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo.Abp.Identity.MongoDB.Tests.csproj @@ -21,9 +21,9 @@ - - - + + + diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj index 07377805af..289276595e 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.MongoDB.Tests/Volo.Abp.IdentityServer.MongoDB.Tests.csproj @@ -21,9 +21,9 @@ - - - + + + diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/package.json b/modules/openiddict/app/OpenIddict.Demo.Server/package.json index ece4546430..367ececa5e 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } diff --git a/modules/openiddict/app/angular/package.json b/modules/openiddict/app/angular/package.json index 34f85ac20a..bf85a461fb 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.2.0-rc.1", - "@abp/ng.components": "~9.2.0-rc.1", - "@abp/ng.core": "~9.2.0-rc.1", - "@abp/ng.oauth": "~9.2.0-rc.1", - "@abp/ng.identity": "~9.2.0-rc.1", - "@abp/ng.setting-management": "~9.2.0-rc.1", - "@abp/ng.tenant-management": "~9.2.0-rc.1", - "@abp/ng.theme.shared": "~9.2.0-rc.1", - "@abp/ng.theme.lepton-x": "~4.2.0-rc.1", + "@abp/ng.account": "~9.2.0-rc.4", + "@abp/ng.components": "~9.2.0-rc.4", + "@abp/ng.core": "~9.2.0-rc.4", + "@abp/ng.oauth": "~9.2.0-rc.4", + "@abp/ng.identity": "~9.2.0-rc.4", + "@abp/ng.setting-management": "~9.2.0-rc.4", + "@abp/ng.tenant-management": "~9.2.0-rc.4", + "@abp/ng.theme.shared": "~9.2.0-rc.4", + "@abp/ng.theme.lepton-x": "~4.2.0-rc.4", "@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.2.0-rc.1", + "@abp/ng.schematics": "~9.2.0-rc.4", "@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/Controllers/AuthorizeController.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs index b575a03c0e..5c2f6ef996 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs +++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/AuthorizeController.cs @@ -11,7 +11,6 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Microsoft.Extensions.Primitives; using OpenIddict.Abstractions; using OpenIddict.Server.AspNetCore; using Volo.Abp.AspNetCore.Security; @@ -31,52 +30,22 @@ public class AuthorizeController : AbpOpenIdDictControllerBase { var request = await GetOpenIddictServerRequestAsync(HttpContext); - // If prompt=login was specified by the client application, - // immediately return the user agent to the login page. - if (request.HasPromptValue(OpenIddictConstants.PromptValues.Login)) - { - // To avoid endless login -> authorization redirects, the prompt=login flag - // is removed from the authorization request payload before redirecting the user. - var prompt = string.Join(" ", request.GetPromptValues().Remove(OpenIddictConstants.PromptValues.Login)); - - var parameters = Request.HasFormContentType ? - Request.Form.Where(parameter => parameter.Key != OpenIddictConstants.Parameters.Prompt).ToList() : - Request.Query.Where(parameter => parameter.Key != OpenIddictConstants.Parameters.Prompt).ToList(); - - parameters.Add(KeyValuePair.Create(OpenIddictConstants.Parameters.Prompt, new StringValues(prompt))); - - return Challenge( - authenticationSchemes: IdentityConstants.ApplicationScheme, - properties: new AuthenticationProperties - { - RedirectUri = Request.PathBase + Request.Path + QueryString.Create(parameters) - }); - } - - // If prompt=select_account was specified by the client application, - // We will redirect the user to the select_account page. - if (request.HasPromptValue(OpenIddictConstants.PromptValues.SelectAccount)) - { - // To avoid endless login -> authorization redirects, the prompt=login flag - // is removed from the authorization request payload before redirecting the user. - var prompt = string.Join(" ", request.GetPromptValues().Remove(OpenIddictConstants.PromptValues.SelectAccount)); - - var parameters = Request.HasFormContentType ? - Request.Form.Where(parameter => parameter.Key != OpenIddictConstants.Parameters.Prompt).ToList() : - Request.Query.Where(parameter => parameter.Key != OpenIddictConstants.Parameters.Prompt).ToList(); - - parameters.Add(KeyValuePair.Create(OpenIddictConstants.Parameters.Prompt, new StringValues(prompt))); - - var selectAccountPath = HttpContext.RequestServices.GetRequiredService>().Value.SelectAccountPage; - return Redirect(Url.Content($"{selectAccountPath}?RedirectUri={UrlEncoder.Default.Encode(Request.PathBase + Request.Path + QueryString.Create(parameters))}")); - } - - // Retrieve the user principal stored in the authentication cookie. - // If a max_age parameter was provided, ensure that the cookie is not too old. - // If the user principal can't be extracted or the cookie is too old, redirect the user to the login page. + // Try to retrieve the user principal stored in the authentication cookie and redirect + // the user agent to the login page (or to an external provider) in the following cases: + // + // - If the user principal can't be extracted or the cookie is too old. + // - If prompt=login was specified by the client application. + // - If max_age=0 was specified by the client application (max_age=0 is equivalent to prompt=login). + // - If a max_age parameter was provided and the authentication cookie is not considered "fresh" enough. + // + // For scenarios where the default authentication handler configured in the ASP.NET Core + // authentication options shouldn't be used, a specific scheme can be specified here. var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme); - if (result == null || !result.Succeeded || (request.MaxAge != null && result.Properties?.IssuedUtc != null && - DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))) + if (result is not { Succeeded: true } || + ((request.HasPromptValue(OpenIddictConstants.PromptValues.Login) || request.MaxAge is 0 || + (request.MaxAge != null && result.Properties?.IssuedUtc != null && + TimeProvider.System.GetUtcNow() - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))) && + TempData["IgnoreAuthenticationChallenge"] is null or false)) { // If the client application requested promptless authentication, // return an error indicating that the user is not logged in. @@ -91,13 +60,33 @@ public class AuthorizeController : AbpOpenIdDictControllerBase })); } - return Challenge( - authenticationSchemes: IdentityConstants.ApplicationScheme, - properties: new AuthenticationProperties - { - RedirectUri = Request.PathBase + Request.Path + QueryString.Create( - Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList()) - }); + // To avoid endless login endpoint -> authorization endpoint redirects, a special temp data entry is + // used to skip the challenge if the user agent has already been redirected to the login endpoint. + // + // Note: this flag doesn't guarantee that the user has accepted to re-authenticate. If such a guarantee + // is needed, the existing authentication cookie MUST be deleted AND revoked (e.g using ASP.NET Core + // Identity's security stamp feature with an extremely short revalidation time span) before triggering + // a challenge to redirect the user agent to the login endpoint. + TempData["IgnoreAuthenticationChallenge"] = true; + + // For scenarios where the default challenge handler configured in the ASP.NET Core + // authentication options shouldn't be used, a specific scheme can be specified here. + return Challenge(new AuthenticationProperties + { + RedirectUri = Request.PathBase + Request.Path + QueryString.Create(Request.HasFormContentType ? Request.Form : Request.Query) + }); + } + + // If prompt=select_account was specified by the client application, + // We will redirect the user to the select_account page. + if (request.HasPromptValue(OpenIddictConstants.PromptValues.SelectAccount) && TempData["IgnoreSelectAccount"] is null or false) + { + // To avoid endless select account endpoint -> authorization endpoint redirects, a special temp data entry is + // used to skip the redirect if the user agent has already been redirected to the select account endpoint. + TempData["IgnoreSelectAccount"] = true; + + var selectAccountPath = HttpContext.RequestServices.GetRequiredService>().Value.SelectAccountPage.RemovePostFix("/"); + return Redirect(Url.Content($"{selectAccountPath}?RedirectUri={UrlEncoder.Default.Encode(Request.PathBase + Request.Path + QueryString.Create(Request.HasFormContentType ? Request.Form : Request.Query))}")); } // Retrieve the profile of the logged in user. @@ -111,8 +100,7 @@ public class AuthorizeController : AbpOpenIdDictControllerBase authenticationSchemes: IdentityConstants.ApplicationScheme, properties: new AuthenticationProperties { - RedirectUri = Request.PathBase + Request.Path + QueryString.Create( - Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList()) + RedirectUri = Request.PathBase + Request.Path + QueryString.Create(Request.HasFormContentType ? Request.Form : Request.Query) }); } } @@ -124,8 +112,7 @@ public class AuthorizeController : AbpOpenIdDictControllerBase authenticationSchemes: IdentityConstants.ApplicationScheme, properties: new AuthenticationProperties { - RedirectUri = Request.PathBase + Request.Path + QueryString.Create( - Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList()) + RedirectUri = Request.PathBase + Request.Path + QueryString.Create(Request.HasFormContentType ? Request.Form : Request.Query) }); } diff --git a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj index d5f8903293..60a422fd38 100644 --- a/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj +++ b/modules/openiddict/test/Volo.Abp.OpenIddict.MongoDB.Tests/Volo.Abp.OpenIddict.MongoDB.Tests.csproj @@ -10,9 +10,9 @@ - - - + + + diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor index 87c2c0db91..7992764c00 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor @@ -37,22 +37,25 @@ @if (_groups != null && _groups.Any()) {
- + @foreach (var group in _groups) { @if (group.Permissions.Any(x => x.IsGranted)) { - - @group.DisplayName ( @(group.Permissions.Count(x => x.IsGranted)) ) - + @group.DisplayName (@(group.Permissions.Count(x => x.IsGranted))) } else { - - @group.DisplayName ( @(group.Permissions.Count(x => x.IsGranted)) ) - + + @group.DisplayName (@(group.Permissions.Count(x => x.IsGranted))) + } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs index d2c2e092d5..cd3be870a1 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs @@ -58,7 +58,7 @@ public partial class PermissionManagementModal var result = await PermissionAppService.GetAsync(_providerName, _providerKey); _entityDisplayName = entityDisplayName ?? result.EntityDisplayName; - _allGroups = result.Groups; + _allGroups = result.Groups.OrderBy(x => x.DisplayName).ToList(); _groups = _allGroups.ToList(); NormalizePermissionGroup(); diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css index f6870a7a16..a0b6579faf 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css @@ -15,7 +15,7 @@ fieldset legend { } ::deep .lpx-scroll-pills-container ul li { - border: 1px solid #e8eef3; + border: 1px solid var(--lpx-border-color); margin-bottom: 10px; border-radius: 10px; } @@ -26,6 +26,15 @@ fieldset legend { background-color: #6c5dd3 !important; } -::deep .lpx-theme-dark .lpx-scroll-pills-container ul li { - border: 1px solid #23262a; -} \ No newline at end of file +::deep .nav-pills .nav-link { + background: none; + border: 0; + border-radius: var(--bs-nav-pills-border-radius); +} + +::deep .nav-pills .nav-link:disabled { + color: var(--bs-nav-link-disabled-color); + background-color: transparent; + border-color: transparent; +} + diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ar.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ar.json index 52de9ea37a..30f4b647e8 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ar.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ar.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "منح كافة الأذونات", "SelectAllInThisTab": "تحديد الكل", "SaveWithoutAnyPermissionsWarningMessage": "هل أنت متأكد أنك تريد الحفظ بدون أي أذونات؟", - "PermissionGroup": "مجموعة الأذونات" + "PermissionGroup": "مجموعة الأذونات", + "Filter": "تصفية" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/cs.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/cs.json index c0e38b9320..814b8e423c 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/cs.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/cs.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Dát veškerá oprávnění", "SelectAllInThisTab": "Vybrat vše", "SaveWithoutAnyPermissionsWarningMessage": "Opravdu chcete ukládat bez jakýchkoli oprávnění?", - "PermissionGroup": "Skupina oprávnění" + "PermissionGroup": "Skupina oprávnění", + "Filter": "Filtr" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/de.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/de.json index a2bb5fe72a..7a40c5d4d4 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/de.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/de.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Alle Berechtigungen erteilen", "SelectAllInThisTab": "Alle auswählen", "SaveWithoutAnyPermissionsWarningMessage": "Sind Sie sicher, dass Sie ohne Berechtigungen speichern möchten?", - "PermissionGroup": "Berechtigungsgruppe" + "PermissionGroup": "Berechtigungsgruppe", + "Filter": "Filtern" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/el.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/el.json index bc2c96db04..3449b7fab6 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/el.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/el.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Χορήγηση όλων των δικαιώματων", "SelectAllInThisTab": "Επιλογή όλων", "SaveWithoutAnyPermissionsWarningMessage": "Είστε βέβαιοι ότι θέλετε να αποθηκεύσετε χωρίς δικαιώματα;", - "PermissionGroup": "Ομάδα δικαιωμάτων" + "PermissionGroup": "Ομάδα δικαιωμάτων", + "Filter": "Φίλτρο" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en-GB.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en-GB.json index 62762d00a8..be6cbcd1f5 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en-GB.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en-GB.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Grant all permissions", "SelectAllInThisTab": "Select all", "SaveWithoutAnyPermissionsWarningMessage": "Are you sure you want to save without any permissions?", - "PermissionGroup": "Permission Group" + "PermissionGroup": "Permission Group", + "Filter": "Filter" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en.json index 45aeb905e2..b8299d4e5b 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/en.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Grant all permissions", "SelectAllInThisTab": "Select all", "SaveWithoutAnyPermissionsWarningMessage": "Are you sure you want to save without any permissions?", - "PermissionGroup": "Permission Group" + "PermissionGroup": "Permission Group", + "Filter": "Filter" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json index 610d86a2ff..622883b259 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Conceder todos los permisos", "SelectAllInThisTab": "Seleccionar todo", "SaveWithoutAnyPermissionsWarningMessage": "¿Estás seguro de que quieres guardar sin ningún permiso?", - "PermissionGroup": "Grupo de permisos" + "PermissionGroup": "Grupo de permisos", + "Filter": "Filtrar" } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fa.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fa.json index 615ef79412..7ea9a6c4f3 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fa.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fa.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "اعطای همه مجوزها", "SelectAllInThisTab": "انتخاب همه", "SaveWithoutAnyPermissionsWarningMessage": "آیا مطمئن هستید که می خواهید بدون هیچ دسترسی ذخیره کنید؟", - "PermissionGroup": "گروه دسترسی" + "PermissionGroup": "گروه دسترسی", + "Filter": "فیلتر" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fi.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fi.json index 2c24727ad5..f9b828ade4 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fi.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fi.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Myönnä kaikki käyttöoikeudet", "SelectAllInThisTab": "Valitse kaikki", "SaveWithoutAnyPermissionsWarningMessage": "Haluatko varmasti tallentaa ilman käyttöoikeuksia?", - "PermissionGroup": "Käyttöoikeus" + "PermissionGroup": "Käyttöoikeus", + "Filter": "Suodatus" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fr.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fr.json index b2676631a2..79f4e68377 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fr.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/fr.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Accorder toutes les autorisations", "SelectAllInThisTab": "Sélectionner tous les", "SaveWithoutAnyPermissionsWarningMessage": "Êtes-vous sûr de vouloir enregistrer sans aucune autorisation ?", - "PermissionGroup": "Groupe d'autorisations" + "PermissionGroup": "Groupe d'autorisations", + "Filter": "Filtrer" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hi.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hi.json index fa271bc752..cdc030e8ef 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hi.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hi.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "सभी अनुमतियां प्रदान करें", "SelectAllInThisTab": "सभी का चयन करे", "SaveWithoutAnyPermissionsWarningMessage": "क्या आप वाकई बिना किसी अनुमति के सहेजना चाहते हैं?", - "PermissionGroup": "अनुमति समूह" + "PermissionGroup": "अनुमति समूह", + "Filter": "फ़िल्टर" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hr.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hr.json index 45034a5bb6..531d0a35d2 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hr.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hr.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Dodijelite sva dopuštenja", "SelectAllInThisTab": "Odaberi sve", "SaveWithoutAnyPermissionsWarningMessage": "Jeste li sigurni da želite spremiti bez ikakvih dopuštenja?", - "PermissionGroup": "Grupa dozvola" + "PermissionGroup": "Grupa dozvola", + "Filter": "Filtriraj" } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hu.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hu.json index fdb727bf2b..3177ef8fa7 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hu.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hu.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Adjon meg minden engedélyt", "SelectAllInThisTab": "Mindet kiválaszt", "SaveWithoutAnyPermissionsWarningMessage": "Biztos, hogy engedélyek nélkül akar menteni?", - "PermissionGroup": "Engedélycsoport" + "PermissionGroup": "Engedélycsoport", + "Filter": "Szűrő" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/is.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/is.json index 322e6b5580..7db32eb99e 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/is.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/is.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Veita allar heimildir", "SelectAllInThisTab": "Velja allt", "SaveWithoutAnyPermissionsWarningMessage": "Ertu viss um að þú viljir vista án nokkurra heimilda?", - "PermissionGroup": "Heimildahópur" + "PermissionGroup": "Heimildahópur", + "Filter": "Sía" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/it.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/it.json index 1312568b53..e473c7b310 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/it.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/it.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Concedi tutte le autorizzazioni", "SelectAllInThisTab": "Seleziona tutto", "SaveWithoutAnyPermissionsWarningMessage": "Sei sicuro di voler salvare senza alcuna autorizzazione?", - "PermissionGroup": "Gruppo di autorizzazioni" + "PermissionGroup": "Gruppo di autorizzazioni", + "Filter": "Filtro" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/nl.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/nl.json index 0dacfe8341..4b928c4d03 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/nl.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/nl.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Verleen alle rechten", "SelectAllInThisTab": "Selecteer alles", "SaveWithoutAnyPermissionsWarningMessage": "Weet u zeker dat u zonder rechten wilt opslaan?", - "PermissionGroup": "Rechtengroep" + "PermissionGroup": "Rechtengroep", + "Filter": "Filter" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pl-PL.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pl-PL.json index aa0bf32851..ee483651eb 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pl-PL.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pl-PL.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Udziel wszystkich uprawnień", "SelectAllInThisTab": "Zaznacz wszystkie", "SaveWithoutAnyPermissionsWarningMessage": "Czy na pewno chcesz zapisać bez żadnych uprawnień?", - "PermissionGroup": "Grupa uprawnień" + "PermissionGroup": "Grupa uprawnień", + "Filter": "Filtr" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pt-BR.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pt-BR.json index 14f45ec46a..28231b227f 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pt-BR.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/pt-BR.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Conceder todas as permissões", "SelectAllInThisTab": "Selecionar todos", "SaveWithoutAnyPermissionsWarningMessage": "Tem certeza que deseja salvar sem nenhuma permissão?", - "PermissionGroup": "Grupo de permissão" + "PermissionGroup": "Grupo de permissão", + "Filter": "Filtrar" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ro-RO.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ro-RO.json index 6466540438..af7db26acb 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ro-RO.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ro-RO.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Acordă toate permisiunile", "SelectAllInThisTab": "Selectează toate", "SaveWithoutAnyPermissionsWarningMessage": "Sigur doriți să salvați fără nicio permisiune?", - "PermissionGroup": "Grup de permisiuni" + "PermissionGroup": "Grup de permisiuni", + "Filter": "Filtru" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ru.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ru.json index d46b4e289e..6041357b0e 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ru.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ru.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Предоставить все разрешения", "SelectAllInThisTab": "Выбрать все", "SaveWithoutAnyPermissionsWarningMessage": "Вы уверены, что хотите сохранить без каких-либо разрешений?", - "PermissionGroup": "Группа разрешений" + "PermissionGroup": "Группа разрешений", + "Filter": "Фильтр" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sk.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sk.json index 722582d28f..c079b8eba1 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sk.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sk.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Udeliť všetky oprávnenia", "SelectAllInThisTab": "Vybrať všetky", "SaveWithoutAnyPermissionsWarningMessage": "Naozaj chcete ukladať bez akýchkoľvek povolení?", - "PermissionGroup": "Skupina oprávnení" + "PermissionGroup": "Skupina oprávnení", + "Filter": "Filtrovať" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sl.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sl.json index 36640ffdbd..9c906f7387 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sl.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sl.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Dodeli vsa dovoljenja", "SelectAllInThisTab": "Izberi vse", "SaveWithoutAnyPermissionsWarningMessage": "Ali ste prepričani, da želite shraniti brez kakršnih koli dovoljenj?", - "PermissionGroup": "Skupina dovoljenj" + "PermissionGroup": "Skupina dovoljenj", + "Filter": "Filtriraj" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sv.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sv.json index 3671bf1422..d46fca4dc4 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sv.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/sv.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Ge alla behörigheter", "SelectAllInThisTab": "Välj alla", "SaveWithoutAnyPermissionsWarningMessage": "Är du säker på att du vill spara utan några behörigheter?", - "PermissionGroup": "Behörighetsgrupp" + "PermissionGroup": "Behörighetsgrupp", + "Filter": "Filtrera" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/tr.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/tr.json index 3edfc2942f..960cd8cf02 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/tr.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/tr.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Tüm izinleri ver", "SelectAllInThisTab": "Hepsini seç", "SaveWithoutAnyPermissionsWarningMessage": "Hiçbir izin olmadan kaydetmek istediğinize emin misiniz?", - "PermissionGroup": "İzin Grubu" + "PermissionGroup": "İzin Grubu", + "Filter": "Filtre" } } diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/vi.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/vi.json index d927f6a4a9..5e9a9d8565 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/vi.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/vi.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "Cấp tất cả các quyền", "SelectAllInThisTab": "Chọn tất cả", "SaveWithoutAnyPermissionsWarningMessage": "Bạn có chắc chắn muốn lưu mà không có bất kỳ quyền nào không?", - "PermissionGroup": "Nhóm quyền" + "PermissionGroup": "Nhóm quyền", + "Filter": "Lọc" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hans.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hans.json index 3ae69c4d58..df844ca2bf 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hans.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hans.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "授予所有权限", "SelectAllInThisTab": "全选", "SaveWithoutAnyPermissionsWarningMessage": "您确定要在没有任何权限的情况下保存吗?", - "PermissionGroup": "权限组" + "PermissionGroup": "权限组", + "Filter": "过滤" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hant.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hant.json index b2d46a42a5..72af56c960 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hant.json +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/zh-Hant.json @@ -7,6 +7,7 @@ "SelectAllInAllTabs": "授予所有權限", "SelectAllInThisTab": "全選", "SaveWithoutAnyPermissionsWarningMessage": "您確定要在沒有任何權限的情況下保存嗎?", - "PermissionGroup": "權限組" + "PermissionGroup": "權限組", + "Filter": "過濾" } } \ No newline at end of file diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml index 155eebfd5a..a9caf5c348 100644 --- a/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml +++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Web/Pages/AbpPermissionManagement/PermissionManagementModal.cshtml @@ -23,7 +23,7 @@
- +
@@ -34,7 +34,7 @@
- Permission Group + @L["PermissionGroup"].Value diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj index 0f9e0169e8..f42d7c0385 100644 --- a/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj +++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.MongoDB.Tests/Volo.Abp.PermissionManagement.MongoDB.Tests.csproj @@ -20,9 +20,9 @@ - - - + + + 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 4196368e02..38d2fecfdf 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } 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 8524474dd3..682f82ae14 100644 --- a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/yarn.lock +++ b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/yarn.lock @@ -2,185 +2,185 @@ # yarn lockfile v1 -"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.1.tgz#00f6c73e8e38578cfb6eb10214a8e4347dda75b3" - integrity sha512-Ophg50dxq2E4A2PgAtErDZ8LQfgAoT1ipZv4H3lxu0GwtRXrLEScfykHVDScTHJVpTF8Z549zYQl3jYtPJACog== +"@abp/aspnetcore.mvc.ui.theme.basic@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.basic/-/aspnetcore.mvc.ui.theme.basic-9.2.0-rc.4.tgz#2659ec541028ec6a1688b748414fb181924f1f58" + integrity sha512-KSpfnvgRPxDb9oJWBnjpFm/FcXSTRO6aAVBlCERi4jtGzp04e//3rHnOWjv+JyxJqOP0JszWSALXK4A/oMQFNQ== dependencies: - "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared" "~9.2.0-rc.4" -"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.1.tgz#4fb738ad5a6ac85165cf3e45893615d1762d43ed" - integrity sha512-TCW7nGGMqnBD8n2Jc1r9ht2HixRj8kDOZJysQUd3uHNmTBCO1b5cBjxL4ksSzM98/kEs6i0q6OTasqJrxHuHNA== +"@abp/aspnetcore.mvc.ui.theme.shared@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui.theme.shared/-/aspnetcore.mvc.ui.theme.shared-9.2.0-rc.4.tgz#4212523cc2d2db881d2a0a9c1b28f372c53c19d7" + integrity sha512-z6nCmIfcaiQ6CPHhVq0C6RYljjrqScVVj+Sf0uI8eP6qG+CVT/aEVgb+3Nc5EM5SjDvR/eTxH4J3YcVNDj32Lg== dependencies: - "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.1" - "@abp/bootstrap" "~9.2.0-rc.1" - "@abp/bootstrap-datepicker" "~9.2.0-rc.1" - "@abp/bootstrap-daterangepicker" "~9.2.0-rc.1" - "@abp/datatables.net-bs5" "~9.2.0-rc.1" - "@abp/font-awesome" "~9.2.0-rc.1" - "@abp/jquery-form" "~9.2.0-rc.1" - "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.1" - "@abp/lodash" "~9.2.0-rc.1" - "@abp/luxon" "~9.2.0-rc.1" - "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.1" - "@abp/moment" "~9.2.0-rc.1" - "@abp/select2" "~9.2.0-rc.1" - "@abp/sweetalert2" "~9.2.0-rc.1" - "@abp/timeago" "~9.2.0-rc.1" - -"@abp/aspnetcore.mvc.ui@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.1.tgz#d2a2c5fc25444eedf2f4ea92505ba4aede86b771" - integrity sha512-vgdJFOzxqwuaDcMhzIHHn1wIJbIar/NzJxpbUBjRWjnZzrKKerDLF9FuDegpU1fX3nOvunI11zSFT3yCuMHebQ== + "@abp/aspnetcore.mvc.ui" "~9.2.0-rc.4" + "@abp/bootstrap" "~9.2.0-rc.4" + "@abp/bootstrap-datepicker" "~9.2.0-rc.4" + "@abp/bootstrap-daterangepicker" "~9.2.0-rc.4" + "@abp/datatables.net-bs5" "~9.2.0-rc.4" + "@abp/font-awesome" "~9.2.0-rc.4" + "@abp/jquery-form" "~9.2.0-rc.4" + "@abp/jquery-validation-unobtrusive" "~9.2.0-rc.4" + "@abp/lodash" "~9.2.0-rc.4" + "@abp/luxon" "~9.2.0-rc.4" + "@abp/malihu-custom-scrollbar-plugin" "~9.2.0-rc.4" + "@abp/moment" "~9.2.0-rc.4" + "@abp/select2" "~9.2.0-rc.4" + "@abp/sweetalert2" "~9.2.0-rc.4" + "@abp/timeago" "~9.2.0-rc.4" + +"@abp/aspnetcore.mvc.ui@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/aspnetcore.mvc.ui/-/aspnetcore.mvc.ui-9.2.0-rc.4.tgz#a47763a480e488363b901327d94556fdad6cccb7" + integrity sha512-7fxC3zifdnpJZwKsP1hgK0+mu9y/w4zrMY1rR8AVvcpMdt8/Mmtj6mJi+Ompv3YtO9F/Zgnxqma5R0pYMTke7g== dependencies: ansi-colors "^4.1.3" -"@abp/bootstrap-datepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.1.tgz#b548840efb6a9c8d9acabf828af4e95628be6cbe" - integrity sha512-ClR+fiOiUccEIvbeAgfo2+Z3eZYp7MRIVrll8Rh93oKr6C0XzjwA7acSGe87CS3e5wkUXMsKtqmRX+eSXyJBPQ== +"@abp/bootstrap-datepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-datepicker/-/bootstrap-datepicker-9.2.0-rc.4.tgz#0aec67332e3148e21658650bfaaa08c64180e2ad" + integrity sha512-CaD709aGigfQk76XDshSrctm9TkgjA+7XgnDuVraPRPwq4dwXGIhbNAiJ1+5k6OXrUHqJP3nPc4NDPZiXDwgqw== dependencies: bootstrap-datepicker "^1.10.0" -"@abp/bootstrap-daterangepicker@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.1.tgz#e7174841889b80f7beddaeb84be7a0b908cc34a3" - integrity sha512-CzSutc7rtYzd4jzTTiKlUmFGlZk70DTcp/tnuD7rVWZp7Njr2INfwGlgt7P7Hj3g9Wt3j0mAM+IDz9t2rleqtA== +"@abp/bootstrap-daterangepicker@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap-daterangepicker/-/bootstrap-daterangepicker-9.2.0-rc.4.tgz#b08d564b0dfc8be62a052fc205e1445764b6a2d0" + integrity sha512-zwWkb6JaUqN2rtIGLtb0Cf1RtP0nuCFK0x2r4J9kYnv1vKiT8vrK2Jl5mJVjvdnO0JifS1rueDMPglVpOeghRw== dependencies: bootstrap-daterangepicker "^3.1.0" -"@abp/bootstrap@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.1.tgz#87c17c50a9e8f6fdb6474541aeaadf1ebb1d6b1b" - integrity sha512-tgOIGY7HfiwgM9QUpcydZN9tdKSrm6mYPzECBDU866xWi8aUeLZp12hLoSL94M1iZ6jchbZaqTqMOy00Tc0FCQ== +"@abp/bootstrap@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/bootstrap/-/bootstrap-9.2.0-rc.4.tgz#0615ec9fa7422d76e8f4af22ec28fe9672d60c38" + integrity sha512-m1ORR/R84nPEfid/x5rC5jy4orsw4yhkk4nApiW11H4Eb7ssbcviR75ugJ5GBt3GOevHHlTZWwvf8K4C+zdqZg== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" bootstrap "^5.3.3" -"@abp/core@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.1.tgz#30fb627e750f651b4d1819461e3ffeb5fc6d9011" - integrity sha512-Adb4sk9oZJaxL19RbM1opLGWn2kKzRUcFLH6lNG2QYCAXf74y/YfFLQyoZSrTKS1M+hkGjIrEW6GssAgHTCJeg== +"@abp/core@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/core/-/core-9.2.0-rc.4.tgz#b758ea117ae3e3e3596e407a347617b8fcb6c112" + integrity sha512-eNklBpyUAort/UEhgmnvMglBS/FSAzUiKalN7hgJFKx0nd3cDDkjkN6YFY8VuPInt3YfRz5omZQsGNq7eyjtbQ== dependencies: - "@abp/utils" "~9.2.0-rc.1" + "@abp/utils" "~9.2.0-rc.4" -"@abp/datatables.net-bs5@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.1.tgz#7d56850b6e46f744c794e40d08aeb5fd1a7543ee" - integrity sha512-PFt0PruHikzXzcEKtykwnRo+Z0D+njmhaoJk4J11yoZjvSFOAQXIRdsVgFgJub8REN3I57eG9PPCl3AZwAba9w== +"@abp/datatables.net-bs5@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net-bs5/-/datatables.net-bs5-9.2.0-rc.4.tgz#75c12fe053d593b738bb5ca7394b2954409f5e00" + integrity sha512-5FG5Jc6Co9q/1xYmmW2SabSaXVkdJohPJ9XtzTthwnY8Ko5eGV7TPkEfwwsk0PLXp+Wu3ifQaZI4CIE9WR81XA== dependencies: - "@abp/datatables.net" "~9.2.0-rc.1" + "@abp/datatables.net" "~9.2.0-rc.4" datatables.net-bs5 "^2.1.8" -"@abp/datatables.net@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.1.tgz#8d165f404e85a54a4e92887173a3d01f827ba5ef" - integrity sha512-rEvCSJWH2l505Nb7Nqa0tL1iFpnMZ+WxnfbomaqdSpL6YsCUd8syeGI37V+LQUknXGsUFqGVyazPrU3vjIR8Kg== +"@abp/datatables.net@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/datatables.net/-/datatables.net-9.2.0-rc.4.tgz#523b017e4b9ea9d3a6d3262f66bd3daaade05c0b" + integrity sha512-udCSjJYYpi/Ql/KJZxYDMxbtX6gXw7hsfMxQjP0u37JsyNLgd4fTrzaXCe7OKn3x7poJcANoqsEgWow/9R/WIg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" datatables.net "^2.1.8" -"@abp/font-awesome@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.1.tgz#758b4028fa5f6d11bb675ff465fc222e3b656c01" - integrity sha512-H0fmIM/YAkT64LLMub0eDzpxvrNVjkFrRgX4YM10U/AQ0gILxjuEapRxv3+ueIJiy3DiBLkPWQ+SQN3Lwh4FOA== +"@abp/font-awesome@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/font-awesome/-/font-awesome-9.2.0-rc.4.tgz#31d9fa475af3b543ddaff16e6af8caba966bd331" + integrity sha512-FYmfrf2mX5rzU+GqK078rn85UmfAwdCB8JQhnGfkylybMRJvmocRsPBIEThjlFZAPGqqvULHUTRMwnRPTgpuNw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" "@fortawesome/fontawesome-free" "^6.6.0" -"@abp/jquery-form@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.1.tgz#558bcf9da8912e0014b407018d1f0fb7ab294bf0" - integrity sha512-MzhptVbyZ7WNYAw4KmWiI4WnR8H16jBshceO7DFtfyZDRUU0n4ZPTYs1rGlj4+5iv2B7r8dci0Nx94bkId7FwA== +"@abp/jquery-form@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-form/-/jquery-form-9.2.0-rc.4.tgz#b200be90031b58305a2ebfd646ffbd5ce4cca40c" + integrity sha512-ohCtIfz48E0+vNdNyKTsLlfW0NYMJfKWXd9BPp2szgBaDbC7jYdGYyABbxGxRc7mp1B8xQzRhLnTzdRtWaJemg== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-form "^4.3.0" -"@abp/jquery-validation-unobtrusive@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.1.tgz#48b227ee95e0d7a12efbdfbdf1a28e3003dcdb8f" - integrity sha512-wTo5/oqU1TVOuuYfsu6XipryW2rrSx+bebP4fm/lQ1cZF+Ki1Rbvt5p+3fIGZfg8dJRMKXCtL3UYyadKTlqJ8A== +"@abp/jquery-validation-unobtrusive@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation-unobtrusive/-/jquery-validation-unobtrusive-9.2.0-rc.4.tgz#0329f9268b83e0832e26ea3f6523dbc5226b9114" + integrity sha512-iOnw5YoiC3bCIFRjuXPagz+ixFV+PM36hP0UJ4x03BK6GDJnAvjLshYe6qnQG9Xnz1arzmIX5ud5EjWvWSBIoA== dependencies: - "@abp/jquery-validation" "~9.2.0-rc.1" + "@abp/jquery-validation" "~9.2.0-rc.4" jquery-validation-unobtrusive "^4.0.0" -"@abp/jquery-validation@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.1.tgz#fae0ce1e0db0af62f80836d3e982c9a79f7b1209" - integrity sha512-c2+BwErN2w6ikbOYuuSQHZeMdLaKR7l0CIvwtUnzwCHjdUGAbMX9w9lYwnO6R6DsNCV7Cb5+YrbjM7jGY7zMiQ== +"@abp/jquery-validation@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery-validation/-/jquery-validation-9.2.0-rc.4.tgz#073e4cbf905f652ce83633b98696b559916b984d" + integrity sha512-pS2Y2c6gXFOzfKeM2/JlW56ZmrUeflT2av64aWrFYnv7IgJUp38PEjR10uPy3g/mP2c9jis8dOfkdbRrlHwf+g== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" jquery-validation "^1.21.0" -"@abp/jquery@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.1.tgz#a930c1ef6a17a831cd7d064b7cbb20d604fbc4bb" - integrity sha512-qc461cJOQvEX95JbIFtDLj5dxUUDyP7PUXP8SjCvxP4GURoKhjxx0j0U0mBkMDJMrSrvALFKbF5S6OlgdgaPGQ== +"@abp/jquery@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/jquery/-/jquery-9.2.0-rc.4.tgz#ac8a6ce969d58cc4f05d33adcfad76e7442231e8" + integrity sha512-N5hZ8VGXJUn5QW1mSXHIO7SjdvoyrkCyH5j8DhXJO1mDlS1L36n+MJHFwQK7UZpHcFOuklAJ7f417r3sISOBCw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" jquery "~3.7.1" -"@abp/lodash@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.1.tgz#0e0b455c84c6b6c52a3aaf1ccc4c704f49503ac8" - integrity sha512-Bg2Bz7G04jvz+QRXLlK3A2eUBR3Ef1rq622jWsaKo4fW4rCdHkZBbjeqYDLYc1PqDIJawhEdIByh8VzMgRd6tA== +"@abp/lodash@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/lodash/-/lodash-9.2.0-rc.4.tgz#e428df195ed90414a9a412e1dcb6494344475f82" + integrity sha512-WsbyBNA57/giyI5pnM7Y7dk0p56hMDS5OMdmNilaGOWMnvz7mMTJNvStMBqS7fqekzfXsFGfrLbTmehY3pTYwQ== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" lodash "^4.17.21" -"@abp/luxon@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.1.tgz#275726bf1f9ff14cdf902a7ea64213a3e7434927" - integrity sha512-vga0taYVDPGwcAQqFe6pAEAUu3vRH7MgxBQdMrEX80YhsSJevPHSl6jG3ey5IqWOy4dpMyiN4v7gWBHJ93mbFg== +"@abp/luxon@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/luxon/-/luxon-9.2.0-rc.4.tgz#dacb173d24987a1ab4fb7e53dff9f91728a1efaa" + integrity sha512-qNuYml25Q2ODzZ830FhijGY66WvAUa02mB9hgulpFlF0p2UiFmhA0dMNVahEuytoFodjkSrhLP6cGfONf7ht8A== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" luxon "^3.5.0" -"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.1.tgz#3d4c17a9d6ace815e4bc4dc825d0020474a794f7" - integrity sha512-Cqs6A88bWggdtDoiCREBTXknCI+c7vhmZ/SM84k4NfwzlPscZYMCbtJlrln4g3zmElJwwBPerl0Gs778kUOjog== +"@abp/malihu-custom-scrollbar-plugin@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/malihu-custom-scrollbar-plugin/-/malihu-custom-scrollbar-plugin-9.2.0-rc.4.tgz#9b0c0444ec8f11c8c8040387f83080e51a281657" + integrity sha512-cvYJI/4jkzOWSvTY0C/PxSq62SxEq3UlaXpefj/W+CAwPVjG+Yik2YHt5qgcmRRn0oF5V/XRJHB7A4H23+VKyA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" malihu-custom-scrollbar-plugin "^3.1.5" -"@abp/moment@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.1.tgz#1604d38429f1e0484223ea4a7a3a10f1785420f4" - integrity sha512-5VnPhCOnTug7tqlLsg46LY84LU5DrYNKxm5T3oz+OFq4I05Ut/LWGElRvOnEFxfFfkYuJvbxih3trAGuEJD6+A== +"@abp/moment@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/moment/-/moment-9.2.0-rc.4.tgz#527ed54f4330a77ec2ea1411bfffe2d57e62d172" + integrity sha512-zIRTuMCcPAfJAU64DUeU7dJPUJqoyJ7TvHBhrUcmmGZK7IzNtaP3/KAGjZIHhHbUwIjidjCxlF2YnW1io7hcJg== dependencies: moment "^2.30.1" -"@abp/select2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.1.tgz#6f378c9bd4a01dbe72bf41f175c964e36353ef4e" - integrity sha512-HlQtSmY3VRIbCbTJnWFmvPeUmHYX8cI5z0Dwa30/TNPWDQuws5Yx3F4B9crw6AC/EIzCobsAZ4QhsgQxsUHNvg== +"@abp/select2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/select2/-/select2-9.2.0-rc.4.tgz#6a8c6347ec75fcf60d76bc50ecca8008253fc7c7" + integrity sha512-OMyXr+gYMM81CQliqDVnEGsK2/WbmC4N5IZ1ZSJl+mW7cUClmyg9CLg418ID/7OU+ItUwbw9YvG4RPwnGF1ujw== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" select2 "^4.0.13" -"@abp/sweetalert2@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.1.tgz#b70784ff038ff4d6cdc07a7ef35edd7da5dfaa23" - integrity sha512-cJVdPB1hh7AtmfmcLLAFGxFDYc08sjtRS5kJ37ru9WFVOyzF1A99QgMOEBSB6BGKNbkCJwQbkwGCHjtQTHQ46w== +"@abp/sweetalert2@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/sweetalert2/-/sweetalert2-9.2.0-rc.4.tgz#26d4e9c935f20a7e0bde23327c6761fe6466cd41" + integrity sha512-zhwnA0WpkNO6JuqbBgO6PQ817wuThw6mtGcP96V1m/xtckJWNDub1gby0gJqnWqnq5Cuj4u9gPRkkcVmfPn8ZA== dependencies: - "@abp/core" "~9.2.0-rc.1" + "@abp/core" "~9.2.0-rc.4" sweetalert2 "^11.14.1" -"@abp/timeago@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.1.tgz#689fa9c9d4b0c0a239b37cd4d045dfb745f392df" - integrity sha512-mNmmRVzGryW45woLmDrxVnUCSi2+Xp2djHNKe7VF4D2Xywos9yxEImTX8B9lB0QMWl8BawsZCz/jsC3QURkXGw== +"@abp/timeago@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/timeago/-/timeago-9.2.0-rc.4.tgz#494b25062f14f8a139ed66958991d34fcf4023a3" + integrity sha512-6HoEkdQCYDxrEGSjxHXN2Vj5ipc3rIXTbCqj7dYI9K5tuaQ4Wq0Obz/Wx6UZ71ZjzGAeAQkDeXVc68GjQyLX6Q== dependencies: - "@abp/jquery" "~9.2.0-rc.1" + "@abp/jquery" "~9.2.0-rc.4" timeago "^1.6.7" -"@abp/utils@~9.2.0-rc.1": - version "9.2.0-rc.1" - resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.1.tgz#508d9922c842f2a76fc748574f0ae3a9954b6895" - integrity sha512-XFaBI4qxeXixAtapXRzETkS60+5XkZeEnW9O3wyHU6r4rEtIdOHo9w7t/vM5b5KAUlcEE02jS6pcqlJHd7miqw== +"@abp/utils@~9.2.0-rc.4": + version "9.2.0-rc.4" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-9.2.0-rc.4.tgz#350eb915af78ecdbc2a0a15a1ad4bac4212cefc2" + integrity sha512-PZzfkiq6sthX5+Icw7h3HVpnDVgN7ZnmOnIyzKhBeHALpH+JfO7QruwJl96Moba4LGmzPdFdLkwm2qznVoqyZA== dependencies: just-compare "^2.3.0" diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/TimeZoneSettingsAppService.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/TimeZoneSettingsAppService.cs index ee8580ac22..4aa5700d8e 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/TimeZoneSettingsAppService.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Application/Volo/Abp/SettingManagement/TimeZoneSettingsAppService.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; @@ -12,6 +13,8 @@ public class TimeZoneSettingsAppService : SettingManagementAppServiceBase, ITime protected ISettingManager SettingManager { get; } protected ITimezoneProvider TimezoneProvider { get; } + private const string UnspecifiedTimeZone = "Unspecified"; + public TimeZoneSettingsAppService(ISettingManager settingManager, ITimezoneProvider timezoneProvider) { SettingManager = settingManager; @@ -20,21 +23,36 @@ public class TimeZoneSettingsAppService : SettingManagementAppServiceBase, ITime public virtual async Task GetAsync() { - if (CurrentTenant.GetMultiTenancySide() == MultiTenancySides.Host) + var timezone = CurrentTenant.GetMultiTenancySide() == MultiTenancySides.Host + ? await SettingManager.GetOrNullGlobalAsync(TimingSettingNames.TimeZone) + : await SettingManager.GetOrNullForCurrentTenantAsync(TimingSettingNames.TimeZone); + + if (timezone.IsNullOrWhiteSpace()) { - return await SettingManager.GetOrNullGlobalAsync(TimingSettingNames.TimeZone); + timezone = UnspecifiedTimeZone; } - return await SettingManager.GetOrNullForCurrentTenantAsync(TimingSettingNames.TimeZone); + return timezone; } public virtual Task> GetTimezonesAsync() { - return Task.FromResult(TimeZoneHelper.GetTimezones(TimezoneProvider.GetWindowsTimezones())); + var timezones = TimeZoneHelper.GetTimezones(TimezoneProvider.GetIanaTimezones()); + timezones.Insert(0, new NameValue + { + Name = L["DefaultTimeZone"], + Value = UnspecifiedTimeZone + }); + return Task.FromResult(timezones); } public virtual async Task UpdateAsync(string timezone) { + if (timezone.Equals(UnspecifiedTimeZone, StringComparison.OrdinalIgnoreCase)) + { + timezone = null; + } + if (CurrentTenant.GetMultiTenancySide() == MultiTenancySides.Host) { await SettingManager.SetGlobalAsync(TimingSettingNames.TimeZone, timezone); diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/SettingManagement.razor b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/SettingManagement.razor index e3ab222ccf..6fb9445860 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/SettingManagement.razor +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Blazor/Pages/SettingManagement/SettingManagement.razor @@ -11,21 +11,22 @@ - + - @foreach (var group in SettingComponentCreationContext.Groups) - { - - @group.DisplayName - - } +
+ @foreach (var group in SettingComponentCreationContext.Groups) + { + + @group.DisplayName + + } +
@foreach (var group in SettingComponentCreationContext.Groups) { - @{ SettingItemRenders.Add(builder => { diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json index 1a0a2e218a..ec35f5286f 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ar.json @@ -20,7 +20,8 @@ "Menu:Emailing": "إرسال بالبريد الإلكتروني", "Menu:TimeZone": "وحدة زمنية", "DisplayName:Timezone": "وحدة زمنية", - "TimezoneHelpText": "يُستخدم هذا الإعداد على مستوى التطبيق أو على أساس المستأجر.", + "TimezoneHelpText": "تتيح لك هذه الميزة تعيين منطقة زمنية افتراضية لخادمك، بينما يمكن للمستخدمين اختيار منطقتهم الزمنية الخاصة. إذا اختلفت المنطقة الزمنية للمستخدم عن المنطقة الزمنية للخادم، فسيتم تعديل جميع الأوقات وفقًا لذلك. على سبيل المثال، مع تعيين الخادم على أوروبا/لندن(00:00) ومستخدم في أوروبا/باريس(+01:00)، سيتم تعديل الأوقات بساعة واحدة لذلك المستخدم. سيؤدي اختيار 'المنطقة الزمنية الافتراضية' إلى استخدام المنطقة الزمنية للخادم أو المتصفح تلقائيًا.", + "DefaultTimeZone": "الوحدة الزمنية الافتراضية", "SmtpHost": "مضيف", "SmtpPort": "ميناء", "SmtpUserName": "اسم المستخدم", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json index 983c6718b9..cd9d4d78d1 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/cs.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Zasílání e-mailem", "Menu:TimeZone": "Časové Pásmo", "DisplayName:Timezone": "Časové pásmo", - "TimezoneHelpText": "Toto nastavení se používá pro celou aplikaci nebo pro klienty.", + "TimezoneHelpText": "Tato funkce vám umožňuje nastavit výchozí časové pásmo pro váš server, zatímco uživatelé si mohou vybrat své vlastní. Pokud se časové pásmo uživatele liší od časového pásma serveru, všechny časy budou odpovídajícím způsobem upraveny. Například, když je server nastaven na Evropa/Londýn(00:00) a uživatel je v Evropa/Paříž(+01:00), časy budou pro tohoto uživatele upraveny o 1 hodinu. Výběrem 'Výchozí časové pásmo' se automaticky použije časové pásmo serveru nebo prohlížeče.", + "DefaultTimeZone": "Výchozí časové pásmo", "SmtpHost": "Hostitel", "SmtpPort": "Přístav", "SmtpUserName": "Uživatelské jméno", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json index 3f44913224..6e17d1c0dc 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de-DE.json @@ -20,7 +20,8 @@ "Menu:Emailing": "E-Mail", "Menu:TimeZone": "Zeitzone", "DisplayName:Timezone": "Zeitzone", - "TimezoneHelpText": "Diese Einstellung wird für die Anwendung oder den Mandanten verwendet.", + "TimezoneHelpText": "Diese Einstellung wird für die Anwendung oder den Mandanten verwendet. Die Standardzeitzone wird versuchen, die Zeitzone des Browsers oder des Servers zu verwenden.", + "DefaultTimeZone": "Standardzeitzone", "SmtpHost": "Host", "SmtpPort": "Port", "SmtpUserName": "Benutzername", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json index c5efcb1718..7f8debc508 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/de.json @@ -20,7 +20,9 @@ "Menu:Emailing": "E-Mail senden", "Menu:TimeZone": "Zeitzone", "DisplayName:Timezone": "Zeitzone", - "TimezoneHelpText": "Diese Einstellung wird anwendungsweit oder mandantenbasiert verwendet.", + "TimezoneHelpText": "Diese Funktion ermöglicht es Ihnen, eine Standardzeitzone für Ihren Server festzulegen, während Benutzer ihre eigene auswählen können. Wenn sich die Zeitzone eines Benutzers von der des Servers unterscheidet, werden alle Zeiten entsprechend angepasst. Zum Beispiel: Wenn der Server auf Europa/London(00:00) eingestellt ist und ein Benutzer in Europa/Paris(+01:00) ist, werden die Zeiten für diesen Benutzer um 1 Stunde angepasst. Die Auswahl von 'Standardzeitzone' verwendet automatisch die Zeitzone des Servers oder Browsers.", + "DefaultTimeZone": "Standardzeitzone", + "DefaultTimeZoneInfo": "Die Standardzeitzone wird versuchen, die Zeitzone des Browsers oder des Servers zu verwenden.", "SmtpHost": "Gastgeber", "SmtpPort": "Hafen", "SmtpUserName": "Nutzername", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json index e7d221b4ef..84933fe44b 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/en.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Emailing", "Menu:TimeZone": "Time Zone", "DisplayName:Timezone": "Time zone", - "TimezoneHelpText": "This setting is used for application-wide or tenant-based.", + "TimezoneHelpText": "This feature allows you to set a default time zone for your server, while users can select their own. If a user's time zone differs from the server's, all times will adjust accordingly. For example, with the server set to Europe/London(00:00) and a user in Europe/Paris(+01:00), times will be adjusted by 1 hour for that user. Selecting 'Default Timezone' will automatically use the server's or browser's time zone.", + "DefaultTimeZone": "Default time zone", "SmtpHost": "Host", "SmtpPort": "Port", "SmtpUserName": "User name", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json index 7d6bcd8236..bfc0ab6a3b 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Configuración", "Menu:TimeZone": "Zona Horaria", "DisplayName:Timezone": "Zona horaria", - "TimezoneHelpText": "Esta configuración se utiliza para toda la aplicación o basada en inquilinos.", + "TimezoneHelpText": "Esta función le permite establecer una zona horaria predeterminada para su servidor, mientras que los usuarios pueden seleccionar la suya propia. Si la zona horaria de un usuario difiere de la del servidor, todas las horas se ajustarán en consecuencia. Por ejemplo, con el servidor configurado en Europa/Londres(00:00) y un usuario en Europa/París(+01:00), las horas se ajustarán 1 hora para ese usuario. Al seleccionar 'Zona horaria predeterminada' se utilizará automáticamente la zona horaria del servidor o del navegador.", + "DefaultTimeZone": "Zona horaria predeterminada", "SmtpHost": "Host", "SmtpPort": "Puerto", "SmtpUserName": "Nombre de usuario", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json index 312ecf608c..f9b52baf2b 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fi.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Sähköpostiviestit", "Menu:TimeZone": "Aikavyöhyke", "DisplayName:Timezone": "Aikavyöhyke", - "TimezoneHelpText": "Tätä asetusta käytetään sovelluksenlaajuisesti tai vuokraajakohtaisesti.", + "TimezoneHelpText": "Tämä ominaisuus antaa sinun asettaa oletusaikavyöhykkeen palvelimellesi, kun taas käyttäjät voivat valita oman aikavyöhykkeensä. Jos käyttäjän aikavyöhyke poikkeaa palvelimen aikavyöhykkeestä, kaikki ajat mukautetaan vastaavasti. Esimerkiksi, kun palvelin on asetettu Eurooppa/Lontoo(00:00) ja käyttäjä on Eurooppa/Pariisi(+01:00), ajat mukautetaan tunnilla kyseiselle käyttäjälle. 'Oletusaikavyöhyke' -valinta käyttää automaattisesti palvelimen tai selaimen aikavyöhykettä.", + "DefaultTimeZone": "Oletusaikavyöhyke", "SmtpHost": "Isäntä", "SmtpPort": "Portti", "SmtpUserName": "Käyttäjänimi", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json index 3ec1a598c2..758e9a090c 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/fr.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Envoi par e-mail", "Menu:TimeZone": "Fuseau Horaire", "DisplayName:Timezone": "Fuseau horaire", - "TimezoneHelpText": "Ce paramètre est utilisé à l’échelle de l’application ou basé sur le client.", + "TimezoneHelpText": "Cette fonctionnalité vous permet de définir un fuseau horaire par défaut pour votre serveur, tandis que les utilisateurs peuvent sélectionner le leur. Si le fuseau horaire d'un utilisateur diffère de celui du serveur, tous les horaires seront ajustés en conséquence. Par exemple, avec le serveur réglé sur Europe/Londres(00:00) et un utilisateur en Europe/Paris(+01:00), les horaires seront ajustés d'une heure pour cet utilisateur. La sélection de 'Fuseau horaire par défaut' utilisera automatiquement le fuseau horaire du serveur ou du navigateur.", + "DefaultTimeZone": "Fuseau horaire par défaut", "SmtpHost": "Hôte", "SmtpPort": "Port", "SmtpUserName": "Nom d'utilisateur", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json index 786616f901..8dacb200e4 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hi.json @@ -20,7 +20,8 @@ "Menu:Emailing": "ईमेल से भेजना", "Menu:TimeZone": "समय क्षेत्र", "DisplayName:Timezone": "समय क्षेत्र", - "TimezoneHelpText": "इस सेटिंग का उपयोग एप्लिकेशन-व्यापी या किरायेदार-आधारित के लिए किया जाता है।", + "TimezoneHelpText": "यह सुविधा आपको अपने सर्वर के लिए एक डिफ़ॉल्ट समय क्षेत्र सेट करने की अनुमति देती है, जबकि उपयोगकर्ता अपना स्वयं का चुन सकते हैं। यदि किसी उपयोगकर्ता का समय क्षेत्र सर्वर के समय क्षेत्र से भिन्न है, तो सभी समय तदनुसार समायोजित किए जाएंगे। उदाहरण के लिए, सर्वर को यूरोप/लंदन(00:00) पर सेट किए जाने पर और एक उपयोगकर्ता यूरोप/पेरिस(+01:00) में होने पर, उस उपयोगकर्ता के लिए समय 1 घंटे के लिए समायोजित किया जाएगा। 'डिफ़ॉल्ट समय क्षेत्र' का चयन स्वचालित रूप से सर्वर या ब्राउज़र के समय क्षेत्र का उपयोग करेगा।", + "DefaultTimeZone": "डिफ़ॉल्ट समय क्षेत्र", "SmtpHost": "मेज़बान", "SmtpPort": "बंदरगाह", "SmtpUserName": "उपयोगकर्ता नाम", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json index acd0c132fa..133233a10f 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json @@ -7,7 +7,7 @@ "Permission:Emailing": "Slanje e-poštom", "Permission:EmailingTest": "Test slanja e-pošte", "Permission:TimeZone": "Vremenska zona", - "SendTestEmail": "Po�alji probnu e-poštu", + "SendTestEmail": "Pošalji probnu e-poštu", "SenderEmailAddress": "Adresa e-pošte pošiljatelja", "TargetEmailAddress": "Ciljana adresa e-pošte", "Subject": "Predmet", @@ -20,7 +20,9 @@ "Menu:Emailing": "Slanje e-poštom", "Menu:TimeZone": "Vremenska Zona", "DisplayName:Timezone": "Vremenska zona", - "TimezoneHelpText": "Ova se postavka koristi za cijelu aplikaciju ili zakupce.", + "TimezoneHelpText": "Ova značajka omogućuje vam postavljanje zadanog vremenskog pojasa za vaš poslužitelj, dok korisnici mogu odabrati svoj vlastiti. Ako se vremenski pojas korisnika razlikuje od vremenskog pojasa poslužitelja, sva vremena će se prilagoditi u skladu s tim. Na primjer, kada je poslužitelj postavljen na Europa/London(00:00) i korisnik je u Europa/Pariz(+01:00), vremena će se prilagoditi za 1 sat za tog korisnika. Odabirom 'Zadani vremenski pojas' automatski će se koristiti vremenski pojas poslužitelja ili preglednika.", + "DefaultTimeZone": "Zadana vremenska zona", + "DefaultTimeZoneInfo": "Zadana vremenska zona pokušat će koristiti vremensku zonu preglednika ili poslužitelja.", "SmtpHost": "Domaćin", "SmtpPort": "Port", "SmtpUserName": "Korisničko ime", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json index c47a813371..4aed2b5688 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hu.json @@ -20,7 +20,8 @@ "Menu:Emailing": "E-mailezés", "Menu:TimeZone": "Időzóna", "DisplayName:Timezone": "Időzóna", - "TimezoneHelpText": "Ez a beállítás az egész alkalmazásra vagy a bérlőre vonatkozik.", + "TimezoneHelpText": "Ez a funkció lehetővé teszi, hogy alapértelmezett időzónát állítson be a szerveréhez, miközben a felhasználók sajátot választhatnak. Ha egy felhasználó időzónája eltér a szerver időzónájától, az összes idő ennek megfelelően módosul. Például, ha a szerver Európa/London(00:00) időzónára van állítva, és egy felhasználó Európa/Párizs(+01:00) időzónában van, az időket 1 órával módosítják ennél a felhasználónál. Az 'Alapértelmezett időzóna' kiválasztása automatikusan a szerver vagy a böngésző időzónáját használja.", + "DefaultTimeZone": "Alapértelmezett időzóna", "SmtpHost": "Házigazda", "SmtpPort": "Kikötő", "SmtpUserName": "Felhasználónév", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json index f39b10f795..2106b156bc 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/is.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Senda tölvupóst", "Menu:TimeZone": "Tímabelti", "DisplayName:Timezone": "Tímabelti", - "TimezoneHelpText": "Þessi stilling er notuð fyrir allt forrit eða leigjanda.", + "TimezoneHelpText": "Þessi eiginleiki gerir þér kleift að setja sjálfgefna tímabelti fyrir þjóninn þinn, á meðan notendur geta valið sitt eigið. Ef tímabelti notanda er frábrugðið tímabelti þjónsins, verða allir tímar aðlagaðir í samræmi við það. Til dæmis, þegar þjónninn er stilltur á Evrópa/London(00:00) og notandi er í Evrópa/París(+01:00), verða tímar aðlagaðir um 1 klukkutíma fyrir þann notanda. Með því að velja 'Sjálfgefið tímabelti' verður sjálfkrafa notað tímabelti þjónsins eða vafrans.", + "DefaultTimeZone": "Sjálfgefitt tímabelti", "SmtpHost": "Smtp Host", "SmtpPort": "Port", "SmtpUserName": "Notanda nafn", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json index 3de6657509..487078c449 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/it.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Invio di e-mail", "Menu:TimeZone": "Fuso Orario", "DisplayName:Timezone": "Fuso orario", - "TimezoneHelpText": "Questa impostazione viene utilizzata per l'intera applicazione o in base al tenant.", + "TimezoneHelpText": "Questa funzione ti permette di impostare un fuso orario predefinito per il tuo server, mentre gli utenti possono selezionare il proprio. Se il fuso orario di un utente differisce da quello del server, tutti gli orari verranno adeguati di conseguenza. Ad esempio, con il server impostato su Europa/Londra(00:00) e un utente in Europa/Parigi(+01:00), gli orari verranno adeguati di 1 ora per quell'utente. Selezionando 'Fuso orario predefinito' verrà utilizzato automaticamente il fuso orario del server o del browser.", + "DefaultTimeZone": "Fuso orario predefinito", "SmtpHost": "Host", "SmtpPort": "Porta", "SmtpUserName": "Nome utente", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json index a188146d0e..06f07346e5 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/nl.json @@ -20,7 +20,8 @@ "Menu:Emailing": "E-mail", "Menu:TimeZone": "Tijdzone", "DisplayName:Timezone": "Tijdzone", - "TimezoneHelpText": "Deze instelling wordt gebruikt voor de hele toepassing of op tenantbasis.", + "TimezoneHelpText": "Deze functie stelt u in staat om een standaardtijdzone in te stellen voor uw server, terwijl gebruikers hun eigen tijdzone kunnen kiezen. Als de tijdzone van een gebruiker verschilt van die van de server, worden alle tijden dienovereenkomstig aangepast. Bijvoorbeeld, met de server ingesteld op Europa/Londen(00:00) en een gebruiker in Europa/Parijs(+01:00), worden de tijden met 1 uur aangepast voor die gebruiker. Door 'Standaardtijdzone' te selecteren wordt automatisch de tijdzone van de server of browser gebruikt.", + "DefaultTimeZone": "Standaardtijdzone", "SmtpHost": "Host", "SmtpPort": "Poort", "SmtpUserName": "Gebruikersnaam", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json index a4bbd7238e..35038ee043 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pl-PL.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Wysyłanie e-maili", "Menu:TimeZone": "Strefa Czasowa", "DisplayName:Timezone": "Strefa czasowa", - "TimezoneHelpText": "To ustawienie jest używane w przypadku całej aplikacji lub opartej na dzierżawie.", + "TimezoneHelpText": "Ta funkcja pozwala ustawić domyślną strefę czasową dla serwera, podczas gdy użytkownicy mogą wybrać własną. Jeśli strefa czasowa użytkownika różni się od strefy czasowej serwera, wszystkie czasy zostaną odpowiednio dostosowane. Na przykład, gdy serwer jest ustawiony na Europa/Londyn(00:00), a użytkownik jest w Europie/Paryżu(+01:00), czasy zostaną dostosowane o 1 godzinę dla tego użytkownika. Wybranie opcji 'Domyślna strefa czasowa' automatycznie wykorzysta strefę czasową serwera lub przeglądarki.", + "DefaultTimeZone": "Domyślna strefa czasowa", "SmtpHost": "Gospodarz", "SmtpPort": "Port", "SmtpUserName": "Nazwa użytkownika", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json index c6c951c025..9a8cf0317b 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/pt-BR.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Enviando por e-mail", "Menu:TimeZone": "Fuso Horário", "DisplayName:Timezone": "Fuso horário", - "TimezoneHelpText": "Essa configuração é usada para todo o aplicativo ou com base em locatário.", + "TimezoneHelpText": "Este recurso permite que você defina um fuso horário padrão para seu servidor, enquanto os usuários podem selecionar o seu próprio. Se o fuso horário de um usuário for diferente do fuso horário do servidor, todos os horários serão ajustados de acordo. Por exemplo, com o servidor definido como Europa/Londres(00:00) e um usuário na Europa/Paris(+01:00), os horários serão ajustados em 1 hora para esse usuário. Selecionar 'Fuso horário padrão' usará automaticamente o fuso horário do servidor ou do navegador.", + "DefaultTimeZone": "Fuso horário padrão", "SmtpHost": "Hospedeiro", "SmtpPort": "Porta", "SmtpUserName": "Nome do usuário", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json index 7e1eac80be..8029a43734 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Emailing", "Menu:TimeZone": "Fus Orar", "DisplayName:Timezone": "Fus orar", - "TimezoneHelpText": "Această setare este utilizată pentru aplicație sau pentru chiriași.", + "TimezoneHelpText": "Această funcționalitate vă permite să setați un fus orar implicit pentru serverul dvs., în timp ce utilizatorii pot selecta propriul lor. Dacă fusul orar al unui utilizator diferă de cel al serverului, toate orele vor fi ajustate în consecință. De exemplu, cu serverul setat la Europa/Londra(00:00) și un utilizator în Europa/Paris(+01:00), orele vor fi ajustate cu 1 oră pentru acel utilizator. Selectarea 'Fus orar implicit' va folosi automat fusul orar al serverului sau browserului.", + "DefaultTimeZone": "Fus orar implicit", "SmtpHost": "Host", "SmtpPort": "Port", "SmtpUserName": "Nume de utilizator", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json index 9fde67ff61..0ab1535a3b 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ru.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Отправка по электронной почте", "Menu:TimeZone": "Часовой пояс", "DisplayName:Timezone": "Часовой пояс", - "TimezoneHelpText": "Этот параметр используется для всего приложения или на уровне клиента.", + "TimezoneHelpText": "Эта функция позволяет вам установить часовой пояс по умолчанию для вашего сервера, в то время как пользователи могут выбрать свой собственный. Если часовой пояс пользователя отличается от часового пояса сервера, все время будет соответствующим образом скорректировано. Например, если сервер установлен на Европа/Лондон(00:00), а пользователь находится в Европа/Париж(+01:00), время будет скорректировано на 1 час для этого пользователя. При выборе 'Часовой пояс по умолчанию' будет автоматически использоваться часовой пояс сервера или браузера.", + "DefaultTimeZone": "Часовой пояс по умолчанию", "SmtpHost": "Хозяин", "SmtpPort": "Порт", "SmtpUserName": "Имя пользователя", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json index e06c4d9d0a..1c68a43ae5 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sk.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Posielanie emailov", "Menu:TimeZone": "Časové Pásmo", "DisplayName:Timezone": "Časové pásmo", - "TimezoneHelpText": "Toto nastavenie sa používa pre celú aplikáciu alebo pre nájomníkov.", + "TimezoneHelpText": "Táto funkcia vám umožňuje nastaviť predvolené časové pásmo pre váš server, zatiaľ čo používatelia si môžu vybrať svoje vlastné. Ak sa časové pásmo používateľa líši od časového pásma servera, všetky časy sa príslušne upravia. Napríklad, keď je server nastavený na Európa/Londýn(00:00) a používateľ je v Európa/Paríž(+01:00), časy sa pre tohto používateľa upravia o 1 hodinu. Výberom 'Predvolené časové pásmo' sa automaticky použije časové pásmo servera alebo prehliadača.", + "DefaultTimeZone": "Predvolené časové pásmo", "SmtpHost": "Host", "SmtpPort": "Port", "SmtpUserName": "Meno používateľa", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json index 509ce74e08..4805b28994 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sl.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Pošiljanje po e-pošti", "Menu:TimeZone": "Časovni Pas", "DisplayName:Timezone": "Časovni pas", - "TimezoneHelpText": "Ta nastavitev se uporablja za celotno aplikacijo ali za najemnika.", + "TimezoneHelpText": "Ta funkcija vam omogoča nastavitev privzetega časovnega pasu za vaš strežnik, medtem ko lahko uporabniki izberejo svojega. Če se časovni pas uporabnika razlikuje od časovnega pasu strežnika, se vsi časi ustrezno prilagodijo. Na primer, ko je strežnik nastavljen na Evropa/London(00:00) in je uporabnik v Evropa/Pariz(+01:00), se časi za tega uporabnika prilagodijo za 1 uro. Z izbiro 'Privzeti časovni pas' se samodejno uporabi časovni pas strežnika ali brskalnika.", + "DefaultTimeZone": "Privzeto časovno pas", "SmtpHost": "Gostitelj", "SmtpPort": "pristanišče", "SmtpUserName": "Uporabniško ime", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json index ad74a9c147..ebbdad2b32 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/sv.json @@ -19,7 +19,8 @@ "Menu:Emailing": "E-post", "Menu:TimeZone": "Tidszon", "DisplayName:Timezone": "Tidszon", - "TimezoneHelpText": "Denna inställning används för applikationsomfattande eller hyresgästbaserad.", + "TimezoneHelpText": "Denna inställning används för applikationsomfattande eller hyresgästbaserad. Standardtidszonen kommer att försöka använda webbläsarens eller serverns tidszon.", + "DefaultTimeZone": "Standardtidszon", "SmtpHost": "Värd", "SmtpPort": "Port", "SmtpUserName": "Användarens namn", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json index aab8928026..3b7fc2ac5f 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/tr.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Email", "Menu:TimeZone": "Zaman Dilimi", "DisplayName:Timezone": "Zaman dilimi", - "TimezoneHelpText": "Bu ayar uygulama genelinde veya müşteri tabanlı olarak kullanılır.", + "TimezoneHelpText": "Bu özellik, kullanıcılar kendi saat dilimlerini seçebilirken, sunucunuz için varsayılan bir saat dilimi ayarlamanıza olanak tanır. Bir kullanıcının saat dilimi sunucunun saat diliminden farklıysa, tüm saatler buna göre ayarlanacaktır. Örneğin, sunucu Avrupa/Londra(00:00) olarak ayarlandığında ve bir kullanıcı Avrupa/Paris(+01:00)'te olduğunda, o kullanıcı için saatler 1 saat ayarlanacaktır. 'Varsayılan Saat Dilimi' seçimi otomatik olarak sunucunun veya tarayıcının saat dilimini kullanacaktır.", + "DefaultTimeZone": "Varsayılan saat dilimi", "SmtpHost": "Sunucu", "SmtpPort": "Port", "SmtpUserName": "Kullanıcı adı", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json index 94acb63a71..a9cc466fdb 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/vi.json @@ -20,7 +20,8 @@ "Menu:Emailing": "Gửi email", "Menu:TimeZone": "Múi Giờ", "DisplayName:Timezone": "Múi giờ", - "TimezoneHelpText": "Cài đặt này được sử dụng cho toàn bộ ứng dụng hoặc dựa trên đối tượng thuê.", + "TimezoneHelpText": "Tính năng này cho phép bạn đặt múi giờ mặc định cho máy chủ của mình, trong khi người dùng có thể chọn múi giờ của riêng họ. Nếu múi giờ của người dùng khác với múi giờ của máy chủ, tất cả thời gian sẽ được điều chỉnh tương ứng. Ví dụ: với máy chủ được đặt ở Châu Âu/Luân Đôn(00:00) và người dùng ở Châu Âu/Paris(+01:00), thời gian sẽ được điều chỉnh 1 giờ cho người dùng đó. Chọn 'Múi giờ mặc định' sẽ tự động sử dụng múi giờ của máy chủ hoặc trình duyệt.", + "DefaultTimeZone": "Múi giờ mặc định", "SmtpHost": "Tổ chức", "SmtpPort": "Hải cảng", "SmtpUserName": "Tên tài khoản", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json index 339f14e292..3aad0b9e8a 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json @@ -20,7 +20,8 @@ "Menu:Emailing": "邮件", "Menu:TimeZone": "时区", "DisplayName:Timezone": "时区", - "TimezoneHelpText": "此设置用于应用程序范围或基于租户。", + "TimezoneHelpText": "此功能允许您为服务器设置默认时区,同时用户可以选择自己的时区。如果用户的时区与服务器的时区不同,所有时间将相应调整。例如,如果服务器设置为欧洲/伦敦(00:00),而用户在欧洲/巴黎(+01:00),则该用户的时间将调整1小时。选择'默认时区'将自动使用服务器或浏览器的时区。", + "DefaultTimeZone": "默认时区", "SmtpHost": "主机", "SmtpPort": "端口", "SmtpUserName": "用户名", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json index e3a06511c2..77c586efe4 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hant.json @@ -20,7 +20,8 @@ "Menu:Emailing": "信箱", "Menu:TimeZone": "時區", "DisplayName:Timezone": "時區", - "TimezoneHelpText": "此設置用於應用程序範圍或基於租戶。", + "TimezoneHelpText": "此功能允許您為伺服器設置預設時區,同時用戶可以選擇自己的時區。如果用戶的時區與伺服器的時區不同,所有時間將相應調整。例如,如果伺服器設置為歐洲/倫敦(00:00),而用戶在歐洲/巴黎(+01:00),則該用戶的時間將調整1小時。選擇'預設時區'將自動使用伺服器或瀏覽器的時區。", + "DefaultTimeZone": "預設時區", "SmtpHost": "主機", "SmtpPort": "Port", "SmtpUserName": "帳號", diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs index ddf451154d..b3fd120f38 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain/Volo/Abp/SettingManagement/SettingManager.cs @@ -136,7 +136,7 @@ public class SettingManager : ISettingManager, ISingletonDependency if (providers.Count > 1 && !forceToSet && setting.IsInherited && value != null) { var fallbackValue = await GetOrNullInternalAsync(name, providers[1].Name, null); - if (fallbackValue == value) + if (string.Equals(fallbackValue, value, StringComparison.OrdinalIgnoreCase)) { //Clear the value if it's same as it's fallback value value = null; diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/AngularInstallationInfo.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/AngularInstallationInfo.json new file mode 100644 index 0000000000..987f8f72ea --- /dev/null +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/AngularInstallationInfo.json @@ -0,0 +1,47 @@ +{ + "packages":[ + { + "name": "@abp/ng.setting-management", + "appRoutingModuleConfiguration":{ + "routes":[ + "{ path: 'setting-management', loadChildren: () => import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()),}" + ] + }, + "appModuleConfiguration":{ + "imports":[ + { + "names":[ + "provideSettingManagementConfig" + ], + "namespace": "@abp/ng.setting-management/config" + } + ], + "ngModuleImports":[ + ], + "providerNames":[ + "provideSettingManagementConfig()" + ] + }, + "tsJsonPathRecordConfigurations":[ + { + "name": "@abp/ng.setting-management", + "paths": [ + "angular/projects/setting-management/src/public-api.ts" + ] + }, + { + "name": "@abp/ng.setting-management/config", + "paths": [ + "angular/projects/setting-management/config/src/public-api.ts" + ] + }, + { + "name": "@abp/ng.setting-management/proxy", + "paths": [ + "angular/projects/setting-management/proxy/src/public-api.ts" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/Volo.Abp.SettingManagement.Installer.csproj b/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/Volo.Abp.SettingManagement.Installer.csproj index c0c5281afe..7a4b257929 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/Volo.Abp.SettingManagement.Installer.csproj +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Installer/Volo.Abp.SettingManagement.Installer.csproj @@ -25,6 +25,8 @@ true content\ + + diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.cshtml b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.cshtml index c146118cb3..11d9af9637 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.cshtml +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.cshtml @@ -1,18 +1,18 @@ @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.SettingManagement.Localization @inject IHtmlLocalizer L -@model Volo.Abp.SettingManagement.Web.Pages.SettingManagement.Components.TimeZoneSettingGroup.TimeZoneSettingGroupViewComponent.UpdateTimezoneSettingsViewModel -
- + +
+
@L["TimezoneHelpText"].Value
- + @L["Save"]
diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.js b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.js index d6e720dbe3..aebbe66352 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.js +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.js @@ -3,13 +3,28 @@ var l = abp.localization.getResource('AbpSettingManagement'); + var select2 = null; + volo.abp.settingManagement.timeZoneSettings.getTimezones().then(function (result) { + var data = $.map(result, function (obj) { + obj.id = obj.value; + obj.text = obj.name; + return obj; + }); + + select2 = $("#timezone-select").select2({ + data: data + }); + + volo.abp.settingManagement.timeZoneSettings.get().then(function (result) { + select2.val(result).trigger("change"); + }); + }); + $("#TimeZoneSettingsForm").on('submit', function (event) { event.preventDefault(); - - volo.abp.settingManagement.timeZoneSettings.update($("#Timezone").val()).then(function (result) { + volo.abp.settingManagement.timeZoneSettings.update($("#timezone-select").val()).then(function (result) { $(document).trigger("AbpSettingSaved"); }); - }); }); })(jQuery); diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/TimeZoneSettingGroupViewComponent.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/TimeZoneSettingGroupViewComponent.cs index eaf24ab2f2..9c22152a6f 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/TimeZoneSettingGroupViewComponent.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Components/TimeZoneSettingGroup/TimeZoneSettingGroupViewComponent.cs @@ -1,42 +1,18 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Rendering; using Volo.Abp.AspNetCore.Mvc; -using Volo.Abp.Auditing; -using Volo.Abp.Timing.Localization.Resources.AbpTiming; namespace Volo.Abp.SettingManagement.Web.Pages.SettingManagement.Components.TimeZoneSettingGroup; public class TimeZoneSettingGroupViewComponent : AbpViewComponent { - protected ITimeZoneSettingsAppService TimeZoneSettingsAppService { get; } - public TimeZoneSettingGroupViewComponent(ITimeZoneSettingsAppService timeZoneSettingsAppService) { ObjectMapperContext = typeof(AbpSettingManagementWebModule); - TimeZoneSettingsAppService = timeZoneSettingsAppService; } public virtual async Task InvokeAsync() { - var timezone = await TimeZoneSettingsAppService.GetAsync(); - var timezones = await TimeZoneSettingsAppService.GetTimezonesAsync(); - var model = new UpdateTimezoneSettingsViewModel() - { - Timezone = timezone, - TimeZoneItems = new List() - }; - model.TimeZoneItems.AddRange(timezones.Select(x => new SelectListItem(x.Name, x.Value)).ToList()); - return View("~/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.cshtml", model); - } - - public class UpdateTimezoneSettingsViewModel - { - public string Timezone { get; set; } - - public List TimeZoneItems { get; set; } + return View("~/Pages/SettingManagement/Components/TimeZoneSettingGroup/Default.cshtml"); } } diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml index 7fa674f4be..d31670a036 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Web/Pages/SettingManagement/Index.cshtml @@ -35,7 +35,7 @@
-
+
diff --git a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj index 9c2c2f36a9..9bbb27387d 100644 --- a/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj +++ b/modules/setting-management/test/Volo.Abp.SettingManagement.MongoDB.Tests/Volo.Abp.SettingManagement.MongoDB.Tests.csproj @@ -19,9 +19,9 @@ - - - + + + diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantValidator.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantValidator.cs new file mode 100644 index 0000000000..badd9515b8 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantValidator.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.TenantManagement; + +public class AbpTenantValidator : ITenantValidator, ITransientDependency +{ + protected ITenantRepository TenantRepository { get; } + + public AbpTenantValidator(ITenantRepository tenantRepository) + { + TenantRepository = tenantRepository; + } + + public virtual async Task ValidateAsync(Tenant tenant) + { + Check.NotNullOrWhiteSpace(tenant.Name, nameof(tenant.Name)); + Check.NotNullOrWhiteSpace(tenant.NormalizedName, nameof(tenant.NormalizedName)); + + var owner = await TenantRepository.FindByNameAsync(tenant.NormalizedName); + if (owner != null && owner.Id != tenant.Id) + { + throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", tenant.NormalizedName); + } + } +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantValidator.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantValidator.cs new file mode 100644 index 0000000000..3a5cc9ffb0 --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/ITenantValidator.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.TenantManagement; + +public interface ITenantValidator +{ + Task ValidateAsync(Tenant tenant); +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs index 0f40cfdd0b..91cdf87abb 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/TenantManager.cs @@ -1,6 +1,4 @@ -using System; -using System.Threading.Tasks; -using Volo.Abp.Caching; +using System.Threading.Tasks; using Volo.Abp.Domain.Services; using Volo.Abp.EventBus.Local; using Volo.Abp.MultiTenancy; @@ -9,16 +7,16 @@ namespace Volo.Abp.TenantManagement; public class TenantManager : DomainService, ITenantManager { - protected ITenantRepository TenantRepository { get; } + protected ITenantValidator TenantValidator { get; } protected ITenantNormalizer TenantNormalizer { get; } protected ILocalEventBus LocalEventBus { get; } public TenantManager( - ITenantRepository tenantRepository, + ITenantValidator tenantValidator, ITenantNormalizer tenantNormalizer, ILocalEventBus localEventBus) { - TenantRepository = tenantRepository; + TenantValidator = tenantValidator; TenantNormalizer = tenantNormalizer; LocalEventBus = localEventBus; } @@ -27,9 +25,9 @@ public class TenantManager : DomainService, ITenantManager { Check.NotNull(name, nameof(name)); - var normalizedName = TenantNormalizer.NormalizeName(name); - await ValidateNameAsync(normalizedName); - return new Tenant(GuidGenerator.Create(), name, normalizedName); + var tenant = new Tenant(GuidGenerator.Create(), name, TenantNormalizer.NormalizeName(name)); + await TenantValidator.ValidateAsync(tenant); + return tenant; } public virtual async Task ChangeNameAsync(Tenant tenant, string name) @@ -37,20 +35,10 @@ public class TenantManager : DomainService, ITenantManager Check.NotNull(tenant, nameof(tenant)); Check.NotNull(name, nameof(name)); - var normalizedName = TenantNormalizer.NormalizeName(name); - - await ValidateNameAsync(normalizedName, tenant.Id); await LocalEventBus.PublishAsync(new TenantChangedEvent(tenant.Id, tenant.NormalizedName)); - tenant.SetName(name); - tenant.SetNormalizedName(normalizedName); - } - protected virtual async Task ValidateNameAsync(string normalizeName, Guid? expectedId = null) - { - var tenant = await TenantRepository.FindByNameAsync(normalizeName); - if (tenant != null && tenant.Id != expectedId) - { - throw new BusinessException("Volo.Abp.TenantManagement:DuplicateTenantName").WithData("Name", normalizeName); - } + tenant.SetName(name); + tenant.SetNormalizedName( TenantNormalizer.NormalizeName(name)); + await TenantValidator.ValidateAsync(tenant); } } diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/AngularInstallationInfo.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/AngularInstallationInfo.json new file mode 100644 index 0000000000..700380b9ca --- /dev/null +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/AngularInstallationInfo.json @@ -0,0 +1,47 @@ +{ + "packages":[ + { + "name": "@abp/ng.tenant-management", + "appRoutingModuleConfiguration":{ + "routes":[ + "{ path: 'tenant-management', loadChildren: () => import('@abp/ng.tenant-management').then(m => m.TenantManagementModule.forLazy()),}" + ] + }, + "appModuleConfiguration":{ + "imports":[ + { + "names":[ + "provideTenantManagementConfig" + ], + "namespace": "@abp/ng.tenant-management/config" + } + ], + "ngModuleImports":[ + ], + "providerNames":[ + "provideTenantManagementConfig()" + ] + }, + "tsJsonPathRecordConfigurations":[ + { + "name": "@abp/ng.tenant-management", + "paths": [ + "angular/projects/tenant-management/src/public-api.ts" + ] + }, + { + "name": "@abp/ng.tenant-management/config", + "paths": [ + "angular/projects/tenant-management/config/src/public-api.ts" + ] + }, + { + "name": "@abp/ng.tenant-management/proxy", + "paths": [ + "angular/projects/tenant-management/proxy/src/public-api.ts" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo.Abp.TenantManagement.Installer.csproj b/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo.Abp.TenantManagement.Installer.csproj index 1375f5bfe7..af992ef8de 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo.Abp.TenantManagement.Installer.csproj +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Installer/Volo.Abp.TenantManagement.Installer.csproj @@ -25,6 +25,8 @@ true content\ + + diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantNameValidator_Tests.cs b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantNameValidator_Tests.cs new file mode 100644 index 0000000000..bc1477d1ff --- /dev/null +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.Domain.Tests/Volo/Abp/TenantManagement/TenantNameValidator_Tests.cs @@ -0,0 +1,47 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.TenantManagement; + +public class TenantValidator_Tests : AbpTenantManagementDomainTestBase +{ + private readonly TenantManager _tenantManager; + private readonly ITenantRepository _tenantRepository; + + public TenantValidator_Tests() + { + _tenantManager = GetRequiredService(); + _tenantRepository = GetRequiredService(); + } + + [Fact] + public async Task Should_Throw_If_Name_Is_Null() + { + await Assert.ThrowsAsync(() => _tenantManager.CreateAsync("")); + } + + [Fact] + public async Task Should_Throw_If_Duplicate_Name() + { + await Assert.ThrowsAsync(() => _tenantManager.CreateAsync("VOLOSOFT")); + + var tenant = await _tenantRepository.FindByNameAsync("ABP"); + await Assert.ThrowsAsync(() => _tenantManager.ChangeNameAsync(tenant, "VOLOSOFT")); + } + + [Fact] + public async Task Should_Not_Throw_For_Unique_Name() + { + var tenant = await _tenantManager.CreateAsync("VOLOSOFT2"); + await _tenantRepository.InsertAsync(tenant); + + tenant = await _tenantRepository.FindByNameAsync("ABP"); + await _tenantManager.ChangeNameAsync(tenant, "VOLOSOFT3"); + await _tenantRepository.UpdateAsync(tenant); + + tenant = await _tenantRepository.FindByNameAsync("VOLOSOFT3"); + tenant.ShouldNotBeNull(); + } +} diff --git a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj index 2913a0ed53..4ad25e0218 100644 --- a/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj +++ b/modules/tenant-management/test/Volo.Abp.TenantManagement.MongoDB.Tests/Volo.Abp.TenantManagement.MongoDB.Tests.csproj @@ -19,9 +19,9 @@ - - - + + + diff --git a/modules/virtual-file-explorer/app/DemoApp.abppkg.analyze.json b/modules/virtual-file-explorer/app/DemoApp.abppkg.analyze.json new file mode 100644 index 0000000000..6adec15576 --- /dev/null +++ b/modules/virtual-file-explorer/app/DemoApp.abppkg.analyze.json @@ -0,0 +1,158 @@ +{ + "name": "DemoApp", + "hash": "", + "contents": [ + { + "namespace": "DemoApp", + "dependsOnModules": [ + { + "declaringAssemblyName": "Volo.Abp.AspNetCore.Mvc", + "namespace": "Volo.Abp.AspNetCore.Mvc", + "name": "AbpAspNetCoreMvcModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Autofac", + "namespace": "Volo.Abp.Autofac", + "name": "AbpAutofacModule" + }, + { + "declaringAssemblyName": "Volo.Abp.AutoMapper", + "namespace": "Volo.Abp.AutoMapper", + "name": "AbpAutoMapperModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Swashbuckle", + "namespace": "Volo.Abp.Swashbuckle", + "name": "AbpSwashbuckleModule" + }, + { + "declaringAssemblyName": "Volo.Abp.AspNetCore.Serilog", + "namespace": "Volo.Abp.AspNetCore.Serilog", + "name": "AbpAspNetCoreSerilogModule" + }, + { + "declaringAssemblyName": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", + "namespace": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic", + "name": "AbpAspNetCoreMvcUiBasicThemeModule" + }, + { + "declaringAssemblyName": "Volo.Abp.VirtualFileExplorer.Web", + "namespace": "Volo.Abp.VirtualFileExplorer.Web", + "name": "AbpVirtualFileExplorerWebModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Account.Web", + "namespace": "Volo.Abp.Account.Web", + "name": "AbpAccountWebModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Account.HttpApi", + "namespace": "Volo.Abp.Account", + "name": "AbpAccountHttpApiModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Account.Application", + "namespace": "Volo.Abp.Account", + "name": "AbpAccountApplicationModule" + }, + { + "declaringAssemblyName": "Volo.Abp.PermissionManagement.Domain.Identity", + "namespace": "Volo.Abp.PermissionManagement.Identity", + "name": "AbpPermissionManagementDomainIdentityModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Identity.Web", + "namespace": "Volo.Abp.Identity.Web", + "name": "AbpIdentityWebModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Identity.HttpApi", + "namespace": "Volo.Abp.Identity", + "name": "AbpIdentityHttpApiModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Identity.Application", + "namespace": "Volo.Abp.Identity", + "name": "AbpIdentityApplicationModule" + }, + { + "declaringAssemblyName": "Volo.Abp.Identity.EntityFrameworkCore", + "namespace": "Volo.Abp.Identity.EntityFrameworkCore", + "name": "AbpIdentityEntityFrameworkCoreModule" + }, + { + "declaringAssemblyName": "Volo.Abp.PermissionManagement.Web", + "namespace": "Volo.Abp.PermissionManagement.Web", + "name": "AbpPermissionManagementWebModule" + }, + { + "declaringAssemblyName": "Volo.Abp.PermissionManagement.Application", + "namespace": "Volo.Abp.PermissionManagement", + "name": "AbpPermissionManagementApplicationModule" + }, + { + "declaringAssemblyName": "Volo.Abp.PermissionManagement.HttpApi", + "namespace": "Volo.Abp.PermissionManagement.HttpApi", + "name": "AbpPermissionManagementHttpApiModule" + }, + { + "declaringAssemblyName": "Volo.Abp.PermissionManagement.EntityFrameworkCore", + "namespace": "Volo.Abp.PermissionManagement.EntityFrameworkCore", + "name": "AbpPermissionManagementEntityFrameworkCoreModule" + }, + { + "declaringAssemblyName": "Volo.Abp.EntityFrameworkCore.SqlServer", + "namespace": "Volo.Abp.EntityFrameworkCore.SqlServer", + "name": "AbpEntityFrameworkCoreSqlServerModule" + } + ], + "implementingInterfaces": [ + { + "name": "IAbpModule", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IAbpModule" + }, + { + "name": "IOnPreApplicationInitialization", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IOnPreApplicationInitialization" + }, + { + "name": "IOnApplicationInitialization", + "namespace": "Volo.Abp", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.IOnApplicationInitialization" + }, + { + "name": "IOnPostApplicationInitialization", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IOnPostApplicationInitialization" + }, + { + "name": "IOnApplicationShutdown", + "namespace": "Volo.Abp", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.IOnApplicationShutdown" + }, + { + "name": "IPreConfigureServices", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IPreConfigureServices" + }, + { + "name": "IPostConfigureServices", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IPostConfigureServices" + } + ], + "contentType": "abpModule", + "name": "DemoAppModule", + "summary": null + } + ] +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/app/package.json b/modules/virtual-file-explorer/app/package.json index e14fdf7d3d..55f5e8cf07 100644 --- a/modules/virtual-file-explorer/app/package.json +++ b/modules/virtual-file-explorer/app/package.json @@ -3,7 +3,7 @@ "name": "my-app", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.1", - "@abp/virtual-file-explorer": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4", + "@abp/virtual-file-explorer": "~9.2.0-rc.4" } } diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg.analyze.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg.analyze.json index 0f37f00591..65361601a2 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg.analyze.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Contracts/Volo.Abp.VirtualFileExplorer.Contracts.abppkg.analyze.json @@ -1,7 +1,57 @@ { - "name": "Volo.Abp.VirtualFileExplorer.Contracts", - "hash": "", - "contents": [ - - ] - } \ No newline at end of file + "name": "Volo.Abp.VirtualFileExplorer.Contracts", + "hash": "", + "contents": [ + { + "namespace": "Volo.Abp.VirtualFileExplorer", + "dependsOnModules": [], + "implementingInterfaces": [ + { + "name": "IAbpModule", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IAbpModule" + }, + { + "name": "IOnPreApplicationInitialization", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IOnPreApplicationInitialization" + }, + { + "name": "IOnApplicationInitialization", + "namespace": "Volo.Abp", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.IOnApplicationInitialization" + }, + { + "name": "IOnPostApplicationInitialization", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IOnPostApplicationInitialization" + }, + { + "name": "IOnApplicationShutdown", + "namespace": "Volo.Abp", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.IOnApplicationShutdown" + }, + { + "name": "IPreConfigureServices", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IPreConfigureServices" + }, + { + "name": "IPostConfigureServices", + "namespace": "Volo.Abp.Modularity", + "declaringAssemblyName": "Volo.Abp.Core", + "fullName": "Volo.Abp.Modularity.IPostConfigureServices" + } + ], + "contentType": "abpModule", + "name": "AbpVirtualFileExplorerContractsModule", + "summary": null + } + ] +} \ No newline at end of file diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.abppkg.analyze.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.abppkg.analyze.json index 8665e359e5..2b6f122188 100644 --- a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.abppkg.analyze.json +++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Volo.Abp.VirtualFileExplorer.Web.abppkg.analyze.json @@ -14,6 +14,11 @@ "declaringAssemblyName": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared", "namespace": "Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared", "name": "AbpAspNetCoreMvcUiThemeSharedModule" + }, + { + "declaringAssemblyName": "Volo.Abp.VirtualFileExplorer.Contracts", + "namespace": "Volo.Abp.VirtualFileExplorer", + "name": "AbpVirtualFileExplorerContractsModule" } ], "implementingInterfaces": [ diff --git a/npm/lerna.json b/npm/lerna.json index a92f94ee5a..76c12999c1 100644 --- a/npm/lerna.json +++ b/npm/lerna.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "packages": [ "packs/*" ], diff --git a/npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts b/npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts deleted file mode 100644 index 0d9f82ea25..0000000000 --- a/npm/ng-packs/apps/dev-app/src/app/app-routing.module.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -const routes: Routes = [ - { - path: '', - pathMatch: 'full', - loadChildren: () => import('./home/home.module').then(m => m.HomeModule), - }, - { - path: 'account', - loadChildren: () => import('@abp/ng.account').then(m => m.AccountModule.forLazy()), - }, - { - path: 'identity', - loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()), - }, - { - path: 'tenant-management', - loadChildren: () => - import('@abp/ng.tenant-management').then(m => m.TenantManagementModule.forLazy()), - }, - { - path: 'setting-management', - loadChildren: () => - import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()), - }, -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes, {})], - exports: [RouterModule], -}) -export class AppRoutingModule {} diff --git a/npm/ng-packs/apps/dev-app/src/app/app.component.ts b/npm/ng-packs/apps/dev-app/src/app/app.component.ts index 1b0993cd2f..5220d57353 100644 --- a/npm/ng-packs/apps/dev-app/src/app/app.component.ts +++ b/npm/ng-packs/apps/dev-app/src/app/app.component.ts @@ -1,12 +1,14 @@ import { Component } from '@angular/core'; +import { InternetConnectionStatusComponent, LoaderBarComponent } from '@abp/ng.theme.shared'; +import { DynamicLayoutComponent } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'app-root', template: ` `, + imports: [LoaderBarComponent, DynamicLayoutComponent, InternetConnectionStatusComponent], }) export class AppComponent {} diff --git a/npm/ng-packs/apps/dev-app/src/app/app.config.ts b/npm/ng-packs/apps/dev-app/src/app/app.config.ts new file mode 100644 index 0000000000..3075c477fc --- /dev/null +++ b/npm/ng-packs/apps/dev-app/src/app/app.config.ts @@ -0,0 +1,42 @@ +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; +import { provideRouter } from '@angular/router'; + +import { appRoutes } from './app.routes'; +import { APP_ROUTE_PROVIDER } from './route.provider'; +import { provideAbpCore, withOptions } from '@abp/ng.core'; +import { environment } from '../environments/environment'; +import { registerLocale } from '@abp/ng.core/locale'; +import { provideAbpOAuth } from '@abp/ng.oauth'; +import { provideAbpThemeShared } from '@abp/ng.theme.shared'; +import { provideSettingManagementConfig } from '@abp/ng.setting-management/config'; +import { provideAccountConfig } from '@abp/ng.account/config'; +import { provideIdentityConfig } from '@abp/ng.identity/config'; +import { provideTenantManagementConfig } from '@abp/ng.tenant-management/config'; +import { provideFeatureManagementConfig } from '@abp/ng.feature-management'; +import { provideThemeBasicConfig } from '@abp/ng.theme.basic'; +import { provideAnimations } from '@angular/platform-browser/animations'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(appRoutes), + APP_ROUTE_PROVIDER, + provideAbpCore( + withOptions({ + environment, + registerLocaleFn: registerLocale(), + sendNullsAsQueryParam: false, + skipGetAppConfiguration: false, + }), + ), + provideAbpOAuth(), + provideAbpThemeShared(), + provideSettingManagementConfig(), + provideAccountConfig(), + provideIdentityConfig(), + provideTenantManagementConfig(), + provideFeatureManagementConfig(), + provideZoneChangeDetection({ eventCoalescing: true }), + provideThemeBasicConfig(), + provideAnimations(), + ], +}; diff --git a/npm/ng-packs/apps/dev-app/src/app/app.module.ts b/npm/ng-packs/apps/dev-app/src/app/app.module.ts deleted file mode 100644 index 707f1f846f..0000000000 --- a/npm/ng-packs/apps/dev-app/src/app/app.module.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { CoreModule, provideAbpCore, withOptions } from '@abp/ng.core'; -import { registerLocale } from '@abp/ng.core/locale'; -import { - InternetConnectionStatusComponent, - ThemeSharedModule, - provideAbpThemeShared, -} from '@abp/ng.theme.shared'; -import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x'; -import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts'; -import { provideAbpOAuth } from '@abp/ng.oauth'; -import { provideSettingManagementConfig } from '@abp/ng.setting-management/config'; -import { provideAccountConfig } from '@abp/ng.account/config'; -import { provideIdentityConfig } from '@abp/ng.identity/config'; -import { provideTenantManagementConfig } from '@abp/ng.tenant-management/config'; -import { provideFeatureManagementConfig } from '@abp/ng.feature-management'; -import { AccountLayoutModule } from '@abp/ng.theme.lepton-x/account'; -import { environment } from '../environments/environment'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { APP_ROUTE_PROVIDER } from './route.provider'; - -@NgModule({ - imports: [ - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, - CoreModule, - ThemeSharedModule, - ThemeLeptonXModule.forRoot(), - SideMenuLayoutModule.forRoot(), - AccountLayoutModule.forRoot(), - InternetConnectionStatusComponent, - ], - providers: [ - APP_ROUTE_PROVIDER, - provideAbpCore( - withOptions({ - environment, - registerLocaleFn: registerLocale(), - sendNullsAsQueryParam: false, - skipGetAppConfiguration: false, - }), - ), - provideAbpOAuth(), - provideAbpThemeShared(), - provideSettingManagementConfig(), - provideAccountConfig(), - provideIdentityConfig(), - provideTenantManagementConfig(), - provideFeatureManagementConfig(), - ], - declarations: [AppComponent], - bootstrap: [AppComponent], -}) -export class AppModule {} diff --git a/npm/ng-packs/apps/dev-app/src/app/app.routes.ts b/npm/ng-packs/apps/dev-app/src/app/app.routes.ts new file mode 100644 index 0000000000..47462b7f8f --- /dev/null +++ b/npm/ng-packs/apps/dev-app/src/app/app.routes.ts @@ -0,0 +1,25 @@ +import { Routes } from '@angular/router'; + +export const appRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + loadComponent: () => import('./home/home.component').then(m => m.HomeComponent), + }, + { + path: 'account', + loadChildren: () => import('@abp/ng.account').then(m => m.createRoutes()), + }, + { + path: 'identity', + loadChildren: () => import('@abp/ng.identity').then(m => m.createRoutes()), + }, + { + path: 'tenant-management', + loadChildren: () => import('@abp/ng.tenant-management').then(m => m.createRoutes()), + }, + { + path: 'setting-management', + loadChildren: () => import('@abp/ng.setting-management').then(m => m.createRoutes()), + }, +]; diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts b/npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts deleted file mode 100644 index 7089990134..0000000000 --- a/npm/ng-packs/apps/dev-app/src/app/home/home-routing.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import { HomeComponent } from './home.component'; - -const routes: Routes = [{ path: '', component: HomeComponent }]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class HomeRoutingModule {} diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts index ad791cabec..4a6287a7c0 100644 --- a/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts +++ b/npm/ng-packs/apps/dev-app/src/app/home/home.component.ts @@ -1,10 +1,12 @@ -import { AuthService } from '@abp/ng.core'; +import { AuthService, LocalizationPipe } from '@abp/ng.core'; import { Component, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ButtonComponent, CardBodyComponent, CardComponent } from '@abp/ng.theme.shared'; @Component({ - standalone: false, selector: 'app-home', templateUrl: './home.component.html', + imports: [CommonModule, LocalizationPipe, CardComponent, CardBodyComponent, ButtonComponent], }) export class HomeComponent { protected readonly authService = inject(AuthService); diff --git a/npm/ng-packs/apps/dev-app/src/app/home/home.module.ts b/npm/ng-packs/apps/dev-app/src/app/home/home.module.ts deleted file mode 100644 index 72d20ccc65..0000000000 --- a/npm/ng-packs/apps/dev-app/src/app/home/home.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NgModule } from '@angular/core'; -import { SharedModule } from '../shared/shared.module'; -import { HomeRoutingModule } from './home-routing.module'; -import { HomeComponent } from './home.component'; - -@NgModule({ - declarations: [HomeComponent], - imports: [SharedModule, HomeRoutingModule], -}) -export class HomeModule {} diff --git a/npm/ng-packs/apps/dev-app/src/app/shared/shared.module.ts b/npm/ng-packs/apps/dev-app/src/app/shared/shared.module.ts deleted file mode 100644 index 964170499d..0000000000 --- a/npm/ng-packs/apps/dev-app/src/app/shared/shared.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { CoreModule } from '@abp/ng.core'; -import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgModule } from '@angular/core'; -import { ThemeSharedModule } from '@abp/ng.theme.shared'; -import { NgxValidateCoreModule } from '@ngx-validate/core'; - -@NgModule({ - declarations: [], - imports: [CoreModule, ThemeSharedModule, NgbDropdownModule, NgxValidateCoreModule], - exports: [CoreModule, ThemeSharedModule, NgbDropdownModule, NgxValidateCoreModule], - providers: [], -}) -export class SharedModule {} diff --git a/npm/ng-packs/apps/dev-app/src/main.ts b/npm/ng-packs/apps/dev-app/src/main.ts index fa4e0aef33..7180ec1a32 100644 --- a/npm/ng-packs/apps/dev-app/src/main.ts +++ b/npm/ng-packs/apps/dev-app/src/main.ts @@ -1,13 +1,5 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { AppComponent } from './app/app.component'; -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index e04e70b5cd..8930406a56 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.2.0-rc.1", - "@abp/utils": "~9.2.0-rc.1", + "@abp/ng.theme.lepton-x": "~4.2.0-rc.4", + "@abp/utils": "~9.2.0-rc.4", "@angular-devkit/build-angular": "~19.1.0", "@angular-devkit/core": "~19.1.0", "@angular-devkit/schematics": "~19.1.0", diff --git a/npm/ng-packs/packages/account-core/package.json b/npm/ng-packs/packages/account-core/package.json index 639809f9c5..b472d6bf03 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.2.0-rc.1", + "version": "9.2.0-rc.4", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.core": "~9.2.0-rc.1", - "@abp/ng.theme.shared": "~9.2.0-rc.1", + "@abp/ng.core": "~9.2.0-rc.4", + "@abp/ng.theme.shared": "~9.2.0-rc.4", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts index b152237503..15baeae9f8 100644 --- a/npm/ng-packs/packages/account/config/src/providers/route.provider.ts +++ b/npm/ng-packs/packages/account/config/src/providers/route.provider.ts @@ -24,12 +24,14 @@ export function configureRoutes() { path: '/account/login', name: eAccountRouteNames.Login, parentName: eAccountRouteNames.Account, + layout: eLayoutType.account, order: 1, }, { path: '/account/register', name: eAccountRouteNames.Register, parentName: eAccountRouteNames.Account, + layout: eLayoutType.account, order: 2, }, { @@ -45,12 +47,14 @@ export function configureRoutes() { path: '/account/forgot-password', parentName: eAccountRouteNames.Account, name: eAccountRouteNames.ForgotPassword, + layout: eLayoutType.account, invisible: true, }, { path: '/account/reset-password', parentName: eAccountRouteNames.Account, name: eAccountRouteNames.ResetPassword, + layout: eLayoutType.account, invisible: true, }, ]); diff --git a/npm/ng-packs/packages/account/package.json b/npm/ng-packs/packages/account/package.json index 6625f149c8..6c608b2245 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.2.0-rc.1", + "version": "9.2.0-rc.4", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.account.core": "~9.2.0-rc.1", - "@abp/ng.theme.shared": "~9.2.0-rc.1", + "@abp/ng.account.core": "~9.2.0-rc.4", + "@abp/ng.theme.shared": "~9.2.0-rc.4", "tslib": "^2.0.0" }, "publishConfig": { diff --git a/npm/ng-packs/packages/account/src/lib/account.module.ts b/npm/ng-packs/packages/account/src/lib/account.module.ts index 58df433232..31c629bb4d 100644 --- a/npm/ng-packs/packages/account/src/lib/account.module.ts +++ b/npm/ng-packs/packages/account/src/lib/account.module.ts @@ -1,49 +1,33 @@ -import { CoreModule, LazyModuleFactory } from '@abp/ng.core'; -import { ThemeSharedModule } from '@abp/ng.theme.shared'; +import { LazyModuleFactory } from '@abp/ng.core'; import { ModuleWithProviders, NgModule, NgModuleFactory } from '@angular/core'; -import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgxValidateCoreModule } from '@ngx-validate/core'; -import { AccountRoutingModule } from './account-routing.module'; -import { ChangePasswordComponent } from './components/change-password/change-password.component'; -import { LoginComponent } from './components/login/login.component'; -import { ManageProfileComponent } from './components/manage-profile/manage-profile.component'; -import { PersonalSettingsComponent } from './components/personal-settings/personal-settings.component'; -import { RegisterComponent } from './components/register/register.component'; import { AccountConfigOptions } from './models/config-options'; import { ACCOUNT_CONFIG_OPTIONS } from './tokens/config-options.token'; import { accountConfigOptionsFactory } from './utils/factory-utils'; import { AuthenticationFlowGuard } from './guards/authentication-flow.guard'; -import { ForgotPasswordComponent } from './components/forgot-password/forgot-password.component'; -import { ResetPasswordComponent } from './components/reset-password/reset-password.component'; import { RE_LOGIN_CONFIRMATION_TOKEN } from './tokens'; import { ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS } from './tokens/extensions.token'; import { AccountExtensionsGuard } from './guards/extensions.guard'; -import { PersonalSettingsHalfRowComponent } from './components/personal-settings/personal-settings-half-row.component'; -import { ExtensibleModule } from "@abp/ng.components/extensible"; - -const declarations = [ +import { + ForgotPasswordComponent, LoginComponent, - RegisterComponent, - ChangePasswordComponent, ManageProfileComponent, - PersonalSettingsComponent, - ForgotPasswordComponent, + RegisterComponent, ResetPasswordComponent, - PersonalSettingsHalfRowComponent, -]; +} from './components'; +import { AccountRoutingModule } from './account-routing.module'; @NgModule({ - declarations: [...declarations], + declarations: [], imports: [ - CoreModule, + LoginComponent, + RegisterComponent, + ForgotPasswordComponent, + ResetPasswordComponent, + ManageProfileComponent, AccountRoutingModule, - ThemeSharedModule, - NgbDropdownModule, - NgxValidateCoreModule, - ExtensibleModule, ], - exports: [...declarations], + exports: [], }) export class AccountModule { static forChild(options = {} as AccountConfigOptions): ModuleWithProviders { @@ -69,7 +53,9 @@ export class AccountModule { ], }; } - + /** + * @deprecated `AccountModule.forLazy()` is deprecated. You can use `createRoutes` **function** instead. + */ static forLazy(options = {} as AccountConfigOptions): NgModuleFactory { return new LazyModuleFactory(AccountModule.forChild(options)); } diff --git a/npm/ng-packs/packages/account/src/lib/account.routes.ts b/npm/ng-packs/packages/account/src/lib/account.routes.ts new file mode 100644 index 0000000000..5fb4236ee1 --- /dev/null +++ b/npm/ng-packs/packages/account/src/lib/account.routes.ts @@ -0,0 +1,119 @@ +import { Routes } from '@angular/router'; +import { + ForgotPasswordComponent, + LoginComponent, + RegisterComponent, + ResetPasswordComponent, + ManageProfileComponent, +} from './components'; +import { eAccountComponents } from './enums'; +import { authenticationFlowGuard } from './guards'; +import { accountExtensionsResolver } from './resolvers'; +import { + RE_LOGIN_CONFIRMATION_TOKEN, + ACCOUNT_CONFIG_OPTIONS, + ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS, +} from './tokens'; +import { AccountConfigOptions } from './models'; +import { accountConfigOptionsFactory } from './utils'; +import { + authGuard, + ReplaceableComponents, + ReplaceableRouteContainerComponent, + RouterOutletComponent, +} from '@abp/ng.core'; + +export function provideAccount(options: AccountConfigOptions = {}) { + return [ + { provide: ACCOUNT_CONFIG_OPTIONS, useValue: options }, + { + provide: 'ACCOUNT_OPTIONS', + useFactory: accountConfigOptionsFactory, + deps: [ACCOUNT_CONFIG_OPTIONS], + }, + { + provide: RE_LOGIN_CONFIRMATION_TOKEN, + useValue: options.isPersonalSettingsChangedConfirmationActive ?? true, + }, + { + provide: ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS, + useValue: options.editFormPropContributors, + }, + ]; +} + +const canActivate = [authenticationFlowGuard]; + +export const createRoutes = (options: AccountConfigOptions = {}): Routes => [ + { + path: '', + component: RouterOutletComponent, + providers: provideAccount(options), + children: [ + { path: '', pathMatch: 'full', redirectTo: 'login' }, + { + path: 'login', + component: ReplaceableRouteContainerComponent, + canActivate, + data: { + replaceableComponent: { + key: eAccountComponents.Login, + defaultComponent: LoginComponent, + } as ReplaceableComponents.RouteData, + }, + title: 'AbpAccount::Login', + }, + { + path: 'register', + component: ReplaceableRouteContainerComponent, + canActivate, + data: { + replaceableComponent: { + key: eAccountComponents.Register, + defaultComponent: RegisterComponent, + } as ReplaceableComponents.RouteData, + }, + title: 'AbpAccount::Register', + }, + { + path: 'forgot-password', + component: ReplaceableRouteContainerComponent, + canActivate, + + data: { + replaceableComponent: { + key: eAccountComponents.ForgotPassword, + defaultComponent: ForgotPasswordComponent, + } as ReplaceableComponents.RouteData, + }, + title: 'AbpAccount::ForgotPassword', + }, + { + path: 'reset-password', + component: ReplaceableRouteContainerComponent, + canActivate: [], + data: { + tenantBoxVisible: false, + replaceableComponent: { + key: eAccountComponents.ResetPassword, + defaultComponent: ResetPasswordComponent, + } as ReplaceableComponents.RouteData, + }, + title: 'AbpAccount::ResetPassword', + }, + { + path: 'manage', + component: ReplaceableRouteContainerComponent, + canActivate: [authGuard], + resolve: [accountExtensionsResolver], + data: { + replaceableComponent: { + key: eAccountComponents.ManageProfile, + defaultComponent: ManageProfileComponent, + } as ReplaceableComponents.RouteData, + }, + title: 'AbpAccount::MyAccount', + }, + ], + }, +]; diff --git a/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html b/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html index 074b6d53ac..a10e190664 100644 --- a/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html +++ b/npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html @@ -1,4 +1,4 @@ - + @if (!hideCurrentPassword) {
diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts index dfdca734a6..5d91c660da 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts @@ -1,20 +1,43 @@ -import { ABP, RoutesService, TreeNode } from '@abp/ng.core'; +import { + ABP, + LazyLocalizationPipe, + LocalizationPipe, + PermissionDirective, + RoutesService, + TreeNode, +} from '@abp/ng.core'; import { Component, ElementRef, + inject, Input, QueryList, Renderer2, TrackByFunction, ViewChildren, } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; +import { RouterModule } from '@angular/router'; +import { EllipsisDirective } from '@abp/ng.theme.shared'; @Component({ - standalone: false, selector: 'abp-routes', templateUrl: 'routes.component.html', + imports: [ + CommonModule, + RouterModule, + NgbDropdownModule, + LazyLocalizationPipe, + PermissionDirective, + EllipsisDirective, + LocalizationPipe, + ], }) export class RoutesComponent { + public readonly routesService = inject(RoutesService); + protected renderer = inject(Renderer2); + @Input() smallScreen?: boolean; @ViewChildren('childrenContainer') childrenContainers!: QueryList>; @@ -23,11 +46,6 @@ export class RoutesComponent { trackByFn: TrackByFunction> = (_, item) => item.name; - constructor( - public readonly routesService: RoutesService, - protected renderer: Renderer2, - ) {} - isDropdown(node: TreeNode) { return !node?.isLeaf || this.routesService.hasChildren(node.name); } diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/validation-error/validation-error.component.ts b/npm/ng-packs/packages/theme-basic/src/lib/components/validation-error/validation-error.component.ts index c3c36ae2b3..bfa9d6cab2 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/validation-error/validation-error.component.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/validation-error/validation-error.component.ts @@ -1,8 +1,9 @@ +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core'; import { Validation, ValidationErrorComponent as ErrorComponent } from '@ngx-validate/core'; +import { LocalizationPipe } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'abp-validation-error', template: ` @for (error of abpErrors; track $index) { @@ -13,6 +14,7 @@ import { Validation, ValidationErrorComponent as ErrorComponent } from '@ngx-val `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, + imports: [CommonModule, LocalizationPipe], }) export class ValidationErrorComponent extends ErrorComponent { get abpErrors(): (Validation.Error & { interpoliteParams?: string[] })[] { diff --git a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts index d959509dfd..7177045805 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts @@ -1,54 +1,39 @@ -import { CoreModule } from '@abp/ng.core'; -import { ThemeSharedModule } from '@abp/ng.theme.shared'; import { ModuleWithProviders, NgModule } from '@angular/core'; -import { NgbCollapseModule, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgxValidateCoreModule } from '@ngx-validate/core'; -import { AccountLayoutComponent } from './components/account-layout/account-layout.component'; -import { AuthWrapperComponent } from './components/account-layout/auth-wrapper/auth-wrapper.component'; -import { TenantBoxComponent } from './components/account-layout/tenant-box/tenant-box.component'; -import { ApplicationLayoutComponent } from './components/application-layout/application-layout.component'; -import { EmptyLayoutComponent } from './components/empty-layout/empty-layout.component'; -import { LogoComponent } from './components/logo/logo.component'; -import { CurrentUserComponent } from './components/nav-items/current-user.component'; -import { LanguagesComponent } from './components/nav-items/languages.component'; -import { NavItemsComponent } from './components/nav-items/nav-items.component'; -import { PageAlertContainerComponent } from './components/page-alert-container/page-alert-container.component'; -import { RoutesComponent } from './components/routes/routes.component'; -import { ValidationErrorComponent } from './components/validation-error/validation-error.component'; +import { + AccountLayoutComponent, + AuthWrapperComponent, + TenantBoxComponent, + ApplicationLayoutComponent, + EmptyLayoutComponent, + LogoComponent, + CurrentUserComponent, + LanguagesComponent, + NavItemsComponent, + PageAlertContainerComponent, + RoutesComponent, + ValidationErrorComponent, +} from './components'; import { provideThemeBasicConfig } from './providers'; export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, EmptyLayoutComponent]; +export const THEME_BASIC_COMPONENTS = [ + ...LAYOUTS, + ValidationErrorComponent, + LogoComponent, + NavItemsComponent, + RoutesComponent, + CurrentUserComponent, + LanguagesComponent, + PageAlertContainerComponent, + AuthWrapperComponent, + TenantBoxComponent, +]; + @NgModule({ - declarations: [ - ...LAYOUTS, - ValidationErrorComponent, - LogoComponent, - NavItemsComponent, - RoutesComponent, - CurrentUserComponent, - LanguagesComponent, - PageAlertContainerComponent, - TenantBoxComponent, - AuthWrapperComponent, - ], - exports: [ - ...LAYOUTS, - ValidationErrorComponent, - LogoComponent, - NavItemsComponent, - RoutesComponent, - CurrentUserComponent, - LanguagesComponent, - PageAlertContainerComponent, - ], - imports: [ - CoreModule, - ThemeSharedModule, - NgbCollapseModule, - NgbDropdownModule, - NgxValidateCoreModule, - ], + declarations: [], + exports: [...THEME_BASIC_COMPONENTS], + imports: [...THEME_BASIC_COMPONENTS], }) export class BaseThemeBasicModule {} diff --git a/npm/ng-packs/packages/theme-shared/package.json b/npm/ng-packs/packages/theme-shared/package.json index 540763cc75..087ab1ed6f 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.2.0-rc.1", + "version": "9.2.0-rc.4", "homepage": "https://abp.io", "repository": { "type": "git", "url": "https://github.com/abpframework/abp.git" }, "dependencies": { - "@abp/ng.core": "~9.2.0-rc.1", + "@abp/ng.core": "~9.2.0-rc.4", "@fortawesome/fontawesome-free": "^5.0.0", "@ng-bootstrap/ng-bootstrap": "~18.0.0", "@ngx-validate/core": "^0.2.0", diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb-items/breadcrumb-items.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb-items/breadcrumb-items.component.ts index d7188f561a..0c68151d36 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb-items/breadcrumb-items.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb-items/breadcrumb-items.component.ts @@ -1,10 +1,12 @@ -import { ABP } from '@abp/ng.core'; import { Component, Input } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { ABP, LocalizationPipe } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'abp-breadcrumb-items', templateUrl: './breadcrumb-items.component.html', + imports: [CommonModule, RouterModule, LocalizationPipe], }) export class BreadcrumbItemsComponent { @Input() items: Partial[] = []; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts index bdc38612b3..4c7bd3cf30 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/breadcrumb/breadcrumb.component.ts @@ -10,13 +10,14 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@ import { Router } from '@angular/router'; import { map, startWith } from 'rxjs/operators'; import { eThemeSharedRouteNames } from '../../enums/route-names'; +import { BreadcrumbItemsComponent } from '../breadcrumb-items/breadcrumb-items.component'; @Component({ - standalone: false, selector: 'abp-breadcrumb', templateUrl: './breadcrumb.component.html', changeDetection: ChangeDetectionStrategy.OnPush, providers: [SubscriptionService], + imports: [BreadcrumbItemsComponent], }) export class BreadcrumbComponent implements OnInit { segments: Partial[] = []; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts index a0005cd5e7..fdebb542a7 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/button/button.component.ts @@ -1,5 +1,4 @@ /* eslint-disable @angular-eslint/no-output-native */ -import { ABP } from '@abp/ng.core'; import { Component, ElementRef, @@ -10,9 +9,10 @@ import { Renderer2, ViewChild, } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ABP } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'abp-button', template: ` `, + imports: [CommonModule], }) export class ButtonComponent implements OnInit { @Input() diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-body.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-body.component.ts index 30eb2478a0..2376cef02e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-body.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-body.component.ts @@ -1,11 +1,12 @@ import { Component, HostBinding, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; @Component({ - standalone: false, selector: 'abp-card-body', template: `
`, + imports: [CommonModule], }) export class CardBodyComponent { @HostBinding('class') componentClass = 'card-body'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-footer.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-footer.component.ts index 31939469d1..0e09e1fda6 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-footer.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-footer.component.ts @@ -1,7 +1,7 @@ import { Component, HostBinding, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; @Component({ - standalone: false, selector: 'abp-card-footer', template: `
@@ -9,6 +9,7 @@ import { Component, HostBinding, Input } from '@angular/core';
`, styles: [], + imports: [CommonModule], }) export class CardFooterComponent { @HostBinding('class') componentClass = 'card-footer'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.component.ts index 4a1051fee4..03e1fa8af4 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.component.ts @@ -1,7 +1,7 @@ import { Component, HostBinding, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; @Component({ - standalone: false, selector: 'abp-card-header', template: `
@@ -9,6 +9,7 @@ import { Component, HostBinding, Input } from '@angular/core';
`, styles: [], + imports: [CommonModule], }) export class CardHeaderComponent { @HostBinding('class') componentClass = 'card-header'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.directive.ts index bebd384ca5..44b8ff0eb5 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-header.directive.ts @@ -1,7 +1,6 @@ import { Directive, HostBinding } from '@angular/core'; @Directive({ - standalone: false, selector: `abp-card-header, [abp-card-header], [abpCardHeader]`, }) export class CardHeaderDirective { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-img-top.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-img-top.directive.ts index 13ca5bb07d..405ea1bb24 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-img-top.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-img-top.directive.ts @@ -1,7 +1,6 @@ import { Directive, HostBinding } from '@angular/core'; @Directive({ - standalone: false, selector: `abp-card-img-top, [abp-card-img-top], [abpCardImgTop]`, }) export class CardImgTopDirective { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-subtitle.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-subtitle.directive.ts index bf561eda78..57ba722500 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-subtitle.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-subtitle.directive.ts @@ -1,7 +1,6 @@ import { Directive, HostBinding } from '@angular/core'; @Directive({ - standalone: false, selector: `abp-card-subtitle, [abp-card-subtitle], [abpCardSubtitle]`, }) export class CardSubtitleDirective { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-title.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-title.directive.ts index f884e2904d..0bb92d9263 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-title.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card-title.directive.ts @@ -1,7 +1,6 @@ import { Directive, HostBinding } from '@angular/core'; @Directive({ - standalone: false, selector: `abp-card-title, [abp-card-title], [abpCardTitle]`, }) export class CardTitleDirective { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.component.ts index c3a24426a7..5c2269b8aa 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.component.ts @@ -1,11 +1,12 @@ import { Component, Input } from '@angular/core'; +import { CommonModule } from '@angular/common'; @Component({ - standalone: false, selector: 'abp-card', template: `
`, + imports: [CommonModule], }) export class CardComponent { @Input() cardClass: string; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.module.ts index ac7e28e568..418dddd809 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/card/card.module.ts @@ -1,4 +1,3 @@ -import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { CardBodyComponent } from './card-body.component'; import { CardComponent } from './card.component'; @@ -9,20 +8,23 @@ import { CardSubtitleDirective } from './card-subtitle.directive'; import { CardImgTopDirective } from './card-img-top.directive'; import { CardHeaderDirective } from './card-header.directive'; -const declarationsWithExports = [ - CardComponent, - CardBodyComponent, - CardHeaderComponent, - CardFooterComponent, +export const CARD_DIRECTIVES = [ CardTitleDirective, CardSubtitleDirective, CardImgTopDirective, CardHeaderDirective, ]; +export const CARD_COMPONENTS = [ + CardComponent, + CardBodyComponent, + CardHeaderComponent, + CardFooterComponent, +]; + @NgModule({ - declarations: [...declarationsWithExports], - imports: [CommonModule], - exports: [...declarationsWithExports], + declarations: [], + imports: [...CARD_COMPONENTS, ...CARD_DIRECTIVES], + exports: [...CARD_COMPONENTS, ...CARD_DIRECTIVES], }) export class CardModule {} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts index 64c3d766e4..9ee8cb1af5 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/checkbox/checkbox.component.ts @@ -1,9 +1,9 @@ -import { AbstractNgModelComponent } from '@abp/ng.core'; import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core'; -import { NG_VALUE_ACCESSOR } from '@angular/forms'; +import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; +import { CommonModule } from '@angular/common'; +import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'abp-checkbox', template: `
@@ -31,6 +31,7 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms'; multi: true, }, ], + imports: [CommonModule, FormsModule, LocalizationPipe], }) export class FormCheckboxComponent extends AbstractNgModelComponent { @Input() label?: string; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts index 493ca44b6b..f211b758e3 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/confirmation/confirmation.component.ts @@ -1,13 +1,15 @@ import { Component, Inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; import { ReplaySubject } from 'rxjs'; import { Confirmation } from '../../models/confirmation'; import { CONFIRMATION_ICONS, ConfirmationIcons } from '../../tokens/confirmation-icons.token'; +import { LocalizationPipe } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'abp-confirmation', templateUrl: './confirmation.component.html', styleUrls: ['./confirmation.component.scss'], + imports: [CommonModule, LocalizationPipe], }) export class ConfirmationComponent { constructor(@Inject(CONFIRMATION_ICONS) private icons: ConfirmationIcons) {} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts index 2d7b358b7a..73ad3306b1 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/form-input/form-input.component.ts @@ -1,9 +1,9 @@ -import { AbstractNgModelComponent } from '@abp/ng.core'; import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core'; -import { NG_VALUE_ACCESSOR } from '@angular/forms'; +import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { CommonModule } from '@angular/common'; +import { AbstractNgModelComponent, LocalizationPipe } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'abp-form-input', template: `
@@ -32,6 +32,7 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms'; multi: true, }, ], + imports: [CommonModule, LocalizationPipe, FormsModule], }) export class FormInputComponent extends AbstractNgModelComponent { @Input() inputId!: string; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts index f45be25d1e..527f7efb7e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/http-error-wrapper/http-error-wrapper.component.ts @@ -14,18 +14,18 @@ import { DestroyRef, } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { DOCUMENT } from '@angular/common'; +import { CommonModule, DOCUMENT } from '@angular/common'; import { Router } from '@angular/router'; import { fromEvent, Subject } from 'rxjs'; import { debounceTime, filter } from 'rxjs/operators'; -import { LocalizationParam } from '@abp/ng.core'; +import { LocalizationParam, LocalizationPipe } from '@abp/ng.core'; import { ErrorScreenErrorCodes } from '../../models'; @Component({ - standalone: false, selector: 'abp-http-error-wrapper', templateUrl: './http-error-wrapper.component.html', styleUrls: ['http-error-wrapper.component.scss'], + imports: [CommonModule, LocalizationPipe], }) export class HttpErrorWrapperComponent implements OnInit, AfterViewInit, OnDestroy { protected readonly destroyRef = inject(DestroyRef); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts index 51aebfdee6..501fbbb82a 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts @@ -1,10 +1,10 @@ -import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng.core'; import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Router } from '@angular/router'; +import { CommonModule } from '@angular/common'; import { combineLatest, Subscription, timer } from 'rxjs'; +import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'abp-loader-bar', template: `
@@ -21,6 +21,7 @@ import { combineLatest, Subscription, timer } from 'rxjs'; `, styleUrls: ['./loader-bar.component.scss'], providers: [SubscriptionService], + imports: [CommonModule], }) export class LoaderBarComponent implements OnDestroy, OnInit { protected _isLoading!: boolean; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/loading/loading.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/loading/loading.component.ts index 56990be1bc..7c4b35c6fa 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/loading/loading.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/loading/loading.component.ts @@ -1,7 +1,6 @@ import { Component, ViewEncapsulation } from '@angular/core'; @Component({ - standalone: false, selector: 'abp-loading', template: `
@@ -33,5 +32,6 @@ import { Component, ViewEncapsulation } from '@angular/core'; } `, ], + imports: [], }) export class LoadingComponent {} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts index 8b50174fd9..96455d1151 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts @@ -2,7 +2,6 @@ import { Directive, HostListener, Optional } from '@angular/core'; import { ModalComponent } from './modal.component'; @Directive({ - standalone: false, selector: '[abpClose]', }) export class ModalCloseDirective { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts index 30c802e387..3ac175ae6c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts @@ -1,4 +1,3 @@ -import { SubscriptionService, uuid } from '@abp/ng.core'; import { Component, DestroyRef, @@ -13,12 +12,14 @@ import { output, viewChild, } from '@angular/core'; +import { CommonModule } from '@angular/common'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { SubscriptionService, uuid } from '@abp/ng.core'; import { NgbModal, NgbModalOptions, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { fromEvent } from 'rxjs'; import { debounceTime, filter } from 'rxjs/operators'; -import { Confirmation } from '../../models/confirmation'; -import { ConfirmationService } from '../../services/confirmation.service'; +import { Confirmation } from '../../models'; +import { ConfirmationService } from '../../services'; import { SUPPRESS_UNSAVED_CHANGES_WARNING } from '../../tokens/suppress-unsaved-changes-warning.token'; import { ButtonComponent } from '../button/button.component'; import { DismissableModal, ModalDismissMode, ModalRefService } from './modal-ref.service'; @@ -26,11 +27,11 @@ import { DismissableModal, ModalDismissMode, ModalRefService } from './modal-ref export type ModalSize = 'sm' | 'md' | 'lg' | 'xl'; @Component({ - standalone: false, selector: 'abp-modal', templateUrl: './modal.component.html', styleUrls: ['./modal.component.scss'], providers: [SubscriptionService], + imports: [CommonModule], }) export class ModalComponent implements OnInit, OnDestroy, DismissableModal { protected readonly confirmationService = inject(ConfirmationService); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts index cfdc080f5b..a6e670db0b 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/password/password.component.ts @@ -1,7 +1,8 @@ import { Component, forwardRef, Input } from '@angular/core'; -import { AbstractNgModelComponent } from '@abp/ng.core'; -import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; +import { AbstractNgModelComponent } from '@abp/ng.core'; +import { NgxValidateCoreModule } from '@ngx-validate/core'; /** * @deprecated use ShowPasswordDirective directive @@ -9,7 +10,7 @@ import { CommonModule } from '@angular/common'; */ @Component({ selector: 'abp-password', - imports: [CommonModule, FormsModule], + imports: [CommonModule, FormsModule, ReactiveFormsModule, NgxValidateCoreModule], templateUrl: `./password.component.html`, providers: [ { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/spinner/spinner.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/spinner/spinner.component.ts index e1d3493261..4847d15652 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/spinner/spinner.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/spinner/spinner.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; @Component({ selector: 'abp-spinner', - standalone: true, template: `
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/toast-container/toast-container.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/toast-container/toast-container.component.ts index 4703a41c17..aca2149f8b 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/toast-container/toast-container.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/toast-container/toast-container.component.ts @@ -2,13 +2,14 @@ import { Component, HostListener, Input, OnInit } from '@angular/core'; import { ReplaySubject } from 'rxjs'; import { toastInOut } from '../../animations/toast.animations'; import { Toaster } from '../../models/toaster'; +import { ToastComponent } from '../toast/toast.component'; @Component({ - standalone: false, selector: 'abp-toast-container', templateUrl: './toast-container.component.html', styleUrls: ['./toast-container.component.scss'], animations: [toastInOut], + imports: [ToastComponent], }) export class ToastContainerComponent implements OnInit { toasts$!: ReplaySubject; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts index d76790bf54..8bb1a7126e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/toast/toast.component.ts @@ -1,10 +1,13 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { CommonModule } from '@angular/common'; import { Toaster } from '../../models/toaster'; +import { LocalizationPipe } from '@abp/ng.core'; + @Component({ - standalone: false, selector: 'abp-toast', templateUrl: './toast.component.html', styleUrls: ['./toast.component.scss'], + imports: [CommonModule, LocalizationPipe], }) export class ToastComponent implements OnInit { @Input() diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts index 8832280dee..c0a1a74995 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/disabled.directive.ts @@ -3,7 +3,6 @@ import { NgControl } from '@angular/forms'; @Directive({ selector: '[abpDisabled]', - standalone:true, }) export class DisabledDirective implements OnChanges { @Input() diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts index 2cad957942..94d963ce2e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ellipsis.directive.ts @@ -10,7 +10,6 @@ import { @Directive({ selector: '[abpEllipsis]', - standalone:true }) export class EllipsisDirective implements AfterViewInit { @Input('abpEllipsis') @@ -38,7 +37,10 @@ export class EllipsisDirective implements AfterViewInit { return this.enabled && this.width ? this.width || '170px' : undefined; } - constructor(private cdRef: ChangeDetectorRef, private elRef: ElementRef) {} + constructor( + private cdRef: ChangeDetectorRef, + private elRef: ElementRef, + ) {} ngAfterViewInit() { this.title = this.title || (this.elRef.nativeElement as HTMLElement).innerText; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts index e20ef4fa02..9de000e15f 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/loading.directive.ts @@ -14,10 +14,9 @@ import { } from '@angular/core'; import { Subscription, timer } from 'rxjs'; import { take } from 'rxjs/operators'; -import { LoadingComponent } from '../components/loading/loading.component'; +import { LoadingComponent } from '../components'; @Directive({ - standalone: false, selector: '[abpLoading]', }) export class LoadingDirective implements OnInit, OnDestroy { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts index 359ca72b59..c7dc96f3c9 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts @@ -7,10 +7,9 @@ import { debounceTime } from 'rxjs/operators'; @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector selector: 'ngx-datatable[default]', - standalone: true, exportAs: 'ngxDatatableDefault', }) -export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy { +export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy { private subscription = new Subscription(); private resizeDiff = 0; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts index d50038b1b7..5715a4f40b 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -24,7 +24,6 @@ import { SpinnerComponent } from '../components'; @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector selector: 'ngx-datatable[list]', - standalone: true, exportAs: 'ngxDatatableList', }) export class NgxDatatableListDirective implements OnChanges, OnInit, DoCheck { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts index bcdd94a5d4..9613779472 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/visible.directive.ts @@ -2,7 +2,6 @@ import { OnInit, Directive, OnDestroy, Input, ViewContainerRef, TemplateRef } fr import { EMPTY, from, Observable, of, Subscription } from 'rxjs'; @Directive({ - standalone: true, selector: '[abpVisible]', }) export class AbpVisibleDirective implements OnDestroy, OnInit { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts index 40a1109de0..7f8010c839 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/breadcrumb.component.spec.ts @@ -33,8 +33,14 @@ describe('BreadcrumbComponent', () => { useFactory: () => mockRoutesService(), }, ], - declarations: [LocalizationPipe, BreadcrumbComponent, BreadcrumbItemsComponent], - imports: [RouterModule,HttpClientModule], + declarations: [], + imports: [ + RouterModule, + HttpClientModule, + LocalizationPipe, + BreadcrumbComponent, + BreadcrumbItemsComponent, + ], routes: [ { path: '', diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/card.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/card.component.spec.ts index a5c8a5c43b..1a03353565 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/card.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/card.component.spec.ts @@ -15,7 +15,8 @@ describe('CardComponent', () => { const createHost = createHostFactory({ component: CardComponent, - declarations: [ + declarations: [], + imports: [ CardHeaderComponent, CardTitleDirective, CardSubtitleDirective, @@ -32,7 +33,7 @@ describe('CardComponent', () => { Card title -

Card subtitle

+

Card subtitle

diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts index 587365e3f6..43b6ef11a9 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts @@ -10,8 +10,8 @@ import { CONFIRMATION_ICONS, DEFAULT_CONFIRMATION_ICONS } from '../tokens/confir @NgModule({ exports: [ConfirmationComponent], - declarations: [ConfirmationComponent], - imports: [CoreTestingModule.withConfig()], + declarations: [], + imports: [CoreTestingModule.withConfig(), ConfirmationComponent], providers: [{ provide: CONFIRMATION_ICONS, useValue: DEFAULT_CONFIRMATION_ICONS }], }) export class MockModule {} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/error.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/error.component.spec.ts index 5bde4d2a54..eef153e8d8 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/error.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/error.component.spec.ts @@ -9,7 +9,7 @@ describe('ErrorComponent', () => { let spectator: SpectatorHost; const createHost = createHostFactory({ component: HttpErrorWrapperComponent, - declarations: [LocalizationPipe], + declarations: [], mocks: [HttpClient], providers: [ { provide: CORE_OPTIONS, useValue: {} }, @@ -19,7 +19,7 @@ describe('ErrorComponent', () => { useValue: { nativeElement: document.createElement('div') }, }, ], - imports:[HttpClientModule] + imports: [HttpClientModule, LocalizationPipe], }); beforeEach(() => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts index 8688572436..ede2bded2d 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts @@ -10,15 +10,22 @@ import { HttpErrorWrapperComponent } from '../components/http-error-wrapper/http import { ErrorHandler } from '../handlers'; import { DEFAULT_ERROR_LOCALIZATIONS, DEFAULT_ERROR_MESSAGES } from '../constants/default-errors'; import { ConfirmationService } from '../services'; -import { httpErrorConfigFactory } from '../tokens/http-error.token'; +import { CUSTOM_ERROR_HANDLERS, HTTP_ERROR_CONFIG } from '../tokens/http-error.token'; +import { CustomHttpErrorHandlerService } from '../models'; + +const customHandlerMock: CustomHttpErrorHandlerService = { + priority: 100, + canHandle: jest.fn().mockReturnValue(true), + execute: jest.fn(), +}; const reporter$ = new Subject(); @NgModule({ exports: [HttpErrorWrapperComponent], - declarations: [HttpErrorWrapperComponent], + declarations: [], //entryComponents: [HttpErrorWrapperComponent], - imports: [CoreTestingModule], + imports: [CoreTestingModule, HttpErrorWrapperComponent], }) class MockModule {} @@ -46,16 +53,21 @@ describe('ErrorHandler', () => { }, }, { provide: APP_BASE_HREF, useValue: '/' }, - { - provide: 'HTTP_ERROR_CONFIG', - useFactory: httpErrorConfigFactory, - }, { provide: ConfirmationService, useValue: { error: errorConfirmation, }, }, + { + provide: CUSTOM_ERROR_HANDLERS, + useValue: customHandlerMock, + multi: true, + }, + { + provide: HTTP_ERROR_CONFIG, + useFactory: () => ({}), + }, ], }); @@ -71,67 +83,26 @@ describe('ErrorHandler', () => { }); test('should display HttpErrorWrapperComponent when server error occurs', () => { - const createComponent = jest.spyOn(service, 'createErrorComponent'); const error = new HttpErrorResponse({ status: 500 }); - const params = { - title: { - key: DEFAULT_ERROR_LOCALIZATIONS.defaultError500.title, - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError500.title, - }, - details: { - key: DEFAULT_ERROR_LOCALIZATIONS.defaultError500.details, - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError500.details, - }, - status: 500, - }; expect(selectHtmlErrorWrapper()).toBeNull(); - httpErrorReporter.reportError(error); - - expect(createComponent).toHaveBeenCalledWith(params); + expect(selectHtmlErrorWrapper()).not.toBeNull(); }); test('should display HttpErrorWrapperComponent when authorize error occurs', () => { - const createComponent = jest.spyOn(service, 'createErrorComponent'); const error = new HttpErrorResponse({ status: 403 }); - const params = { - title: { - key: DEFAULT_ERROR_LOCALIZATIONS.defaultError403.title, - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError403.title, - }, - details: { - key: DEFAULT_ERROR_LOCALIZATIONS.defaultError403.details, - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError403.details, - }, - status: 403, - }; expect(selectHtmlErrorWrapper()).toBeNull(); - httpErrorReporter.reportError(error); - - expect(createComponent).toHaveBeenCalledWith(params); + expect(selectHtmlErrorWrapper()).not.toBeNull(); }); test('should display HttpErrorWrapperComponent when unknown error occurs', () => { - const createComponent = jest.spyOn(service, 'createErrorComponent'); - const error = new HttpErrorResponse({ - status: 0, - statusText: 'Unknown Error', - }); - const params = { - title: { - key: DEFAULT_ERROR_LOCALIZATIONS.defaultError.title, - defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title, - }, - details: error.message, - isHomeShow: false, - }; + const error = new HttpErrorResponse({ status: 0 }); httpErrorReporter.reportError(error); - - expect(createComponent).toHaveBeenCalledWith(params); + expect(selectHtmlErrorWrapper()).not.toBeNull(); }); test('should call error method of ConfirmationService when not found error occurs', () => { @@ -215,6 +186,15 @@ describe('ErrorHandler', () => { CONFIRMATION_BUTTONS, ); }); + + test('should delegate to CUSTOM_ERROR_HANDLERS and call execute if canHandle is true', () => { + const error = new HttpErrorResponse({ status: 418 }); + + httpErrorReporter.reportError(error); + + expect(customHandlerMock.canHandle).toHaveBeenCalledWith(error); + expect(customHandlerMock.execute).toHaveBeenCalled(); + }); }); @Component({ @@ -227,9 +207,9 @@ class DummyErrorComponent { } @NgModule({ - declarations: [DummyErrorComponent], + declarations: [], exports: [DummyErrorComponent], - entryComponents: [DummyErrorComponent], + imports: [DummyErrorComponent], }) class ErrorModule {} @@ -310,15 +290,6 @@ class ErrorModule {} // }); // }); -export function customHttpErrorConfigFactory() { - return httpErrorConfigFactory({ - errorScreen: { - component: DummyErrorComponent, - forWhichErrors: [401, 403, 404, 500], - }, - }); -} - function removeIfExistsInDom(errorSelector: () => HTMLDivElement | null) { const abpError = errorSelector(); if (abpError) abpError.parentNode.removeChild(abpError); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts index b359a2000c..808419616b 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts @@ -14,8 +14,9 @@ describe('LoadingDirective', () => { let spectator: SpectatorDirective; const createDirective = createDirectiveFactory({ directive: LoadingDirective, - declarations: [LoadingComponent, DummyComponent], - entryComponents: [LoadingComponent], + declarations: [], + entryComponents: [], + imports: [LoadingComponent, DummyComponent], }); describe('default', () => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts index 838d83d226..ebb50f3bb1 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts @@ -18,8 +18,14 @@ describe('ModalComponent', () => { let mockConfirmation$: Subject; const createHost = createHostFactory({ component: ModalComponent, - imports: [RouterTestingModule, NgbModalModule], - declarations: [ConfirmationComponent, LocalizationPipe, ButtonComponent], + imports: [ + RouterTestingModule, + NgbModalModule, + ConfirmationComponent, + LocalizationPipe, + ButtonComponent, + ], + declarations: [], providers: [ { provide: ConfirmationService, diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts index 3493d9c12a..576c4f0320 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts @@ -8,8 +8,8 @@ import { ToasterService } from '../services/toaster.service'; @NgModule({ exports: [ToastContainerComponent], - declarations: [ToastContainerComponent, ToastComponent], - imports: [CoreTestingModule.withConfig()], + declarations: [], + imports: [CoreTestingModule.withConfig(), ToastContainerComponent, ToastComponent], }) export class MockModule {} const toastClassPrefix = 'abp-toast'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 50d179c3a9..b15ca00ed4 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -1,25 +1,31 @@ -import { CoreModule } from '@abp/ng.core'; -import { DatePipe } from '@angular/common'; import { ModuleWithProviders, NgModule } from '@angular/core'; -import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap'; import { NgxValidateCoreModule } from '@ngx-validate/core'; import { NgxDatatableModule } from '@swimlane/ngx-datatable'; -import { BreadcrumbItemsComponent } from './components/breadcrumb-items/breadcrumb-items.component'; -import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; -import { ButtonComponent } from './components/button/button.component'; -import { ConfirmationComponent } from './components/confirmation/confirmation.component'; -import { HttpErrorWrapperComponent } from './components/http-error-wrapper/http-error-wrapper.component'; -import { LoaderBarComponent } from './components/loader-bar/loader-bar.component'; -import { LoadingComponent } from './components/loading/loading.component'; -import { ModalCloseDirective } from './components/modal/modal-close.directive'; -import { ModalComponent } from './components/modal/modal.component'; -import { ToastContainerComponent } from './components/toast-container/toast-container.component'; -import { ToastComponent } from './components/toast/toast.component'; -import { EllipsisDirective } from './directives/ellipsis.directive'; -import { LoadingDirective } from './directives/loading.directive'; -import { NgxDatatableDefaultDirective } from './directives/ngx-datatable-default.directive'; -import { NgxDatatableListDirective } from './directives/ngx-datatable-list.directive'; -import { RootParams } from './models/common'; +import { + BreadcrumbItemsComponent, + BreadcrumbComponent, + ButtonComponent, + ConfirmationComponent, + HttpErrorWrapperComponent, + LoaderBarComponent, + LoadingComponent, + ModalComponent, + ToastContainerComponent, + ToastComponent, + ModalCloseDirective, + PasswordComponent, + CardModule, + FormInputComponent, + FormCheckboxComponent, +} from './components'; +import { + LoadingDirective, + NgxDatatableDefaultDirective, + NgxDatatableListDirective, + AbpVisibleDirective, + DisabledDirective, +} from './directives'; +import { RootParams } from './models'; import { provideAbpThemeShared, withConfirmationIcon, @@ -28,13 +34,8 @@ import { withValidationBluePrint, withValidationMapErrorsFn, } from './providers'; -import { PasswordComponent } from './components/password/password.component'; -import { CardModule } from './components/card/card.module'; -import { AbpVisibleDirective, DisabledDirective } from './directives'; -import { FormInputComponent } from './components/form-input/form-input.component'; -import { FormCheckboxComponent } from './components/checkbox/checkbox.component'; -const declarationsWithExports = [ +export const THEME_SHARED_EXPORTS = [ BreadcrumbComponent, BreadcrumbItemsComponent, ButtonComponent, @@ -48,35 +49,21 @@ const declarationsWithExports = [ ModalCloseDirective, FormInputComponent, FormCheckboxComponent, + HttpErrorWrapperComponent, + NgxDatatableModule, + NgxValidateCoreModule, + CardModule, + DisabledDirective, + AbpVisibleDirective, + NgxDatatableListDirective, + NgxDatatableDefaultDirective, + PasswordComponent, ]; @NgModule({ - imports: [ - CoreModule, - NgxDatatableModule, - NgxValidateCoreModule, - NgbPaginationModule, - EllipsisDirective, - CardModule, - PasswordComponent, - NgxDatatableDefaultDirective, - NgxDatatableListDirective, - DisabledDirective, - AbpVisibleDirective, - ], - declarations: [...declarationsWithExports, HttpErrorWrapperComponent], - exports: [ - NgxDatatableModule, - NgxValidateCoreModule, - CardModule, - DisabledDirective, - AbpVisibleDirective, - NgxDatatableListDirective, - NgxDatatableDefaultDirective, - PasswordComponent, - ...declarationsWithExports, - ], - providers: [DatePipe], + imports: [...THEME_SHARED_EXPORTS], + declarations: [], + exports: [...THEME_SHARED_EXPORTS], }) export class BaseThemeSharedModule {} diff --git a/npm/ng-packs/scripts/build-schematics.ts b/npm/ng-packs/scripts/build-schematics.ts index 6690b272b3..0699eb0567 100644 --- a/npm/ng-packs/scripts/build-schematics.ts +++ b/npm/ng-packs/scripts/build-schematics.ts @@ -23,10 +23,15 @@ const FILES_TO_COPY_AFTER_BUILD: (FileCopy | string)[] = [ { src: 'src/commands/create-lib/schema.json', dest: 'commands/create-lib/schema.json' }, { src: 'src/commands/change-theme/schema.json', dest: 'commands/change-theme/schema.json' }, { src: 'src/commands/create-lib/files-package', dest: 'commands/create-lib/files-package' }, + { src: 'src/commands/create-lib/files-package-standalone', dest: 'commands/create-lib/files-package-standalone' }, { src: 'src/commands/create-lib/files-secondary-entrypoint', dest: 'commands/create-lib/files-secondary-entrypoint', }, + { + src: 'src/commands/create-lib/files-secondary-entrypoint-standalone', + dest: 'commands/create-lib/files-secondary-entrypoint-standalone', + }, { src: 'src/commands/proxy-add/schema.json', dest: 'commands/proxy-add/schema.json' }, { src: 'src/commands/proxy-index/schema.json', dest: 'commands/proxy-index/schema.json' }, { src: 'src/commands/proxy-refresh/schema.json', dest: 'commands/proxy-refresh/schema.json' }, diff --git a/npm/packs/anchor-js/package.json b/npm/packs/anchor-js/package.json index 6f3189a323..d6fb9126f4 100644 --- a/npm/packs/anchor-js/package.json +++ b/npm/packs/anchor-js/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/anchor-js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "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 fe10693b7a..879536af15 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.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/aspnetcore.components.server.basictheme", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/aspnetcore.components.server.theming": "~9.2.0-rc.1" + "@abp/aspnetcore.components.server.theming": "~9.2.0-rc.4" }, "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 2b6fe011b7..c832f8894f 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.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/aspnetcore.components.server.theming", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/bootstrap": "~9.2.0-rc.1", - "@abp/font-awesome": "~9.2.0-rc.1" + "@abp/bootstrap": "~9.2.0-rc.4", + "@abp/font-awesome": "~9.2.0-rc.4" }, "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 c4166220c3..4386862cfe 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.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/aspnetcore.mvc.ui.theme.basic", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared": "~9.2.0-rc.4" }, "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 6b6c826530..69464ebab7 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.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/aspnetcore.mvc.ui.theme.shared", "repository": { "type": "git", @@ -10,21 +10,21 @@ "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui": "~9.2.0-rc.1", - "@abp/bootstrap": "~9.2.0-rc.1", - "@abp/bootstrap-datepicker": "~9.2.0-rc.1", - "@abp/bootstrap-daterangepicker": "~9.2.0-rc.1", - "@abp/datatables.net-bs5": "~9.2.0-rc.1", - "@abp/font-awesome": "~9.2.0-rc.1", - "@abp/jquery-form": "~9.2.0-rc.1", - "@abp/jquery-validation-unobtrusive": "~9.2.0-rc.1", - "@abp/lodash": "~9.2.0-rc.1", - "@abp/luxon": "~9.2.0-rc.1", - "@abp/malihu-custom-scrollbar-plugin": "~9.2.0-rc.1", - "@abp/moment": "~9.2.0-rc.1", - "@abp/select2": "~9.2.0-rc.1", - "@abp/sweetalert2": "~9.2.0-rc.1", - "@abp/timeago": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui": "~9.2.0-rc.4", + "@abp/bootstrap": "~9.2.0-rc.4", + "@abp/bootstrap-datepicker": "~9.2.0-rc.4", + "@abp/bootstrap-daterangepicker": "~9.2.0-rc.4", + "@abp/datatables.net-bs5": "~9.2.0-rc.4", + "@abp/font-awesome": "~9.2.0-rc.4", + "@abp/jquery-form": "~9.2.0-rc.4", + "@abp/jquery-validation-unobtrusive": "~9.2.0-rc.4", + "@abp/lodash": "~9.2.0-rc.4", + "@abp/luxon": "~9.2.0-rc.4", + "@abp/malihu-custom-scrollbar-plugin": "~9.2.0-rc.4", + "@abp/moment": "~9.2.0-rc.4", + "@abp/select2": "~9.2.0-rc.4", + "@abp/sweetalert2": "~9.2.0-rc.4", + "@abp/timeago": "~9.2.0-rc.4" }, "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 385ae37092..948d8af9f4 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.2.0-rc.1", + "version": "9.2.0-rc.4", "lockfileVersion": 1, "requires": true, "packages": { diff --git a/npm/packs/aspnetcore.mvc.ui/package.json b/npm/packs/aspnetcore.mvc.ui/package.json index 41bc43b7e7..ebbd33adb5 100644 --- a/npm/packs/aspnetcore.mvc.ui/package.json +++ b/npm/packs/aspnetcore.mvc.ui/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/aspnetcore.mvc.ui", "repository": { "type": "git", diff --git a/npm/packs/blogging/package.json b/npm/packs/blogging/package.json index b54ad1a4a6..921dd7a405 100644 --- a/npm/packs/blogging/package.json +++ b/npm/packs/blogging/package.json @@ -1,14 +1,14 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/blogging", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.shared": "~9.2.0-rc.1", - "@abp/owl.carousel": "~9.2.0-rc.1", - "@abp/prismjs": "~9.2.0-rc.1", - "@abp/tui-editor": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.shared": "~9.2.0-rc.4", + "@abp/owl.carousel": "~9.2.0-rc.4", + "@abp/prismjs": "~9.2.0-rc.4", + "@abp/tui-editor": "~9.2.0-rc.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/bootstrap-datepicker/package.json b/npm/packs/bootstrap-datepicker/package.json index 7da1d9c85b..be963ec642 100644 --- a/npm/packs/bootstrap-datepicker/package.json +++ b/npm/packs/bootstrap-datepicker/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/bootstrap-datepicker", "repository": { "type": "git", diff --git a/npm/packs/bootstrap-daterangepicker/package.json b/npm/packs/bootstrap-daterangepicker/package.json index 891521467c..9e8f62ee6a 100644 --- a/npm/packs/bootstrap-daterangepicker/package.json +++ b/npm/packs/bootstrap-daterangepicker/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/bootstrap-daterangepicker", "repository": { "type": "git", diff --git a/npm/packs/bootstrap/package.json b/npm/packs/bootstrap/package.json index d6da941990..9210f6f29f 100644 --- a/npm/packs/bootstrap/package.json +++ b/npm/packs/bootstrap/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/bootstrap", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "bootstrap": "^5.3.3" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/chart.js/package.json b/npm/packs/chart.js/package.json index 99b723d749..c2beb1bc90 100644 --- a/npm/packs/chart.js/package.json +++ b/npm/packs/chart.js/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/chart.js", "publishConfig": { "access": "public" diff --git a/npm/packs/clipboard/package.json b/npm/packs/clipboard/package.json index 233fa5d8cd..5e76514257 100644 --- a/npm/packs/clipboard/package.json +++ b/npm/packs/clipboard/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/clipboard", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "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 81c078f77b..0b2a5b0854 100644 --- a/npm/packs/cms-kit.admin/package.json +++ b/npm/packs/cms-kit.admin/package.json @@ -1,16 +1,16 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/cms-kit.admin", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/codemirror": "~9.2.0-rc.1", - "@abp/jstree": "~9.2.0-rc.1", - "@abp/markdown-it": "~9.2.0-rc.1", - "@abp/slugify": "~9.2.0-rc.1", - "@abp/tui-editor": "~9.2.0-rc.1", - "@abp/uppy": "~9.2.0-rc.1" + "@abp/codemirror": "~9.2.0-rc.4", + "@abp/jstree": "~9.2.0-rc.4", + "@abp/markdown-it": "~9.2.0-rc.4", + "@abp/slugify": "~9.2.0-rc.4", + "@abp/tui-editor": "~9.2.0-rc.4", + "@abp/uppy": "~9.2.0-rc.4" }, "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 64a113ae98..13cb6da556 100644 --- a/npm/packs/cms-kit.public/package.json +++ b/npm/packs/cms-kit.public/package.json @@ -1,12 +1,12 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/cms-kit.public", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/highlight.js": "~9.2.0-rc.1", - "@abp/star-rating-svg": "~9.2.0-rc.1" + "@abp/highlight.js": "~9.2.0-rc.4", + "@abp/star-rating-svg": "~9.2.0-rc.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/cms-kit/package.json b/npm/packs/cms-kit/package.json index b9c87a1562..9c60433dd3 100644 --- a/npm/packs/cms-kit/package.json +++ b/npm/packs/cms-kit/package.json @@ -1,12 +1,12 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/cms-kit", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/cms-kit.admin": "~9.2.0-rc.1", - "@abp/cms-kit.public": "~9.2.0-rc.1" + "@abp/cms-kit.admin": "~9.2.0-rc.4", + "@abp/cms-kit.public": "~9.2.0-rc.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/codemirror/package.json b/npm/packs/codemirror/package.json index 7403c6e1e2..86726af360 100644 --- a/npm/packs/codemirror/package.json +++ b/npm/packs/codemirror/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/codemirror", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "codemirror": "^5.65.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/core/package.json b/npm/packs/core/package.json index d0254b6e5f..b4acf95d1d 100644 --- a/npm/packs/core/package.json +++ b/npm/packs/core/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/core", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/utils": "~9.2.0-rc.1" + "@abp/utils": "~9.2.0-rc.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/core/src/abp.js b/npm/packs/core/src/abp.js index 05c9f3bbe5..f117c4d5f1 100644 --- a/npm/packs/core/src/abp.js +++ b/npm/packs/core/src/abp.js @@ -4,7 +4,9 @@ var abp = abp || {}; /* Application paths *****************************************/ //Current application root path (including virtual directory if exists). - abp.appPath = abp.appPath || '/'; + var baseElement = document.querySelector('base'); + var baseHref = baseElement ? baseElement.getAttribute('href') : null; + abp.appPath = baseHref || abp.appPath || '/'; abp.pageLoadTime = new Date(); @@ -81,7 +83,7 @@ var abp = abp || {}; if (resource) { return resource; } - + var legacySource = abp.localization.values[resourceName]; if (legacySource) { return { @@ -89,11 +91,11 @@ var abp = abp || {}; baseResources: [] }; } - - abp.log.warn('Could not find localization source: ' + resourceName); + + abp.log.warn('Could not find localization source: ' + resourceName); return null; }; - + abp.localization.internal.localize = function (key, sourceName) { var resource = abp.localization.internal.getResource(sourceName); if (!resource){ @@ -104,7 +106,7 @@ var abp = abp || {}; } var value = resource.texts[key]; - if (value === undefined) { + if (value === undefined) { for (var i = 0; i < resource.baseResources.length; i++){ var basedArguments = Array.prototype.slice.call(arguments, 0); basedArguments[1] = resource.baseResources[i]; @@ -114,7 +116,7 @@ var abp = abp || {}; return result; } } - + return { value: key, found: false @@ -135,7 +137,7 @@ var abp = abp || {}; if (sourceName === '_') { //A convention to suppress the localization return key; } - + if (sourceName) { return abp.localization.internal.localize.apply(this, arguments).value; } @@ -750,7 +752,11 @@ var abp = abp || {}; abp.clock.supportsMultipleTimezone = function () { return abp.clock.kind === 'Utc'; - }; + } + + abp.clock.timeZone = function () { + return abp.setting.get('Abp.Timing.TimeZone') || abp.clock.browserTimeZone(); + } // Normalize Date object or date string to standard string format that will be sent to server abp.clock.normalizeToString = function (date) { @@ -763,32 +769,42 @@ var abp = abp || {}; return date; } - if (abp.clock.kind === 'Utc') { - return dateObj.toISOString(); - } - function padZero(num) { return num < 10 ? '0' + num : num; } - function padMilliseconds(num) { - if (num < 10) return '00' + num; - if (num < 100) return '0' + num; - return num; + var addZulu = false; + if (abp.clock.supportsMultipleTimezone()) { + var timeZone = abp.clock.timeZone(); + var now = new Date(); + var formattedDate = now.toLocaleString('en-US', { timeZone: timeZone, timeZoneName: 'longOffset' }); + var match = formattedDate.match(/GMT([+-]\d+)/); + var targetOffsetHours = match ? parseInt(match[1], 10) : 0; + dateObj = new Date(dateObj.getTime() - (targetOffsetHours * 60 * 60 * 1000)); + addZulu = true; } - - // yyyy-MM-ddTHH:mm:ss.SSS + + // yyyy-MM-DDTHH:mm:ss return dateObj.getFullYear() + '-' + - padZero(dateObj.getMonth() + 1) + '-' + - padZero(dateObj.getDate()) + 'T' + - padZero(dateObj.getHours()) + ':' + - padZero(dateObj.getMinutes()) + ':' + - padZero(dateObj.getSeconds()) + '.' + - padMilliseconds(dateObj.getMilliseconds()); + padZero(dateObj.getMonth() + 1) + '-' + + padZero(dateObj.getDate()) + 'T' + + padZero(dateObj.getHours()) + ':' + + padZero(dateObj.getMinutes()) + ':' + + padZero(dateObj.getSeconds()) + (addZulu ? 'Z' : ''); + }; + + // Default options for toLocaleString + abp.clock.toLocaleStringOptions = abp.clock.toLocaleStringOptions || { + "year": "numeric", + "month": "long", + "day": "numeric", + "hour": "numeric", + "minute": "numeric", + "second": "numeric" }; // Normalize date string to locale date string that will be displayed to user - abp.clock.normalizeToLocaleString = function (dateString) { + abp.clock.normalizeToLocaleString = function (dateString, options) { if (!dateString) { return dateString; } @@ -797,11 +813,36 @@ var abp = abp || {}; if (isNaN(date)) { return dateString; } - - //TODO: Get timezone setting and pass it to toLocaleString - return date.toLocaleString(); + + var culture = abp.localization.currentCulture.cultureName; + options = options || abp.clock.toLocaleStringOptions; + if (abp.clock.supportsMultipleTimezone()) { + var timezone = abp.clock.timeZone(); + if (timezone) { + return date.toLocaleString(culture, Object.assign({}, options, { timeZone: timezone })); + } + } + return date.toLocaleString(culture, options); } + abp.clock.browserTimeZone = function () { + return Intl.DateTimeFormat().resolvedOptions().timeZone; + } + + abp.clock.trySetBrowserTimeZoneToCookie = true; + + abp.clock.setBrowserTimeZoneToCookie = function () { + if (!abp.clock.trySetBrowserTimeZoneToCookie || !abp.clock.supportsMultipleTimezone() || abp.currentUser.isAuthenticated) { + return; + } + + abp.utils.setCookieValue('__timezone', abp.clock.browserTimeZone(), new Date(new Date().setFullYear(new Date().getFullYear() + 1)), '/'); + } + + abp.event.on('abp.configurationInitialized', function () { + abp.clock.setBrowserTimeZoneToCookie(); + }); + /* FEATURES *************************************************/ abp.features = abp.features || {}; diff --git a/npm/packs/cropperjs/package.json b/npm/packs/cropperjs/package.json index 37c6fe62a2..2c307902dd 100644 --- a/npm/packs/cropperjs/package.json +++ b/npm/packs/cropperjs/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/cropperjs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "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 697dffcc18..47c634e5b2 100644 --- a/npm/packs/datatables.net-bs4/package.json +++ b/npm/packs/datatables.net-bs4/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/datatables.net-bs4", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/datatables.net": "~9.2.0-rc.1", + "@abp/datatables.net": "~9.2.0-rc.4", "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 aadfc64a5d..564563b360 100644 --- a/npm/packs/datatables.net-bs5/package.json +++ b/npm/packs/datatables.net-bs5/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/datatables.net-bs5", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/datatables.net": "~9.2.0-rc.1", + "@abp/datatables.net": "~9.2.0-rc.4", "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 8cea2655e5..90267e19fc 100644 --- a/npm/packs/datatables.net/package.json +++ b/npm/packs/datatables.net/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/datatables.net", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", + "@abp/jquery": "~9.2.0-rc.4", "datatables.net": "^2.1.8" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/docs/package.json b/npm/packs/docs/package.json index aee539d036..357c2b7dd0 100644 --- a/npm/packs/docs/package.json +++ b/npm/packs/docs/package.json @@ -1,15 +1,15 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/docs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/anchor-js": "~9.2.0-rc.1", - "@abp/clipboard": "~9.2.0-rc.1", - "@abp/malihu-custom-scrollbar-plugin": "~9.2.0-rc.1", - "@abp/popper.js": "~9.2.0-rc.1", - "@abp/prismjs": "~9.2.0-rc.1" + "@abp/anchor-js": "~9.2.0-rc.4", + "@abp/clipboard": "~9.2.0-rc.4", + "@abp/malihu-custom-scrollbar-plugin": "~9.2.0-rc.4", + "@abp/popper.js": "~9.2.0-rc.4", + "@abp/prismjs": "~9.2.0-rc.4" }, "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 c44a479ac6..c125cafc98 100644 --- a/npm/packs/flag-icon-css/package.json +++ b/npm/packs/flag-icon-css/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "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 03c72f7258..cc97de389c 100644 --- a/npm/packs/flag-icons/package.json +++ b/npm/packs/flag-icons/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/flag-icons", "publishConfig": { "access": "public" diff --git a/npm/packs/font-awesome/package.json b/npm/packs/font-awesome/package.json index 6070797e70..18cbbe5c39 100644 --- a/npm/packs/font-awesome/package.json +++ b/npm/packs/font-awesome/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/font-awesome", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "@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 e9f1a9e31c..a9fa55d19f 100644 --- a/npm/packs/highlight.js/package.json +++ b/npm/packs/highlight.js/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/highlight.js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "@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 3d7e70ead5..f7d41ee38e 100644 --- a/npm/packs/jquery-form/package.json +++ b/npm/packs/jquery-form/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/jquery-form", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", + "@abp/jquery": "~9.2.0-rc.4", "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 0ee8bb2fdb..f790a4c5df 100644 --- a/npm/packs/jquery-validation-unobtrusive/package.json +++ b/npm/packs/jquery-validation-unobtrusive/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/jquery-validation-unobtrusive", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery-validation": "~9.2.0-rc.1", + "@abp/jquery-validation": "~9.2.0-rc.4", "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 e1197f6aa9..8741301aea 100644 --- a/npm/packs/jquery-validation/package.json +++ b/npm/packs/jquery-validation/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/jquery-validation", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", + "@abp/jquery": "~9.2.0-rc.4", "jquery-validation": "^1.21.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/jquery/package.json b/npm/packs/jquery/package.json index 2468e4cca1..3646a0e27f 100644 --- a/npm/packs/jquery/package.json +++ b/npm/packs/jquery/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/jquery", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "jquery": "~3.7.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/jstree/package.json b/npm/packs/jstree/package.json index c13ab3e650..4ef328923f 100644 --- a/npm/packs/jstree/package.json +++ b/npm/packs/jstree/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/jstree", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", + "@abp/jquery": "~9.2.0-rc.4", "jstree": "^3.3.17" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/lodash/package.json b/npm/packs/lodash/package.json index 349d47e8d6..54e0a0d86a 100644 --- a/npm/packs/lodash/package.json +++ b/npm/packs/lodash/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/lodash", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "lodash": "^4.17.21" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/luxon/package.json b/npm/packs/luxon/package.json index 4de7766faa..d0c0cbf4bf 100644 --- a/npm/packs/luxon/package.json +++ b/npm/packs/luxon/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/luxon", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "luxon": "^3.5.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/luxon/src/abp.luxon.js b/npm/packs/luxon/src/abp.luxon.js index b04de7cadf..40b3f965b8 100644 --- a/npm/packs/luxon/src/abp.luxon.js +++ b/npm/packs/luxon/src/abp.luxon.js @@ -32,7 +32,7 @@ var abp = abp || {}; .fromFormat( getObjectValue(form, field), abp.localization.currentCulture.dateTimeFormat.shortDatePattern, - {locale: abp.localization.currentCulture.cultureName} + { locale: abp.localization.currentCulture.cultureName } ); if (!dateTime.invalid) { @@ -43,4 +43,60 @@ var abp = abp || {}; return form; } + // Normalize Date object or date string to standard string format that will be sent to server + abp.clock.normalizeToString = function (date) { + if (!date) { + return date; + } + + var dateObj = date instanceof Date ? date : new Date(date); + if (isNaN(dateObj)) { + return date; + } + + var timeZone = abp.clock.timeZone(); + if (abp.clock.supportsMultipleTimezone() && timeZone) { + return luxon.DateTime.fromObject({ + year: dateObj.getFullYear(), + month: dateObj.getMonth() + 1, + day: dateObj.getDate(), + hour: dateObj.getHours(), + minute: dateObj.getMinutes(), + second: dateObj.getSeconds() + }, { zone: timeZone }).setZone("utc").toISO(); + } else { + return luxon.DateTime.fromJSDate(dateObj).toFormat("yyyy-MM-dd'T'HH:mm:ss"); + } + }; + + // Normalize date string to locale date string that will be displayed to user + abp.clock.normalizeToLocaleString = function (dateString, options) { + if (!dateString) { + return dateString; + } + + var date = new Date(dateString); + if (isNaN(date)) { + return dateString; + } + + options = options || abp.clock.toLocaleStringOptions; + if (abp.clock.supportsMultipleTimezone()) { + var timezone = abp.clock.timeZone(); + if (timezone) { + return luxon.DateTime.fromJSDate(date) + .setZone(timezone) + .setLocale(abp.localization.currentCulture.cultureName) + .toLocaleString(options); + } + } + + return luxon.DateTime.fromJSDate(date) + .setLocale(abp.localization.currentCulture.cultureName) + .toLocaleString(options); + } + + abp.clock.browserTimeZone = function () { + return luxon.DateTime.local().zoneName; + } })(jQuery); diff --git a/npm/packs/malihu-custom-scrollbar-plugin/package.json b/npm/packs/malihu-custom-scrollbar-plugin/package.json index 415b7425bc..9c6e5e5236 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.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/malihu-custom-scrollbar-plugin", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "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 d1bedb4ece..b6c3bd3196 100644 --- a/npm/packs/markdown-it/package.json +++ b/npm/packs/markdown-it/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/markdown-it", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "markdown-it": "^14.1.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/moment/package.json b/npm/packs/moment/package.json index 2723c28be7..3601298abb 100644 --- a/npm/packs/moment/package.json +++ b/npm/packs/moment/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/moment", "repository": { "type": "git", diff --git a/npm/packs/owl.carousel/package.json b/npm/packs/owl.carousel/package.json index a9dbe54bee..4fc5064e41 100644 --- a/npm/packs/owl.carousel/package.json +++ b/npm/packs/owl.carousel/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/owl.carousel", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "owl.carousel": "^2.3.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/popper.js/package.json b/npm/packs/popper.js/package.json index 5aab07642d..e9412ebbfc 100644 --- a/npm/packs/popper.js/package.json +++ b/npm/packs/popper.js/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/popper.js", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "@popperjs/core": "^2.11.8" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/prismjs/package.json b/npm/packs/prismjs/package.json index e34744a1b5..934dd5ff42 100644 --- a/npm/packs/prismjs/package.json +++ b/npm/packs/prismjs/package.json @@ -1,12 +1,12 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/prismjs", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/clipboard": "~9.2.0-rc.1", - "@abp/core": "~9.2.0-rc.1", + "@abp/clipboard": "~9.2.0-rc.4", + "@abp/core": "~9.2.0-rc.4", "prismjs": "^1.29.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/qrcode/package.json b/npm/packs/qrcode/package.json index 9feb5049cf..b0f077f2b4 100644 --- a/npm/packs/qrcode/package.json +++ b/npm/packs/qrcode/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/qrcode", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1" + "@abp/core": "~9.2.0-rc.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/select2/package.json b/npm/packs/select2/package.json index e55c32a0de..20b95d940d 100644 --- a/npm/packs/select2/package.json +++ b/npm/packs/select2/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/select2", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "select2": "^4.0.13" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/signalr/package.json b/npm/packs/signalr/package.json index 8b78d96d3f..433286fbe5 100644 --- a/npm/packs/signalr/package.json +++ b/npm/packs/signalr/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/signalr", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "@microsoft/signalr": "~8.0.7" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/slugify/package.json b/npm/packs/slugify/package.json index f28f636cfa..972859c18f 100644 --- a/npm/packs/slugify/package.json +++ b/npm/packs/slugify/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "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 425db70019..b3ecf385ad 100644 --- a/npm/packs/star-rating-svg/package.json +++ b/npm/packs/star-rating-svg/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/star-rating-svg", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", + "@abp/jquery": "~9.2.0-rc.4", "star-rating-svg": "^3.5.0" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/sweetalert2/package.json b/npm/packs/sweetalert2/package.json index 66f088aebd..3b81d40af4 100644 --- a/npm/packs/sweetalert2/package.json +++ b/npm/packs/sweetalert2/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/sweetalert2", "publishConfig": { "access": "public" @@ -10,7 +10,7 @@ "directory": "npm/packs/sweetalert2" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "sweetalert2": "^11.14.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/timeago/package.json b/npm/packs/timeago/package.json index 5346aacaf2..ff29071f8e 100644 --- a/npm/packs/timeago/package.json +++ b/npm/packs/timeago/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/timeago", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", + "@abp/jquery": "~9.2.0-rc.4", "timeago": "^1.6.7" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/toastr/package.json b/npm/packs/toastr/package.json index a16d50a51b..9f59fcecb6 100644 --- a/npm/packs/toastr/package.json +++ b/npm/packs/toastr/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/toastr", "repository": { "type": "git", @@ -10,7 +10,7 @@ "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", + "@abp/jquery": "~9.2.0-rc.4", "toastr": "^2.1.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/tui-editor/package.json b/npm/packs/tui-editor/package.json index 0df242ac9f..3b825f2c3e 100644 --- a/npm/packs/tui-editor/package.json +++ b/npm/packs/tui-editor/package.json @@ -1,12 +1,12 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/tui-editor", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/jquery": "~9.2.0-rc.1", - "@abp/prismjs": "~9.2.0-rc.1" + "@abp/jquery": "~9.2.0-rc.4", + "@abp/prismjs": "~9.2.0-rc.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/uppy/package.json b/npm/packs/uppy/package.json index 734ae62e76..b81b01a753 100644 --- a/npm/packs/uppy/package.json +++ b/npm/packs/uppy/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/uppy", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "uppy": "^4.4.1" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", diff --git a/npm/packs/utils/package.json b/npm/packs/utils/package.json index 1c23228042..6a0881e98e 100644 --- a/npm/packs/utils/package.json +++ b/npm/packs/utils/package.json @@ -1,6 +1,6 @@ { "name": "@abp/utils", - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "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 b497d94a4e..09743df686 100644 --- a/npm/packs/vee-validate/package.json +++ b/npm/packs/vee-validate/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/vee-validate", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/vue": "~9.2.0-rc.1", + "@abp/vue": "~9.2.0-rc.4", "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 fb654b85b4..5ca0999b9b 100644 --- a/npm/packs/virtual-file-explorer/package.json +++ b/npm/packs/virtual-file-explorer/package.json @@ -1,12 +1,12 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/virtual-file-explorer", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/clipboard": "~9.2.0-rc.1", - "@abp/prismjs": "~9.2.0-rc.1" + "@abp/clipboard": "~9.2.0-rc.4", + "@abp/prismjs": "~9.2.0-rc.4" }, "gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431", "homepage": "https://abp.io", diff --git a/npm/packs/vue/package.json b/npm/packs/vue/package.json index dec826c8ed..6fb12496f9 100644 --- a/npm/packs/vue/package.json +++ b/npm/packs/vue/package.json @@ -1,5 +1,5 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/vue", "publishConfig": { "access": "public" diff --git a/npm/packs/zxcvbn/package.json b/npm/packs/zxcvbn/package.json index 1f3db85f80..02a8cf02d4 100644 --- a/npm/packs/zxcvbn/package.json +++ b/npm/packs/zxcvbn/package.json @@ -1,11 +1,11 @@ { - "version": "9.2.0-rc.1", + "version": "9.2.0-rc.4", "name": "@abp/zxcvbn", "publishConfig": { "access": "public" }, "dependencies": { - "@abp/core": "~9.2.0-rc.1", + "@abp/core": "~9.2.0-rc.4", "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 ecf5781fa3..f9dd902a21 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 64579d7de7..548ebd6806 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 9fcba5587f..5013948d72 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 38f7029298..b27ff917d5 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 7fcac202c3..0a87ddc5c9 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 871516c165..e89c0b6fba 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 ca49a232df..4f3ee6ccda 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 48f0a729c0..6c3a5641d9 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 ed30e62b3f..fa652ba725 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 509b3f7a34..362cf5fde1 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 12d511eece..fbdee312c6 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 f3fd4fdcf5..f2c1c1ac1b 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 494ea9ca62..cda1d2ed7e 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 f92955ed65..7fe9575bc8 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 366da77677..d2e95829cd 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 2886be384e..c370c25dd1 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 48003c3244..1de76a0454 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 5a3440867d..57181e435d 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 ddfbfd446f..5e3e8747a9 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.2.0-rc.1", - "@abp/ng.components": "~9.2.0-rc.1", - "@abp/ng.core": "~9.2.0-rc.1", - "@abp/ng.identity": "~9.2.0-rc.1", - "@abp/ng.oauth": "~9.2.0-rc.1", - "@abp/ng.setting-management": "~9.2.0-rc.1", - "@abp/ng.tenant-management": "~9.2.0-rc.1", - "@abp/ng.theme.lepton-x": "~4.2.0-rc.1", - "@abp/ng.theme.shared": "~9.2.0-rc.1", + "@abp/ng.account": "~9.2.0-rc.4", + "@abp/ng.components": "~9.2.0-rc.4", + "@abp/ng.core": "~9.2.0-rc.4", + "@abp/ng.identity": "~9.2.0-rc.4", + "@abp/ng.oauth": "~9.2.0-rc.4", + "@abp/ng.setting-management": "~9.2.0-rc.4", + "@abp/ng.tenant-management": "~9.2.0-rc.4", + "@abp/ng.theme.lepton-x": "~4.2.0-rc.4", + "@abp/ng.theme.shared": "~9.2.0-rc.4", "@angular/animations": "~19.1.0", "@angular/common": "~19.1.0", "@angular/compiler": "~19.1.0", @@ -36,7 +36,7 @@ "zone.js": "~0.15.0" }, "devDependencies": { - "@abp/ng.schematics": "~9.2.0-rc.1", + "@abp/ng.schematics": "~9.2.0-rc.4", "@angular-devkit/build-angular": "~19.1.0", "@angular-eslint/builder": "~19.0.0", "@angular-eslint/eslint-plugin": "~19.0.0", diff --git a/templates/app-nolayers/angular/src/app/app-routing.module.ts b/templates/app-nolayers/angular/src/app/app-routing.module.ts deleted file mode 100644 index 0d9f82ea25..0000000000 --- a/templates/app-nolayers/angular/src/app/app-routing.module.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -const routes: Routes = [ - { - path: '', - pathMatch: 'full', - loadChildren: () => import('./home/home.module').then(m => m.HomeModule), - }, - { - path: 'account', - loadChildren: () => import('@abp/ng.account').then(m => m.AccountModule.forLazy()), - }, - { - path: 'identity', - loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()), - }, - { - path: 'tenant-management', - loadChildren: () => - import('@abp/ng.tenant-management').then(m => m.TenantManagementModule.forLazy()), - }, - { - path: 'setting-management', - loadChildren: () => - import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()), - }, -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes, {})], - exports: [RouterModule], -}) -export class AppRoutingModule {} diff --git a/templates/app-nolayers/angular/src/app/app.component.ts b/templates/app-nolayers/angular/src/app/app.component.ts index 5476691764..5ef8f52ddb 100644 --- a/templates/app-nolayers/angular/src/app/app.component.ts +++ b/templates/app-nolayers/angular/src/app/app.component.ts @@ -1,12 +1,14 @@ import { Component } from '@angular/core'; +import {InternetConnectionStatusComponent, LoaderBarComponent} from "@abp/ng.theme.shared"; +import {DynamicLayoutComponent} from "@abp/ng.core"; @Component({ - standalone: false, selector: 'app-root', template: ` `, + imports: [LoaderBarComponent, DynamicLayoutComponent, InternetConnectionStatusComponent] }) export class AppComponent {} diff --git a/templates/app-nolayers/angular/src/app/app.module.ts b/templates/app-nolayers/angular/src/app/app.config.ts similarity index 50% rename from templates/app-nolayers/angular/src/app/app.module.ts rename to templates/app-nolayers/angular/src/app/app.config.ts index 48ae3ab98a..5fcd465589 100644 --- a/templates/app-nolayers/angular/src/app/app.module.ts +++ b/templates/app-nolayers/angular/src/app/app.config.ts @@ -1,39 +1,24 @@ -import { provideAccountConfig } from '@abp/ng.account/config'; -import { CoreModule, provideAbpCore, withOptions } from '@abp/ng.core'; +import {ApplicationConfig, importProvidersFrom} from '@angular/core'; +import {provideAnimations} from "@angular/platform-browser/animations"; +import {provideRouter} from "@angular/router"; +import { appRoutes } from './app.routes'; +import { APP_ROUTE_PROVIDER } from './route.provider'; +import { provideAbpCore, withOptions } from '@abp/ng.core'; +import { environment } from '../environments/environment'; import { registerLocale } from '@abp/ng.core/locale'; -import { provideIdentityConfig } from '@abp/ng.identity/config'; +import { provideAbpOAuth } from '@abp/ng.oauth'; +import { provideAbpThemeShared } from '@abp/ng.theme.shared'; import { provideSettingManagementConfig } from '@abp/ng.setting-management/config'; +import { provideAccountConfig } from '@abp/ng.account/config'; +import { provideIdentityConfig } from '@abp/ng.identity/config'; import { provideTenantManagementConfig } from '@abp/ng.tenant-management/config'; -import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x'; -import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts'; -import { - InternetConnectionStatusComponent, - ThemeSharedModule, - provideAbpThemeShared, -} from '@abp/ng.theme.shared'; import { provideFeatureManagementConfig } from '@abp/ng.feature-management'; -import { provideAbpOAuth } from '@abp/ng.oauth'; -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { environment } from '../environments/environment'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { APP_ROUTE_PROVIDER } from './route.provider'; +import {ThemeLeptonXModule} from "@abp/ng.theme.lepton-x"; +import {SideMenuLayoutModule} from "@abp/ng.theme.lepton-x/layouts"; -@NgModule({ - imports: [ - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, - CoreModule, - ThemeSharedModule, - ThemeLeptonXModule.forRoot(), - SideMenuLayoutModule.forRoot(), - InternetConnectionStatusComponent, - ], - declarations: [AppComponent], +export const appConfig: ApplicationConfig = { providers: [ + provideRouter(appRoutes), APP_ROUTE_PROVIDER, provideAbpCore( withOptions({ @@ -48,7 +33,10 @@ import { APP_ROUTE_PROVIDER } from './route.provider'; provideIdentityConfig(), provideTenantManagementConfig(), provideFeatureManagementConfig(), + provideAnimations(), + importProvidersFrom([ + ThemeLeptonXModule.forRoot(), + SideMenuLayoutModule.forRoot(), + ]) ], - bootstrap: [AppComponent], -}) -export class AppModule {} +}; diff --git a/templates/app-nolayers/angular/src/app/app.routes.ts b/templates/app-nolayers/angular/src/app/app.routes.ts new file mode 100644 index 0000000000..2c5b4cae93 --- /dev/null +++ b/templates/app-nolayers/angular/src/app/app.routes.ts @@ -0,0 +1,27 @@ +import { Routes } from '@angular/router'; + +export const appRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + loadChildren: () => import('./home/home.routes').then(m => m.homeRoutes), + }, + { + path: 'account', + loadChildren: () => import('@abp/ng.account').then(m => m.createRoutes()), + }, + { + path: 'identity', + loadChildren: () => import('@abp/ng.identity').then(m => m.createRoutes()), + }, + { + path: 'tenant-management', + loadChildren: () => + import('@abp/ng.tenant-management').then(m => m.createRoutes()), + }, + { + path: 'setting-management', + loadChildren: () => + import('@abp/ng.setting-management').then(m => m.createRoutes()), + }, +]; diff --git a/templates/app-nolayers/angular/src/app/home/home-routing.module.ts b/templates/app-nolayers/angular/src/app/home/home-routing.module.ts deleted file mode 100644 index 7089990134..0000000000 --- a/templates/app-nolayers/angular/src/app/home/home-routing.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import { HomeComponent } from './home.component'; - -const routes: Routes = [{ path: '', component: HomeComponent }]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class HomeRoutingModule {} diff --git a/templates/app-nolayers/angular/src/app/home/home.component.ts b/templates/app-nolayers/angular/src/app/home/home.component.ts index 458f51628c..4fa3761541 100644 --- a/templates/app-nolayers/angular/src/app/home/home.component.ts +++ b/templates/app-nolayers/angular/src/app/home/home.component.ts @@ -1,11 +1,12 @@ -import { AuthService } from '@abp/ng.core'; +import {AuthService, LocalizationPipe} from '@abp/ng.core'; import { Component, inject } from '@angular/core'; +import {CommonModule} from "@angular/common"; @Component({ - standalone: false, selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'], + imports: [CommonModule, LocalizationPipe], }) export class HomeComponent { private authService = inject(AuthService); diff --git a/templates/app-nolayers/angular/src/app/home/home.module.ts b/templates/app-nolayers/angular/src/app/home/home.module.ts deleted file mode 100644 index 72d20ccc65..0000000000 --- a/templates/app-nolayers/angular/src/app/home/home.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NgModule } from '@angular/core'; -import { SharedModule } from '../shared/shared.module'; -import { HomeRoutingModule } from './home-routing.module'; -import { HomeComponent } from './home.component'; - -@NgModule({ - declarations: [HomeComponent], - imports: [SharedModule, HomeRoutingModule], -}) -export class HomeModule {} diff --git a/templates/app-nolayers/angular/src/app/home/home.routes.ts b/templates/app-nolayers/angular/src/app/home/home.routes.ts new file mode 100644 index 0000000000..b04601eddc --- /dev/null +++ b/templates/app-nolayers/angular/src/app/home/home.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; + +export const homeRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + loadComponent: () => import('./home.component').then(m => m.HomeComponent), + }, +]; diff --git a/templates/app-nolayers/angular/src/main.ts b/templates/app-nolayers/angular/src/main.ts index fa4e0aef33..7180ec1a32 100644 --- a/templates/app-nolayers/angular/src/main.ts +++ b/templates/app-nolayers/angular/src/main.ts @@ -1,13 +1,5 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { AppComponent } from './app/app.component'; -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); 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 32cd17a78e..ee35a6e0e0 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,10 +8,10 @@ - - - - + + + + @@ -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 6684be4dcf..76aab3216a 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.2.0-rc.1", - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.1" + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.4", + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 7761bbde29..a76d39682f 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,10 +8,10 @@ - - - - + + + + @@ -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 adc128035d..3552d6b18d 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.2.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.4" } } 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 34eeb42de4..3ecc615439 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 c42c2e72f1..47ac168149 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,12 +8,12 @@ - + - - + + @@ -79,7 +79,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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 8d3698cb1b..065ffb9552 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,12 +8,12 @@ - + - - + + @@ -80,11 +80,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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 d086ca8003..fa43424fa6 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 a1436f339f..1e5069d33c 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 @@ -8,8 +8,8 @@ - - + + @@ -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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 d5843b5373..0431d2befa 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 @@ -8,8 +8,8 @@ - - + + @@ -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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 f7de34413f..f4c32ff0c8 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 @@ -8,8 +8,8 @@ - - + + @@ -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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 ccbc44f2b8..16e8d6ba9f 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 @@ -8,8 +8,8 @@ - - + + @@ -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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } diff --git a/templates/app/angular/package.json b/templates/app/angular/package.json index ddfbfd446f..5e3e8747a9 100644 --- a/templates/app/angular/package.json +++ b/templates/app/angular/package.json @@ -12,15 +12,15 @@ }, "private": true, "dependencies": { - "@abp/ng.account": "~9.2.0-rc.1", - "@abp/ng.components": "~9.2.0-rc.1", - "@abp/ng.core": "~9.2.0-rc.1", - "@abp/ng.identity": "~9.2.0-rc.1", - "@abp/ng.oauth": "~9.2.0-rc.1", - "@abp/ng.setting-management": "~9.2.0-rc.1", - "@abp/ng.tenant-management": "~9.2.0-rc.1", - "@abp/ng.theme.lepton-x": "~4.2.0-rc.1", - "@abp/ng.theme.shared": "~9.2.0-rc.1", + "@abp/ng.account": "~9.2.0-rc.4", + "@abp/ng.components": "~9.2.0-rc.4", + "@abp/ng.core": "~9.2.0-rc.4", + "@abp/ng.identity": "~9.2.0-rc.4", + "@abp/ng.oauth": "~9.2.0-rc.4", + "@abp/ng.setting-management": "~9.2.0-rc.4", + "@abp/ng.tenant-management": "~9.2.0-rc.4", + "@abp/ng.theme.lepton-x": "~4.2.0-rc.4", + "@abp/ng.theme.shared": "~9.2.0-rc.4", "@angular/animations": "~19.1.0", "@angular/common": "~19.1.0", "@angular/compiler": "~19.1.0", @@ -36,7 +36,7 @@ "zone.js": "~0.15.0" }, "devDependencies": { - "@abp/ng.schematics": "~9.2.0-rc.1", + "@abp/ng.schematics": "~9.2.0-rc.4", "@angular-devkit/build-angular": "~19.1.0", "@angular-eslint/builder": "~19.0.0", "@angular-eslint/eslint-plugin": "~19.0.0", diff --git a/templates/app/angular/src/app/app-routing.module.ts b/templates/app/angular/src/app/app-routing.module.ts deleted file mode 100644 index 0d9f82ea25..0000000000 --- a/templates/app/angular/src/app/app-routing.module.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -const routes: Routes = [ - { - path: '', - pathMatch: 'full', - loadChildren: () => import('./home/home.module').then(m => m.HomeModule), - }, - { - path: 'account', - loadChildren: () => import('@abp/ng.account').then(m => m.AccountModule.forLazy()), - }, - { - path: 'identity', - loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()), - }, - { - path: 'tenant-management', - loadChildren: () => - import('@abp/ng.tenant-management').then(m => m.TenantManagementModule.forLazy()), - }, - { - path: 'setting-management', - loadChildren: () => - import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()), - }, -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes, {})], - exports: [RouterModule], -}) -export class AppRoutingModule {} diff --git a/templates/app/angular/src/app/app.component.ts b/templates/app/angular/src/app/app.component.ts index 5476691764..68cc759e1b 100644 --- a/templates/app/angular/src/app/app.component.ts +++ b/templates/app/angular/src/app/app.component.ts @@ -1,12 +1,14 @@ import { Component } from '@angular/core'; +import { InternetConnectionStatusComponent, LoaderBarComponent } from '@abp/ng.theme.shared'; +import { DynamicLayoutComponent } from '@abp/ng.core'; @Component({ - standalone: false, selector: 'app-root', template: ` `, + imports: [LoaderBarComponent, DynamicLayoutComponent, InternetConnectionStatusComponent], }) export class AppComponent {} diff --git a/templates/app/angular/src/app/app.config.ts b/templates/app/angular/src/app/app.config.ts new file mode 100644 index 0000000000..0d7e64c80c --- /dev/null +++ b/templates/app/angular/src/app/app.config.ts @@ -0,0 +1,46 @@ +import {ApplicationConfig, importProvidersFrom} from '@angular/core'; +import { provideRouter } from '@angular/router'; +import {provideAnimations} from "@angular/platform-browser/animations"; + +import { appRoutes } from './app.routes'; +import { APP_ROUTE_PROVIDER } from './route.provider'; +import { provideAbpCore, withOptions } from '@abp/ng.core'; +import { environment } from '../environments/environment'; +import { registerLocale } from '@abp/ng.core/locale'; +import { provideAbpOAuth } from '@abp/ng.oauth'; +import { provideAbpThemeShared } from '@abp/ng.theme.shared'; +import { provideSettingManagementConfig } from '@abp/ng.setting-management/config'; +import { provideAccountConfig } from '@abp/ng.account/config'; +import { provideIdentityConfig } from '@abp/ng.identity/config'; +import { provideTenantManagementConfig } from '@abp/ng.tenant-management/config'; +import { provideFeatureManagementConfig } from '@abp/ng.feature-management'; +import {ThemeLeptonXModule} from "@abp/ng.theme.lepton-x"; +import {SideMenuLayoutModule} from "@abp/ng.theme.lepton-x/layouts"; +import {AccountLayoutModule} from "@abp/ng.theme.lepton-x/account"; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(appRoutes), + APP_ROUTE_PROVIDER, + provideAbpCore( + withOptions({ + environment, + registerLocaleFn: registerLocale(), + }) + ), + provideAbpOAuth(), + provideAbpThemeShared(), + provideSettingManagementConfig(), + provideAccountConfig(), + provideIdentityConfig(), + provideTenantManagementConfig(), + provideFeatureManagementConfig(), + provideAnimations(), + provideAbpCore(), + importProvidersFrom([ + ThemeLeptonXModule.forRoot(), + SideMenuLayoutModule.forRoot(), + AccountLayoutModule.forRoot(), + ]) + ], +}; diff --git a/templates/app/angular/src/app/app.module.ts b/templates/app/angular/src/app/app.module.ts deleted file mode 100644 index de45468f4a..0000000000 --- a/templates/app/angular/src/app/app.module.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { CoreModule, provideAbpCore, withOptions } from '@abp/ng.core'; -import { registerLocale } from '@abp/ng.core/locale'; -import { - InternetConnectionStatusComponent, - ThemeSharedModule, - provideAbpThemeShared, -} from '@abp/ng.theme.shared'; -import { provideFeatureManagementConfig } from '@abp/ng.feature-management'; -import { provideAbpOAuth } from '@abp/ng.oauth'; -import { provideIdentityConfig } from '@abp/ng.identity/config'; -import { provideSettingManagementConfig } from '@abp/ng.setting-management/config'; -import { provideTenantManagementConfig } from '@abp/ng.tenant-management/config'; -import { provideAccountConfig } from '@abp/ng.account/config'; -import { ThemeLeptonXModule } from '@abp/ng.theme.lepton-x'; -import { SideMenuLayoutModule } from '@abp/ng.theme.lepton-x/layouts'; -import { AccountLayoutModule } from '@abp/ng.theme.lepton-x/account'; -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { environment } from '../environments/environment'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { APP_ROUTE_PROVIDER } from './route.provider'; - -@NgModule({ - imports: [ - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, - CoreModule, - ThemeSharedModule, - ThemeLeptonXModule.forRoot(), - SideMenuLayoutModule.forRoot(), - AccountLayoutModule.forRoot(), - InternetConnectionStatusComponent, - ], - declarations: [AppComponent], - providers: [ - APP_ROUTE_PROVIDER, - provideAbpCore( - withOptions({ - environment, - registerLocaleFn: registerLocale(), - }) - ), - provideAbpOAuth(), - provideAbpThemeShared(), - provideSettingManagementConfig(), - provideAccountConfig(), - provideIdentityConfig(), - provideTenantManagementConfig(), - provideFeatureManagementConfig(), - ], - bootstrap: [AppComponent], -}) -export class AppModule {} diff --git a/templates/app/angular/src/app/app.routes.ts b/templates/app/angular/src/app/app.routes.ts new file mode 100644 index 0000000000..2c5b4cae93 --- /dev/null +++ b/templates/app/angular/src/app/app.routes.ts @@ -0,0 +1,27 @@ +import { Routes } from '@angular/router'; + +export const appRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + loadChildren: () => import('./home/home.routes').then(m => m.homeRoutes), + }, + { + path: 'account', + loadChildren: () => import('@abp/ng.account').then(m => m.createRoutes()), + }, + { + path: 'identity', + loadChildren: () => import('@abp/ng.identity').then(m => m.createRoutes()), + }, + { + path: 'tenant-management', + loadChildren: () => + import('@abp/ng.tenant-management').then(m => m.createRoutes()), + }, + { + path: 'setting-management', + loadChildren: () => + import('@abp/ng.setting-management').then(m => m.createRoutes()), + }, +]; diff --git a/templates/app/angular/src/app/home/home-routing.module.ts b/templates/app/angular/src/app/home/home-routing.module.ts deleted file mode 100644 index 7089990134..0000000000 --- a/templates/app/angular/src/app/home/home-routing.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import { HomeComponent } from './home.component'; - -const routes: Routes = [{ path: '', component: HomeComponent }]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class HomeRoutingModule {} diff --git a/templates/app/angular/src/app/home/home.component.spec.ts b/templates/app/angular/src/app/home/home.component.spec.ts index e02c272719..2243bfca92 100644 --- a/templates/app/angular/src/app/home/home.component.spec.ts +++ b/templates/app/angular/src/app/home/home.component.spec.ts @@ -6,8 +6,6 @@ import { HomeComponent } from "./home.component"; import { OAuthService } from 'angular-oauth2-oidc'; import { AuthService } from '@abp/ng.core'; - - describe("HomeComponent", () => { let fixture: ComponentFixture; const mockOAuthService = jasmine.createSpyObj('OAuthService', ['hasValidAccessToken']) @@ -15,11 +13,12 @@ describe("HomeComponent", () => { beforeEach( waitForAsync(() => { TestBed.configureTestingModule({ - declarations: [HomeComponent], + declarations: [], imports: [ CoreTestingModule.withConfig(), ThemeSharedTestingModule.withConfig(), NgxValidateCoreModule, + HomeComponent ], providers: [ /* mock providers here */ diff --git a/templates/app/angular/src/app/home/home.component.ts b/templates/app/angular/src/app/home/home.component.ts index 458f51628c..cf42b0f606 100644 --- a/templates/app/angular/src/app/home/home.component.ts +++ b/templates/app/angular/src/app/home/home.component.ts @@ -1,11 +1,12 @@ -import { AuthService } from '@abp/ng.core'; +import {AuthService, LocalizationPipe} from '@abp/ng.core'; import { Component, inject } from '@angular/core'; +import {CommonModule} from "@angular/common"; @Component({ - standalone: false, selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'], + imports: [CommonModule, LocalizationPipe] }) export class HomeComponent { private authService = inject(AuthService); diff --git a/templates/app/angular/src/app/home/home.module.ts b/templates/app/angular/src/app/home/home.module.ts deleted file mode 100644 index 72d20ccc65..0000000000 --- a/templates/app/angular/src/app/home/home.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NgModule } from '@angular/core'; -import { SharedModule } from '../shared/shared.module'; -import { HomeRoutingModule } from './home-routing.module'; -import { HomeComponent } from './home.component'; - -@NgModule({ - declarations: [HomeComponent], - imports: [SharedModule, HomeRoutingModule], -}) -export class HomeModule {} diff --git a/templates/app/angular/src/app/home/home.routes.ts b/templates/app/angular/src/app/home/home.routes.ts new file mode 100644 index 0000000000..b04601eddc --- /dev/null +++ b/templates/app/angular/src/app/home/home.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; + +export const homeRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + loadComponent: () => import('./home.component').then(m => m.HomeComponent), + }, +]; diff --git a/templates/app/angular/src/main.ts b/templates/app/angular/src/main.ts index fa4e0aef33..7180ec1a32 100644 --- a/templates/app/angular/src/main.ts +++ b/templates/app/angular/src/main.ts @@ -1,13 +1,5 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { AppComponent } from './app/app.component'; -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); 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 b95c06305c..2d2e9e301d 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 @@ -39,9 +39,9 @@ - - - + + + 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 413f9c7231..8030b601c8 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 72840b70b4..1ba78a108b 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 a8ff20d2ec..a5952f1911 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 adc128035d..3552d6b18d 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.2.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.4" } } 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 20b58b045d..00b35d31c8 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,11 +14,11 @@ - - - - - + + + + + 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 adc128035d..3552d6b18d 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.2.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.4" } } 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 9347651ff4..24f55913bc 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 8861471b0f..8d591b19ec 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 f0da067b27..b5359b0e17 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 adc128035d..3552d6b18d 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.2.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.4" } } 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 65d54aeb32..20e3591801 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,11 +15,11 @@ - - - - - + + + + + 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 adc128035d..3552d6b18d 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.2.0-rc.1", - "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4", + "@abp/aspnetcore.components.server.leptonxlitetheme": "~4.2.0-rc.4" } } 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 156e1147b7..9ea9c32df8 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,12 +8,12 @@ - - + + - + 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 7fbbb92fa8..b68c8562f0 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 @@ -18,11 +18,11 @@ - - - + + + - + 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 7f6b9936fa..6a84c34249 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 3c77133bb4..d03b199ebd 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 6928fab989..7fdb28b27f 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 @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj index 05ef26fb35..f1f76659b6 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyCompanyName.MyProjectName.HttpApi.HostWithIds.csproj @@ -11,8 +11,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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 ea2058353f..f20ee25c62 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 @@ -17,9 +17,9 @@ - - - + + + 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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj index 2e932fad4c..b97fd05460 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj @@ -39,8 +39,8 @@ - - + + 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 a894d66556..c29c293eeb 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "~4.2.0-rc.4" } } 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 8cd45f7b82..d6f2e5f70e 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/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index 79c080216c..68848d75c2 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index 426dcaca1c..791033b241 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -17,15 +17,15 @@ - - + + all runtime; build; native; contentfiles; analyzers - - - - + + + + diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj index 3ca0425b28..8d41ed9e74 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.Web.Tests/MyCompanyName.MyProjectName.Web.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index 65fee12cfc..1a29eebb8d 100644 --- a/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/console/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -13,12 +13,12 @@ - - - - + + + + - + diff --git a/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/maui/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index f33122e97a..66e554f50f 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 fd28632e9d..f67a6e5e30 100644 --- a/templates/module/angular/package.json +++ b/templates/module/angular/package.json @@ -13,15 +13,15 @@ }, "private": true, "dependencies": { - "@abp/ng.account": "~9.2.0-rc.1", - "@abp/ng.components": "~9.2.0-rc.1", - "@abp/ng.core": "~9.2.0-rc.1", - "@abp/ng.identity": "~9.2.0-rc.1", - "@abp/ng.oauth": "~9.2.0-rc.1", - "@abp/ng.setting-management": "~9.2.0-rc.1", - "@abp/ng.tenant-management": "~9.2.0-rc.1", - "@abp/ng.theme.basic": "~9.2.0-rc.1", - "@abp/ng.theme.shared": "~9.2.0-rc.1", + "@abp/ng.account": "~9.2.0-rc.4", + "@abp/ng.components": "~9.2.0-rc.4", + "@abp/ng.core": "~9.2.0-rc.4", + "@abp/ng.identity": "~9.2.0-rc.4", + "@abp/ng.oauth": "~9.2.0-rc.4", + "@abp/ng.setting-management": "~9.2.0-rc.4", + "@abp/ng.tenant-management": "~9.2.0-rc.4", + "@abp/ng.theme.basic": "~9.2.0-rc.4", + "@abp/ng.theme.shared": "~9.2.0-rc.4", "@angular/animations": "~19.1.0", "@angular/common": "~19.1.0", "@angular/compiler": "~19.1.0", @@ -36,7 +36,7 @@ "zone.js": "~0.15.0" }, "devDependencies": { - "@abp/ng.schematics": "~9.2.0-rc.1", + "@abp/ng.schematics": "~9.2.0-rc.4", "@angular-devkit/build-angular": "~19.1.0", "@angular-eslint/builder": "~19.0.0", "@angular-eslint/eslint-plugin": "~19.0.0", diff --git a/templates/module/angular/projects/dev-app/src/app/app-routing.module.ts b/templates/module/angular/projects/dev-app/src/app/app-routing.module.ts deleted file mode 100644 index ba7ee06b13..0000000000 --- a/templates/module/angular/projects/dev-app/src/app/app-routing.module.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; - -const routes: Routes = [ - { - path: '', - pathMatch: 'full', - loadChildren: () => import('./home/home.module').then(m => m.HomeModule), - }, - { - path: 'account', - loadChildren: () => import('@abp/ng.account').then(m => m.AccountModule.forLazy()), - }, - { - path: 'identity', - loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()), - }, - { - path: 'tenant-management', - loadChildren: () => - import('@abp/ng.tenant-management').then(m => m.TenantManagementModule.forLazy()), - }, - { - path: 'setting-management', - loadChildren: () => - import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()), - }, - { - path: 'my-project-name', - loadChildren: () => - import('@my-company-name/my-project-name').then(m => m.MyProjectNameModule.forLazy()), - }, -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes, {})], - exports: [RouterModule], -}) -export class AppRoutingModule {} diff --git a/templates/module/angular/projects/dev-app/src/app/app.component.ts b/templates/module/angular/projects/dev-app/src/app/app.component.ts index 3a2a61014e..bea8e842f1 100644 --- a/templates/module/angular/projects/dev-app/src/app/app.component.ts +++ b/templates/module/angular/projects/dev-app/src/app/app.component.ts @@ -1,11 +1,13 @@ import { Component } from '@angular/core'; +import {LoaderBarComponent} from "@abp/ng.theme.shared"; +import {DynamicLayoutComponent} from "@abp/ng.core"; @Component({ - standalone: false, selector: 'app-root', template: ` - + , `, + imports: [LoaderBarComponent, DynamicLayoutComponent] }) export class AppComponent {} diff --git a/templates/module/angular/projects/dev-app/src/app/app.module.ts b/templates/module/angular/projects/dev-app/src/app/app.config.ts similarity index 54% rename from templates/module/angular/projects/dev-app/src/app/app.module.ts rename to templates/module/angular/projects/dev-app/src/app/app.config.ts index ab0a3acb67..f05d9956cc 100644 --- a/templates/module/angular/projects/dev-app/src/app/app.module.ts +++ b/templates/module/angular/projects/dev-app/src/app/app.config.ts @@ -1,33 +1,24 @@ -import { provideAccountConfig } from '@abp/ng.account/config'; -import { CoreModule, provideAbpCore, withOptions } from '@abp/ng.core'; +import {ApplicationConfig} from '@angular/core'; +import {provideAnimations} from "@angular/platform-browser/animations"; +import {provideRouter} from "@angular/router"; +import { appRoutes } from './app.routes'; +import { APP_ROUTE_PROVIDER } from './route.provider'; +import { provideAbpCore, withOptions } from '@abp/ng.core'; +import { environment } from '../environments/environment'; import { registerLocale } from '@abp/ng.core/locale'; -import { provideIdentityConfig } from '@abp/ng.identity/config'; +import { provideAbpOAuth } from '@abp/ng.oauth'; +import { provideAbpThemeShared } from '@abp/ng.theme.shared'; import { provideSettingManagementConfig } from '@abp/ng.setting-management/config'; +import { provideAccountConfig } from '@abp/ng.account/config'; +import { provideIdentityConfig } from '@abp/ng.identity/config'; import { provideTenantManagementConfig } from '@abp/ng.tenant-management/config'; -import { ThemeBasicModule, provideThemeBasicConfig } from '@abp/ng.theme.basic'; -import { ThemeSharedModule, provideAbpThemeShared } from '@abp/ng.theme.shared'; import { provideFeatureManagementConfig } from '@abp/ng.feature-management'; -import { provideAbpOAuth } from '@abp/ng.oauth'; -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { MyProjectNameConfigModule } from '@my-company-name/my-project-name/config'; -import { environment } from '../environments/environment'; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { APP_ROUTE_PROVIDER } from './route.provider'; +import {provideThemeBasicConfig} from "@abp/ng.theme.basic"; +import {provideMyProjectNameConfig} from "@my-company-name/my-project-name/config"; -@NgModule({ - imports: [ - BrowserModule, - BrowserAnimationsModule, - AppRoutingModule, - CoreModule, - ThemeSharedModule, - MyProjectNameConfigModule.forRoot(), - ThemeBasicModule, - ], +export const appConfig: ApplicationConfig = { providers: [ + provideRouter(appRoutes), APP_ROUTE_PROVIDER, provideAbpCore( withOptions({ @@ -44,9 +35,8 @@ import { APP_ROUTE_PROVIDER } from './route.provider'; provideIdentityConfig(), provideTenantManagementConfig(), provideFeatureManagementConfig(), + provideAnimations(), provideThemeBasicConfig(), + provideMyProjectNameConfig(), ], - declarations: [AppComponent], - bootstrap: [AppComponent], -}) -export class AppModule {} +}; diff --git a/templates/module/angular/projects/dev-app/src/app/app.routes.ts b/templates/module/angular/projects/dev-app/src/app/app.routes.ts new file mode 100644 index 0000000000..0aba22b861 --- /dev/null +++ b/templates/module/angular/projects/dev-app/src/app/app.routes.ts @@ -0,0 +1,32 @@ +import { Routes } from '@angular/router'; + +export const appRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + loadChildren: () => import('./home/home.routes').then(m => m.homeRoutes), + }, + { + path: 'account', + loadChildren: () => import('@abp/ng.account').then(m => m.createRoutes()), + }, + { + path: 'identity', + loadChildren: () => import('@abp/ng.identity').then(m => m.createRoutes()), + }, + { + path: 'tenant-management', + loadChildren: () => + import('@abp/ng.tenant-management').then(m => m.createRoutes()), + }, + { + path: 'setting-management', + loadChildren: () => + import('@abp/ng.setting-management').then(m => m.createRoutes()), + }, + { + path: 'my-project-name', + loadChildren: () => + import('@my-company-name/my-project-name').then(m => m.myProjectNameRoutes), + }, +]; diff --git a/templates/module/angular/projects/dev-app/src/app/home/home-routing.module.ts b/templates/module/angular/projects/dev-app/src/app/home/home-routing.module.ts deleted file mode 100644 index 634706a36c..0000000000 --- a/templates/module/angular/projects/dev-app/src/app/home/home-routing.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import { HomeComponent } from './home.component'; - -const routes: Routes = [ - { - path: '', - children: [{ path: '', component: HomeComponent }], - }, -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class HomeRoutingModule {} diff --git a/templates/module/angular/projects/dev-app/src/app/home/home.component.ts b/templates/module/angular/projects/dev-app/src/app/home/home.component.ts index a0f37a99ca..ab1f354e89 100644 --- a/templates/module/angular/projects/dev-app/src/app/home/home.component.ts +++ b/templates/module/angular/projects/dev-app/src/app/home/home.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; @Component({ - standalone: false, selector: 'app-home', templateUrl: './home.component.html', }) diff --git a/templates/module/angular/projects/dev-app/src/app/home/home.module.ts b/templates/module/angular/projects/dev-app/src/app/home/home.module.ts deleted file mode 100644 index 72d20ccc65..0000000000 --- a/templates/module/angular/projects/dev-app/src/app/home/home.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NgModule } from '@angular/core'; -import { SharedModule } from '../shared/shared.module'; -import { HomeRoutingModule } from './home-routing.module'; -import { HomeComponent } from './home.component'; - -@NgModule({ - declarations: [HomeComponent], - imports: [SharedModule, HomeRoutingModule], -}) -export class HomeModule {} diff --git a/templates/module/angular/projects/dev-app/src/app/home/home.routes.ts b/templates/module/angular/projects/dev-app/src/app/home/home.routes.ts new file mode 100644 index 0000000000..b04601eddc --- /dev/null +++ b/templates/module/angular/projects/dev-app/src/app/home/home.routes.ts @@ -0,0 +1,9 @@ +import { Routes } from '@angular/router'; + +export const homeRoutes: Routes = [ + { + path: '', + pathMatch: 'full', + loadComponent: () => import('./home.component').then(m => m.HomeComponent), + }, +]; diff --git a/templates/module/angular/projects/dev-app/src/main.ts b/templates/module/angular/projects/dev-app/src/main.ts index c7b673cf44..7180ec1a32 100644 --- a/templates/module/angular/projects/dev-app/src/main.ts +++ b/templates/module/angular/projects/dev-app/src/main.ts @@ -1,12 +1,5 @@ -import { enableProdMode } from '@angular/core'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from './app/app.config'; +import { AppComponent } from './app/app.component'; -import { AppModule } from './app/app.module'; -import { environment } from './environments/environment'; - -if (environment.production) { - enableProdMode(); -} - -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); diff --git a/templates/module/angular/projects/my-project-name/config/src/my-project-name-config.module.ts b/templates/module/angular/projects/my-project-name/config/src/my-project-name-config.module.ts index 6ce45aa112..d756a8ad0d 100644 --- a/templates/module/angular/projects/my-project-name/config/src/my-project-name-config.module.ts +++ b/templates/module/angular/projects/my-project-name/config/src/my-project-name-config.module.ts @@ -1,12 +1,6 @@ -import { ModuleWithProviders, NgModule } from '@angular/core'; +import {makeEnvironmentProviders} from '@angular/core'; import { MY_PROJECT_NAME_ROUTE_PROVIDERS } from './providers/route.provider'; -@NgModule() -export class MyProjectNameConfigModule { - static forRoot(): ModuleWithProviders { - return { - ngModule: MyProjectNameConfigModule, - providers: [MY_PROJECT_NAME_ROUTE_PROVIDERS], - }; - } +export function provideMyProjectNameConfig() { + return makeEnvironmentProviders([MY_PROJECT_NAME_ROUTE_PROVIDERS]) } diff --git a/templates/module/angular/projects/my-project-name/package.json b/templates/module/angular/projects/my-project-name/package.json index 5634350e0e..430759b9f5 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": "~19.1.0", "@angular/core": "~19.1.0", - "@abp/ng.core": "~9.2.0-rc.1", - "@abp/ng.theme.shared": "~9.2.0-rc.1" + "@abp/ng.core": "~9.2.0-rc.4", + "@abp/ng.theme.shared": "~9.2.0-rc.4" }, "dependencies": { "tslib": "^2.1.0" diff --git a/templates/module/angular/projects/my-project-name/src/lib/components/my-project-name.component.ts b/templates/module/angular/projects/my-project-name/src/lib/components/my-project-name.component.ts index 21628304ac..3482489623 100644 --- a/templates/module/angular/projects/my-project-name/src/lib/components/my-project-name.component.ts +++ b/templates/module/angular/projects/my-project-name/src/lib/components/my-project-name.component.ts @@ -2,7 +2,6 @@ import { Component, inject, OnInit } from '@angular/core'; import { MyProjectNameService } from '../services/my-project-name.service'; @Component({ - standalone: false, selector: 'lib-my-project-name', template: `

my-project-name works!

`, styles: [], diff --git a/templates/module/angular/projects/my-project-name/src/lib/my-project-name.module.ts b/templates/module/angular/projects/my-project-name/src/lib/my-project-name.module.ts deleted file mode 100644 index 7e92915f4e..0000000000 --- a/templates/module/angular/projects/my-project-name/src/lib/my-project-name.module.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { NgModule, NgModuleFactory, ModuleWithProviders } from '@angular/core'; -import { CoreModule, LazyModuleFactory } from '@abp/ng.core'; -import { ThemeSharedModule } from '@abp/ng.theme.shared'; -import { MyProjectNameComponent } from './components/my-project-name.component'; -import { MyProjectNameRoutingModule } from './my-project-name-routing.module'; - -@NgModule({ - declarations: [MyProjectNameComponent], - imports: [CoreModule, ThemeSharedModule, MyProjectNameRoutingModule], - exports: [MyProjectNameComponent], -}) -export class MyProjectNameModule { - static forChild(): ModuleWithProviders { - return { - ngModule: MyProjectNameModule, - providers: [], - }; - } - - static forLazy(): NgModuleFactory { - return new LazyModuleFactory(MyProjectNameModule.forChild()); - } -} diff --git a/templates/module/angular/projects/my-project-name/src/lib/my-project-name-routing.module.ts b/templates/module/angular/projects/my-project-name/src/lib/my-project-name.routes.ts similarity index 56% rename from templates/module/angular/projects/my-project-name/src/lib/my-project-name-routing.module.ts rename to templates/module/angular/projects/my-project-name/src/lib/my-project-name.routes.ts index f676a219d9..ae9f1dfcec 100644 --- a/templates/module/angular/projects/my-project-name/src/lib/my-project-name-routing.module.ts +++ b/templates/module/angular/projects/my-project-name/src/lib/my-project-name.routes.ts @@ -1,9 +1,8 @@ -import { NgModule } from '@angular/core'; import { RouterOutletComponent } from '@abp/ng.core'; -import { Routes, RouterModule } from '@angular/router'; +import { Routes } from '@angular/router'; import { MyProjectNameComponent } from './components/my-project-name.component'; -const routes: Routes = [ +export const myProjectNameRoutes: Routes = [ { path: '', pathMatch: 'full', @@ -16,9 +15,3 @@ const routes: Routes = [ ], }, ]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule], -}) -export class MyProjectNameRoutingModule {} diff --git a/templates/module/angular/projects/my-project-name/src/public-api.ts b/templates/module/angular/projects/my-project-name/src/public-api.ts index 3bb54f6a9a..b445f589e0 100644 --- a/templates/module/angular/projects/my-project-name/src/public-api.ts +++ b/templates/module/angular/projects/my-project-name/src/public-api.ts @@ -4,4 +4,4 @@ export * from './lib/components/my-project-name.component'; export * from './lib/services/my-project-name.service'; -export * from './lib/my-project-name.module'; +export * from './lib/my-project-name.routes'; 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 7efc0aae71..f48c02d1b4 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 @@ -11,10 +11,10 @@ - - - - + + + + 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 f1868f1166..04dded9ca9 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } 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 3fe2b0415b..05e6cbac0b 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 589c0fced6..dc15b0086f 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,12 +8,12 @@ - - + + - + 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 d05d66c666..c8096f7080 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 ca64a417cd..3a541204b7 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.2.0-rc.1", - "@abp/aspnetcore.components.server.basictheme": "~9.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4", + "@abp/aspnetcore.components.server.basictheme": "~9.2.0-rc.4" } } 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 8db094e467..b9dffe7646 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 @@ -11,12 +11,12 @@ - - + + - - - + + + 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 666658da33..f2a0614cc0 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 @@ -11,9 +11,9 @@ - - - + + + 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 ece4546430..367ececa5e 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } 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 bc22e1a5f6..e2deed8b1f 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 @@ -11,9 +11,9 @@ - - - + + + 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 ece4546430..367ececa5e 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.2.0-rc.1" + "@abp/aspnetcore.mvc.ui.theme.basic": "~9.2.0-rc.4" } } 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 20c07d94f8..557b0e24be 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 b8791a1f3f..6d10c6e6fd 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 7a93e9f941..6aff21d32c 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 98abac34f3..321143def3 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/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj index f63599ff8a..f29fb32a5a 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MyCompanyName.MyProjectName.MongoDB.Tests.csproj @@ -10,10 +10,10 @@ - - - - + + + + diff --git a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj index 4c004ee12a..9addb70011 100644 --- a/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj +++ b/templates/module/aspnet-core/test/MyCompanyName.MyProjectName.TestBase/MyCompanyName.MyProjectName.TestBase.csproj @@ -10,15 +10,15 @@ - - + + all runtime; build; native; contentfiles; analyzers - - - - + + + + diff --git a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj index 3f3a1535bb..b40aa0ffb2 100644 --- a/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj +++ b/templates/wpf/src/MyCompanyName.MyProjectName/MyCompanyName.MyProjectName.csproj @@ -14,11 +14,11 @@ - - - - - + + + + +