Browse Source

Merge branch 'dev' into pr/19919

pull/19919/head
enisn 2 years ago
parent
commit
fbd081203a
  1. 20
      .github/workflows/auto-pr.yml
  2. 14
      Directory.Packages.props
  3. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json
  4. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json
  5. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json
  6. 2
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  7. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json
  8. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json
  9. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json
  10. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json
  11. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json
  12. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
  13. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json
  14. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json
  15. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json
  16. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json
  17. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json
  18. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json
  19. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json
  20. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json
  21. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json
  22. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json
  23. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
  24. 4
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json
  25. 37
      docs/en/API/API-Versioning.md
  26. 11
      docs/en/API/Application-Configuration.md
  27. BIN
      docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/adding-incorrect-data.png
  28. BIN
      docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/error.png
  29. BIN
      docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/validation.png
  30. BIN
      docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/automapper.png
  31. BIN
      docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/swagger1.png
  32. BIN
      docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/swagger2.png
  33. 134
      docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/post.md
  34. 340
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md
  35. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/cover-image.png
  36. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/demo.gif
  37. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis-steps.png
  38. BIN
      docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis.png
  39. 61
      docs/en/Migration-Guides/Abp-8_2.md
  40. 1
      docs/en/Migration-Guides/Index.md
  41. 2
      docs/en/Modules/Cms-Kit/Index.md
  42. 8
      docs/en/Samples/Index.md
  43. 59
      docs/en/UI/Angular/Title-Strategy-Service.md
  44. 4
      docs/en/docs-nav.json
  45. 37
      docs/zh-Hans/API/API-Versioning.md
  46. 17
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs
  47. 6
      framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/Extensions/DependencyInjection/AbpApiVersioningExtensions.cs
  48. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
  49. 7
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs
  50. 7
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs
  51. 14
      framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor
  52. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor
  53. 1
      framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj
  54. 11
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs
  55. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStyleStep.cs
  56. 23
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs
  57. 21
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  58. 8
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs
  59. 8
      framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs
  60. 19
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/AppEntityWithNavigations.cs
  61. 101
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs
  62. 2
      latest-versions.json
  63. 6
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json
  64. 8003
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css
  65. 2194
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css
  66. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf
  67. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2
  68. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf
  69. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2
  70. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf
  71. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2
  72. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.ttf
  73. BIN
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.woff2
  74. 56
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css
  75. 823
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js
  76. 411
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js
  77. 46
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js
  78. 694
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js
  79. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map
  80. 2
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js
  81. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map
  82. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.css.map
  83. 7
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.css
  84. 8
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.js
  85. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker-en-CA.min.js
  86. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-DZ.min.js
  87. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-tn.min.js
  88. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js
  89. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js
  90. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js
  91. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bm.min.js
  92. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bn.min.js
  93. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.br.min.js
  94. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js
  95. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js
  96. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js
  97. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js
  98. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js
  99. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js
  100. 1
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js

20
.github/workflows/auto-pr.yml

@ -1,13 +1,13 @@
name: Merge branch dev with prerel-8.2 name: Merge branch dev with rel-8.2
on: on:
push: push:
branches: branches:
- prerel-8.2 - rel-8.2
permissions: permissions:
contents: read contents: read
jobs: jobs:
merge-dev-with-prerel-8-2: merge-dev-with-rel-8-2:
permissions: permissions:
contents: write # for peter-evans/create-pull-request to create branch contents: write # for peter-evans/create-pull-request to create branch
pull-requests: write # for peter-evans/create-pull-request to create a PR pull-requests: write # for peter-evans/create-pull-request to create a PR
@ -18,19 +18,19 @@ jobs:
ref: dev ref: dev
- name: Reset promotion branch - name: Reset promotion branch
run: | run: |
git fetch origin prerel-8.2:prerel-8.2 git fetch origin rel-8.2:rel-8.2
git reset --hard prerel-8.2 git reset --hard rel-8.2
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v3 uses: peter-evans/create-pull-request@v3
with: with:
branch: auto-merge/prerel-8-2/${{github.run_number}} branch: auto-merge/rel-8-2/${{github.run_number}}
title: Merge branch dev with prerel-8.2 title: Merge branch dev with rel-8.2
body: This PR generated automatically to merge dev with prerel-8.2. Please review the changed files before merging to prevent any errors that may occur. body: This PR generated automatically to merge dev with rel-8.2. Please review the changed files before merging to prevent any errors that may occur.
reviewers: maliming reviewers: maliming
token: ${{ github.token }} token: ${{ github.token }}
- name: Merge Pull Request - name: Merge Pull Request
env: env:
GH_TOKEN: ${{ secrets.BOT_SECRET }} GH_TOKEN: ${{ secrets.BOT_SECRET }}
run: | run: |
gh pr review auto-merge/prerel-8-2/${{github.run_number}} --approve gh pr review auto-merge/rel-8-2/${{github.run_number}} --approve
gh pr merge auto-merge/prerel-8-2/${{github.run_number}} --merge --auto --delete-branch gh pr merge auto-merge/rel-8-2/${{github.run_number}} --merge --auto --delete-branch

14
Directory.Packages.props

@ -11,15 +11,16 @@
<PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" /> <PackageVersion Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageVersion Include="Autofac.Extras.DynamicProxy" Version="7.1.0" /> <PackageVersion Include="Autofac.Extras.DynamicProxy" Version="7.1.0" />
<PackageVersion Include="AutoMapper" Version="13.0.1" /> <PackageVersion Include="AutoMapper" Version="13.0.1" />
<PackageVersion Include="Asp.Versioning.Mvc" Version="7.1.0" /> <PackageVersion Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageVersion Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageVersion Include="AWSSDK.S3" Version="3.7.300.2" /> <PackageVersion Include="AWSSDK.S3" Version="3.7.300.2" />
<PackageVersion Include="AWSSDK.SecurityToken" Version="3.7.300.2" /> <PackageVersion Include="AWSSDK.SecurityToken" Version="3.7.300.2" />
<PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.17.0" /> <PackageVersion Include="Azure.Messaging.ServiceBus" Version="7.17.0" />
<PackageVersion Include="Azure.Storage.Blobs" Version="12.19.1" /> <PackageVersion Include="Azure.Storage.Blobs" Version="12.19.1" />
<PackageVersion Include="Blazorise" Version="1.5.0" /> <PackageVersion Include="Blazorise" Version="1.5.2" />
<PackageVersion Include="Blazorise.Components" Version="1.5.0" /> <PackageVersion Include="Blazorise.Components" Version="1.5.2" />
<PackageVersion Include="Blazorise.DataGrid" Version="1.5.0" /> <PackageVersion Include="Blazorise.DataGrid" Version="1.5.2" />
<PackageVersion Include="Blazorise.Snackbar" Version="1.5.0" /> <PackageVersion Include="Blazorise.Snackbar" Version="1.5.2" />
<PackageVersion Include="Castle.Core" Version="5.1.1" /> <PackageVersion Include="Castle.Core" Version="5.1.1" />
<PackageVersion Include="Castle.Core.AsyncInterceptor" Version="2.1.0" /> <PackageVersion Include="Castle.Core.AsyncInterceptor" Version="2.1.0" />
<PackageVersion Include="CommonMark.NET" Version="0.15.1" /> <PackageVersion Include="CommonMark.NET" Version="0.15.1" />
@ -60,7 +61,6 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.4" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" /> <PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
@ -88,7 +88,7 @@
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /> <PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" /> <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="8.0.0" /> <PackageVersion Include="Microsoft.Extensions.FileProviders.Composite" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.0" /> <PackageVersion Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.4" />
<PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="8.0.0" /> <PackageVersion Include="Microsoft.Extensions.FileProviders.Physical" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="8.0.0" /> <PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json

@ -816,6 +816,7 @@
"ErrorExceptionMessage": "حدث خطأ أثناء معالجة طلبك", "ErrorExceptionMessage": "حدث خطأ أثناء معالجة طلبك",
"WatchTakeCodeGeneration": "شاهد فيديو \"استكشاف إمكانات إنشاء الأكواد البرمجية: ABP Suite\"!", "WatchTakeCodeGeneration": "شاهد فيديو \"استكشاف إمكانات إنشاء الأكواد البرمجية: ABP Suite\"!",
"ExtendNow": "تمديد / تجديد", "ExtendNow": "تمديد / تجديد",
"RegisterDemo": "يسجل" "RegisterDemo": "يسجل",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">إذا كنت ترغب في اختبار ABP Studio قبل أي شخص آخر، يمكنك أن تصبح أحد مختبري النسخة التجريبية</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json

@ -431,6 +431,7 @@
"ErrorExceptionMessage": "Při zpracování vašeho požadavku nastala chyba", "ErrorExceptionMessage": "Při zpracování vašeho požadavku nastala chyba",
"WatchTakeCodeGeneration": "Podívejte se na video „Prozkoumejte potenciál generování kódu: ABP Suite“!", "WatchTakeCodeGeneration": "Podívejte se na video „Prozkoumejte potenciál generování kódu: ABP Suite“!",
"ExtendNow": "Prodloužit / Obnovit", "ExtendNow": "Prodloužit / Obnovit",
"RegisterDemo": "Registrovat" "RegisterDemo": "Registrovat",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Pokud chcete ABP Studio otestovat dříve než kdokoli jiný, staňte se BETA testerem</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/de.json

@ -411,6 +411,7 @@
"SendUsEmail": "Senden Sie uns eine E-Mail", "SendUsEmail": "Senden Sie uns eine E-Mail",
"ErrorExceptionMessage": "Während Ihrer Anfrage ist ein Fehler aufgetreten", "ErrorExceptionMessage": "Während Ihrer Anfrage ist ein Fehler aufgetreten",
"WatchTakeCodeGeneration": "Sehen Sie sich das Video „Entdecken Sie das Potenzial der Codegenerierung: ABP Suite“ an!", "WatchTakeCodeGeneration": "Sehen Sie sich das Video „Entdecken Sie das Potenzial der Codegenerierung: ABP Suite“ an!",
"ExtendNow": "Verlängern / Erneuern" "ExtendNow": "Verlängern / Erneuern",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Wenn Sie ABP Studio vor allen anderen testen möchten, werden Sie BETA-Tester</span>"
} }
} }

2
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -916,7 +916,7 @@
"AbpStudio_Description": "ABP Studio is still under development. You can fill out the form below to be one of the first users.", "AbpStudio_Description": "ABP Studio is still under development. You can fill out the form below to be one of the first users.",
"AbpStudio_Description1": "ABP Studio is a <span class=\"text-highlight-white\">cross-platform desktop application</span> for ABP developers.", "AbpStudio_Description1": "ABP Studio is a <span class=\"text-highlight-white\">cross-platform desktop application</span> for ABP developers.",
"AbpStudio_Description2": "It is <span class=\"text-highlight-white\">well integrated</span> to the ABP Framework and aims to provide a comfortable development environment for you by <span class=\"text-highlight-white\">automating things, providing insights</span> about your solution, making <span class=\"text-highlight-white\">develop, run</span> and <span class=\"text-highlight-white\">deploy</span> your solutions much easier.", "AbpStudio_Description2": "It is <span class=\"text-highlight-white\">well integrated</span> to the ABP Framework and aims to provide a comfortable development environment for you by <span class=\"text-highlight-white\">automating things, providing insights</span> about your solution, making <span class=\"text-highlight-white\">develop, run</span> and <span class=\"text-highlight-white\">deploy</span> your solutions much easier.",
"AbpStudio_ComingSoon": "Coming Soon <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Planned beta release date: Q4 of 2023.</span>", "AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">If you want to test ABP Studio before anyone else, become a BETA tester</span>",
"AbpStudio_PlannedPreviewDate": "Planned preview release date: Q4 of 2023.", "AbpStudio_PlannedPreviewDate": "Planned preview release date: Q4 of 2023.",
"BetaRequest": "Beta Request", "BetaRequest": "Beta Request",
"CreateNewSolutions": "Create New Solutions", "CreateNewSolutions": "Create New Solutions",

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json

@ -411,6 +411,7 @@
"SendUsEmail": "Envíanos un correo electrónico", "SendUsEmail": "Envíanos un correo electrónico",
"ErrorExceptionMessage": "Se produjo un error al procesar su solicitud.", "ErrorExceptionMessage": "Se produjo un error al procesar su solicitud.",
"WatchTakeCodeGeneration": "¡Mire el vídeo \"Explore el potencial de la generación de código: ABP Suite\"!", "WatchTakeCodeGeneration": "¡Mire el vídeo \"Explore el potencial de la generación de código: ABP Suite\"!",
"ExtendNow": "Ampliar / Renovar" "ExtendNow": "Ampliar / Renovar",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Si quieres probar ABP Studio antes que nadie, conviértete en tester BETA</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json

@ -852,6 +852,7 @@
"ErrorExceptionMessage": "Virhe pyynnön käsittelyn yhteydessä", "ErrorExceptionMessage": "Virhe pyynnön käsittelyn yhteydessä",
"WatchTakeCodeGeneration": "Katso \"Tutki koodin luomisen potentiaalia: ABP Suite\" -video!", "WatchTakeCodeGeneration": "Katso \"Tutki koodin luomisen potentiaalia: ABP Suite\" -video!",
"ExtendNow": "Laajenna / Uusi", "ExtendNow": "Laajenna / Uusi",
"RegisterDemo": "Rekisteröidy" "RegisterDemo": "Rekisteröidy",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Jos haluat testata ABP Studiota ennen muita, ryhdy BETA-testaajaksi</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json

@ -431,6 +431,7 @@
"ErrorExceptionMessage": "Une erreur s'est produite lors du traitement de votre demande", "ErrorExceptionMessage": "Une erreur s'est produite lors du traitement de votre demande",
"WatchTakeCodeGeneration": "Regardez la vidéo « Explorez le potentiel de la génération de code : ABP Suite » !", "WatchTakeCodeGeneration": "Regardez la vidéo « Explorez le potentiel de la génération de code : ABP Suite » !",
"ExtendNow": "Prolonger / Renouveler", "ExtendNow": "Prolonger / Renouveler",
"RegisterDemo": "Registre" "RegisterDemo": "Registre",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Si vous souhaitez tester ABP Studio avant tout le monde, devenez BETA testeur</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json

@ -430,6 +430,7 @@
"ErrorExceptionMessage": "आपका अनुरोध संसाधित करते समय एक त्रुटि पाई गई", "ErrorExceptionMessage": "आपका अनुरोध संसाधित करते समय एक त्रुटि पाई गई",
"WatchTakeCodeGeneration": "\"कोड जनरेशन की क्षमता का अन्वेषण करें: एबीपी सुइट\" वीडियो देखें!", "WatchTakeCodeGeneration": "\"कोड जनरेशन की क्षमता का अन्वेषण करें: एबीपी सुइट\" वीडियो देखें!",
"ExtendNow": "विस्तार/नवीनीकरण", "ExtendNow": "विस्तार/नवीनीकरण",
"RegisterDemo": "पंजीकरण करवाना" "RegisterDemo": "पंजीकरण करवाना",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">यदि आप किसी और से पहले एबीपी स्टूडियो का परीक्षण करना चाहते हैं, तो बीटा परीक्षक बनें</span>"
} }
} }

4
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hr.json

@ -915,7 +915,6 @@
"AbpStudio_Description": "ABP Studio je još uvijek u razvoju. Možete ispuniti obrazac ispod i biti jedan od prvih korisnika.", "AbpStudio_Description": "ABP Studio je još uvijek u razvoju. Možete ispuniti obrazac ispod i biti jedan od prvih korisnika.",
"AbpStudio_Description1": "ABP Studio je <span class=\"text-highlight-white\">stolna aplikacija za više platformi</span> za ABP programere.", "AbpStudio_Description1": "ABP Studio je <span class=\"text-highlight-white\">stolna aplikacija za više platformi</span> za ABP programere.",
"AbpStudio_Description2": "<span class=\"text-highlight-white\">Dobro je integriran</span> u ABP Framework i ima za cilj pružiti vam ugodno razvojno okruženje <span class=\"text-highlight-white\">automatiziranjem stvari, pružanjem uvida</span> u vaše rješenje, čineći <span class=\"text-highlight-white\">razvoj, pokretanje</span> i <span class=\"text-highlight-white\">implementaciju</span> vaših rješenja puno lakšim.", "AbpStudio_Description2": "<span class=\"text-highlight-white\">Dobro je integriran</span> u ABP Framework i ima za cilj pružiti vam ugodno razvojno okruženje <span class=\"text-highlight-white\">automatiziranjem stvari, pružanjem uvida</span> u vaše rješenje, čineći <span class=\"text-highlight-white\">razvoj, pokretanje</span> i <span class=\"text-highlight-white\">implementaciju</span> vaših rješenja puno lakšim.",
"AbpStudio_ComingSoon": "Uskoro. <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Planirani datum izdavanja beta verzije: 4. tromjesečje 2023.</span>",
"AbpStudio_PlannedPreviewDate": "Planirani datum izdavanja pregleda: 4. kvartal 2023.", "AbpStudio_PlannedPreviewDate": "Planirani datum izdavanja pregleda: 4. kvartal 2023.",
"BetaRequest": "Zahtjev za beta verziju", "BetaRequest": "Zahtjev za beta verziju",
"CreateNewSolutions": "Stvorite nova rješenja", "CreateNewSolutions": "Stvorite nova rješenja",
@ -1107,6 +1106,7 @@
"SendUsEmail": "Pošaljite nam e-mail", "SendUsEmail": "Pošaljite nam e-mail",
"ErrorExceptionMessage": "Pojavila se greška prilikom obrade Vašeg zahtjeva", "ErrorExceptionMessage": "Pojavila se greška prilikom obrade Vašeg zahtjeva",
"WatchTakeCodeGeneration": "Pogledajte video \"Istražite potencijal generiranja koda: ABP Suite\"!", "WatchTakeCodeGeneration": "Pogledajte video \"Istražite potencijal generiranja koda: ABP Suite\"!",
"ExtendNow": "Produži / obnovi" "ExtendNow": "Produži / obnovi",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Ako želite testirati ABP Studio prije svih ostalih, postanite BETA tester</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json

@ -777,6 +777,7 @@
"SendUsEmail": "Küldjön nekünk e-mailt", "SendUsEmail": "Küldjön nekünk e-mailt",
"ErrorExceptionMessage": "Hiba történt a kérése feldolgozása során", "ErrorExceptionMessage": "Hiba történt a kérése feldolgozása során",
"WatchTakeCodeGeneration": "Nézze meg a \"Fedezze fel a kódgenerálás lehetőségét: ABP Suite\" videót!", "WatchTakeCodeGeneration": "Nézze meg a \"Fedezze fel a kódgenerálás lehetőségét: ABP Suite\" videót!",
"ExtendNow": "Bővítés / Megújítás" "ExtendNow": "Bővítés / Megújítás",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Ha bárki más előtt szeretné tesztelni az ABP Studio-t, legyen BÉTA tesztelő</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/is.json

@ -408,6 +408,7 @@
"SendUsEmail": "Sendu okkur tölvupóst", "SendUsEmail": "Sendu okkur tölvupóst",
"ErrorExceptionMessage": "Villa kom upp við úrvinnslu beiðni þinnar", "ErrorExceptionMessage": "Villa kom upp við úrvinnslu beiðni þinnar",
"WatchTakeCodeGeneration": "Horfðu á \"Kannaðu möguleika kóðaframleiðslu: ABP Suite\" myndbandið!", "WatchTakeCodeGeneration": "Horfðu á \"Kannaðu möguleika kóðaframleiðslu: ABP Suite\" myndbandið!",
"ExtendNow": "Framlengja / endurnýja" "ExtendNow": "Framlengja / endurnýja",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Ef þú vilt prófa ABP Studio á undan öllum öðrum skaltu gerast BETA prófari</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json

@ -430,6 +430,7 @@
"ErrorExceptionMessage": "Si è verificato un errore durante l'elaborazione della richiesta", "ErrorExceptionMessage": "Si è verificato un errore durante l'elaborazione della richiesta",
"WatchTakeCodeGeneration": "Guarda il video \"Esplora il potenziale della generazione di codice: ABP Suite\"!", "WatchTakeCodeGeneration": "Guarda il video \"Esplora il potenziale della generazione di codice: ABP Suite\"!",
"ExtendNow": "Estendi/Rinnova", "ExtendNow": "Estendi/Rinnova",
"RegisterDemo": "Registrati" "RegisterDemo": "Registrati",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Se vuoi provare ABP Studio prima di chiunque altro, diventa un BETA tester</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/nl.json

@ -408,6 +408,7 @@
"SendUsEmail": "Stuur ons een e-mail", "SendUsEmail": "Stuur ons een e-mail",
"ErrorExceptionMessage": "Er is een fout opgetreden bij het verwerken van uw verzoek", "ErrorExceptionMessage": "Er is een fout opgetreden bij het verwerken van uw verzoek",
"WatchTakeCodeGeneration": "Bekijk de video 'Ontdek het potentieel van codegeneratie: ABP Suite'!", "WatchTakeCodeGeneration": "Bekijk de video 'Ontdek het potentieel van codegeneratie: ABP Suite'!",
"ExtendNow": "Verlengen / Verlengen" "ExtendNow": "Verlengen / Verlengen",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Als u ABP Studio als eerste wilt testen, wordt dan BETA-tester</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pl-PL.json

@ -409,6 +409,7 @@
"ErrorExceptionMessage": "Podczas przetwarzania żądania wystąpił błąd", "ErrorExceptionMessage": "Podczas przetwarzania żądania wystąpił błąd",
"WatchTakeCodeGeneration": "Obejrzyj film „Odkryj potencjał generowania kodu: pakiet ABP”!", "WatchTakeCodeGeneration": "Obejrzyj film „Odkryj potencjał generowania kodu: pakiet ABP”!",
"ExtendNow": "Przedłuż/Odnów", "ExtendNow": "Przedłuż/Odnów",
"RegisterDemo": "Rejestr" "RegisterDemo": "Rejestr",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Jeśli chcesz przetestować ABP Studio zanim ktokolwiek inny, zostań testerem BETA</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json

@ -431,6 +431,7 @@
"SendUsEmail": "Envie-nos um e-mail", "SendUsEmail": "Envie-nos um e-mail",
"ErrorExceptionMessage": "Um erro ocorreu durante o processamento do seu pedido", "ErrorExceptionMessage": "Um erro ocorreu durante o processamento do seu pedido",
"WatchTakeCodeGeneration": "Assista ao vídeo \"Explore o potencial de geração de código: ABP Suite\"!", "WatchTakeCodeGeneration": "Assista ao vídeo \"Explore o potencial de geração de código: ABP Suite\"!",
"ExtendNow": "Estender/Renovar" "ExtendNow": "Estender/Renovar",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Se você quiser testar o ABP Studio antes de todo mundo, torne-se um testador BETA</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ro-RO.json

@ -408,6 +408,7 @@
"SendUsEmail": "Trimite-ne e-mail", "SendUsEmail": "Trimite-ne e-mail",
"ErrorExceptionMessage": "A apărut o eroare în timpul procesării cererii dumneavoastră", "ErrorExceptionMessage": "A apărut o eroare în timpul procesării cererii dumneavoastră",
"WatchTakeCodeGeneration": "Urmărește videoclipul „Explorați potențialul generării codului: ABP Suite”!", "WatchTakeCodeGeneration": "Urmărește videoclipul „Explorați potențialul generării codului: ABP Suite”!",
"ExtendNow": "Extinde/Reînnoiește" "ExtendNow": "Extinde/Reînnoiește",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Dacă doriți să testați ABP Studio înaintea oricui, deveniți un tester BETA</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json

@ -427,6 +427,7 @@
"SendUsEmail": "Pošlite nám e-mail", "SendUsEmail": "Pošlite nám e-mail",
"ErrorExceptionMessage": "Nastala chyba pri spracovaní vašej žiadosti", "ErrorExceptionMessage": "Nastala chyba pri spracovaní vašej žiadosti",
"WatchTakeCodeGeneration": "Pozrite si video „Preskúmajte potenciál generovania kódu: ABP Suite“!", "WatchTakeCodeGeneration": "Pozrite si video „Preskúmajte potenciál generovania kódu: ABP Suite“!",
"ExtendNow": "Predĺžiť / obnoviť" "ExtendNow": "Predĺžiť / obnoviť",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Ak chcete otestovať ABP Studio skôr ako ktokoľvek iný, staňte sa BETA testerom</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sl.json

@ -409,6 +409,7 @@
"ErrorExceptionMessage": "Pri obdelavi vaše zahteve je prišlo do napake", "ErrorExceptionMessage": "Pri obdelavi vaše zahteve je prišlo do napake",
"WatchTakeCodeGeneration": "Oglejte si video »Raziščite potencial generiranja kode: zbirka ABP«!", "WatchTakeCodeGeneration": "Oglejte si video »Raziščite potencial generiranja kode: zbirka ABP«!",
"ExtendNow": "Podaljšaj / obnovi", "ExtendNow": "Podaljšaj / obnovi",
"RegisterDemo": "Registrirajte se" "RegisterDemo": "Registrirajte se",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Če želite preizkusiti ABP Studio pred vsemi drugimi, postanite BETA tester</span>"
} }
} }

4
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/tr.json

@ -1058,7 +1058,6 @@
"AbpStudio_Description": "ABP Studio hala geliştirme aşamasında. İlk kullanıcılardan biri olmak için aşağıdaki formu doldurabilirsiniz.", "AbpStudio_Description": "ABP Studio hala geliştirme aşamasında. İlk kullanıcılardan biri olmak için aşağıdaki formu doldurabilirsiniz.",
"AbpStudio_Description1": "ABP Studio, ABP geliştiricileri için <span class=\"text-highlight-white\">çok platformlu masaüstü uygulamasıdır</span>.", "AbpStudio_Description1": "ABP Studio, ABP geliştiricileri için <span class=\"text-highlight-white\">çok platformlu masaüstü uygulamasıdır</span>.",
"AbpStudio_Description2": "ABP Studio, ABP Framework'e <span class=\"text-highlight-white\">iyi entegre edilmiştir</span> ve sizin için işleri <span class=\"text-highlight-white\">otomatikleştirerek, projeniz hakkında bilgi sağlayarak</span>, projelerinizi <span class=\"text-highlight-white\">geliştirmeyi, çalıştırmayı</span> ve <span class=\"text-highlight-white\">dağıtımını</span> çok daha kolay hale getirmeyi amaçlamaktadır.", "AbpStudio_Description2": "ABP Studio, ABP Framework'e <span class=\"text-highlight-white\">iyi entegre edilmiştir</span> ve sizin için işleri <span class=\"text-highlight-white\">otomatikleştirerek, projeniz hakkında bilgi sağlayarak</span>, projelerinizi <span class=\"text-highlight-white\">geliştirmeyi, çalıştırmayı</span> ve <span class=\"text-highlight-white\">dağıtımını</span> çok daha kolay hale getirmeyi amaçlamaktadır.",
"AbpStudio_ComingSoon": "Yakında <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Planlanan beta sürüm tarihi: 2023'ün 4. çeyreği.</span>",
"AbpStudio_PlannedPreviewDate": "Planlanan beta sürüm tarihi: 2023'ün 4. çeyreği.", "AbpStudio_PlannedPreviewDate": "Planlanan beta sürüm tarihi: 2023'ün 4. çeyreği.",
"BetaRequest": "Beta Talebi", "BetaRequest": "Beta Talebi",
"CreateNewSolutions": "Yeni Projeler Oluştur", "CreateNewSolutions": "Yeni Projeler Oluştur",
@ -1140,6 +1139,7 @@
"RemoveBasket": "Sepetten kaldır", "RemoveBasket": "Sepetten kaldır",
"TrainingPack": "Eğitim paketi", "TrainingPack": "Eğitim paketi",
"TrainingPackDiscount": "Eğitim paketi indirimi", "TrainingPackDiscount": "Eğitim paketi indirimi",
"LinkExpiredMessage": "Ödeme bağlantısının süresi doldu! Bağlantıyı güncellemek için <a href='mailto:sales@volosoft.com'>sales@volosoft.com</a> adresinden bizimle iletişime geçin veya iletişim sayfasına gitmek için <a href='https://commercial.abp.io/contact'>buraya</a> tıklayın." "LinkExpiredMessage": "Ödeme bağlantısının süresi doldu! Bağlantıyı güncellemek için <a href='mailto:sales@volosoft.com'>sales@volosoft.com</a> adresinden bizimle iletişime geçin veya iletişim sayfasına gitmek için <a href='https://commercial.abp.io/contact'>buraya</a> tıklayın.",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">ABP Studio'yu herkesten önce test etmek istiyorsanız BETA test kullanıcısı olun</span>"
} }
} }

3
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/vi.json

@ -408,6 +408,7 @@
"SendUsEmail": "Gửi email cho chúng tôi", "SendUsEmail": "Gửi email cho chúng tôi",
"ErrorExceptionMessage": "Đã xảy ra lỗi trong khi xử lý yêu cầu của bạn", "ErrorExceptionMessage": "Đã xảy ra lỗi trong khi xử lý yêu cầu của bạn",
"WatchTakeCodeGeneration": "Xem video \"Khám phá tiềm năng tạo mã: ABP Suite\"!", "WatchTakeCodeGeneration": "Xem video \"Khám phá tiềm năng tạo mã: ABP Suite\"!",
"ExtendNow": "Gia hạn/Gia hạn" "ExtendNow": "Gia hạn/Gia hạn",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">Nếu bạn muốn thử nghiệm ABP Studio trước bất kỳ ai khác, hãy trở thành người thử nghiệm BETA</span>"
} }
} }

4
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json

@ -915,7 +915,6 @@
"AbpStudio_Description": "ABP Studio 仍在开发中。您可以填写下面的表单,成为首批用户之一。", "AbpStudio_Description": "ABP Studio 仍在开发中。您可以填写下面的表单,成为首批用户之一。",
"AbpStudio_Description1": "ABP Studio 是专为 ABP 开发人员设计的<span class=\"text-highlight-white\">跨平台桌面应用程序</span>。", "AbpStudio_Description1": "ABP Studio 是专为 ABP 开发人员设计的<span class=\"text-highlight-white\">跨平台桌面应用程序</span>。",
"AbpStudio_Description2": "它<span class=\"text-highlight-white\">与 ABP 框架集成得很好</span>,旨在通过<span class=\"text-highlight-white\">自动化、提供有关解决方案的见解</span>,为您提供舒适的开发环境,使<span class=\"text-highlight-white\">开发、运行</span>和<span class=\"text-highlight-white\">部署</span>解决方案变得更加容易。", "AbpStudio_Description2": "它<span class=\"text-highlight-white\">与 ABP 框架集成得很好</span>,旨在通过<span class=\"text-highlight-white\">自动化、提供有关解决方案的见解</span>,为您提供舒适的开发环境,使<span class=\"text-highlight-white\">开发、运行</span>和<span class=\"text-highlight-white\">部署</span>解决方案变得更加容易。",
"AbpStudio_ComingSoon": "即将发布 <span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">计划测试版发布日期:</span>计划测试版发布日期:2023年第四季度。",
"AbpStudio_PlannedPreviewDate": "计划预览版发布日期:2023 年第四季度。", "AbpStudio_PlannedPreviewDate": "计划预览版发布日期:2023 年第四季度。",
"BetaRequest": "测试版请求", "BetaRequest": "测试版请求",
"CreateNewSolutions": "创建新的解决方案", "CreateNewSolutions": "创建新的解决方案",
@ -1110,6 +1109,7 @@
"ErrorExceptionMessage": "处理您的请求时发生错误", "ErrorExceptionMessage": "处理您的请求时发生错误",
"WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!", "WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!",
"PreBuiltApplicationModulesTitle": "预构建应用程序 <span class=\"gradient-commercial\">模块</span>", "PreBuiltApplicationModulesTitle": "预构建应用程序 <span class=\"gradient-commercial\">模块</span>",
"RegisterDemo": "登记" "RegisterDemo": "登记",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">如果您想先于其他人测试 ABP Studio,请成为 BETA 测试员</span>"
} }
} }

4
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json

@ -897,7 +897,6 @@
"AbpStudio_Description": "ABP Studio 仍在開發中。您可以填寫下面的表单,成為第一批使用者之一。", "AbpStudio_Description": "ABP Studio 仍在開發中。您可以填寫下面的表单,成為第一批使用者之一。",
"AbpStudio_Description1": "ABP Studio 是一款針對 ABP 開發人員的<span class=\"text-highlight-white\">跨平台桌面應用程式</span>。", "AbpStudio_Description1": "ABP Studio 是一款針對 ABP 開發人員的<span class=\"text-highlight-white\">跨平台桌面應用程式</span>。",
"AbpStudio_Description2": "它與 ABP 框架<span class=\"text-highlight-white\">很好地集成</span>,旨在透過<span class=\"text-highlight-white\">自動化為您提供一個舒適的開發環境,提供有關您的解決方案的見解</span>,使<span class=\"text-highlight-white\">開發、運行</span>和<span class=\"text-highlight-white\">部署</span>您的解決方案變得更加容易。", "AbpStudio_Description2": "它與 ABP 框架<span class=\"text-highlight-white\">很好地集成</span>,旨在透過<span class=\"text-highlight-white\">自動化為您提供一個舒適的開發環境,提供有關您的解決方案的見解</span>,使<span class=\"text-highlight-white\">開發、運行</span>和<span class=\"text-highlight-white\">部署</span>您的解決方案變得更加容易。",
"AbpStudio_ComingSoon": "即將推出<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">計劃測試版發布日期:2023 年第四季。</span>",
"AbpStudio_PlannedPreviewDate": "計畫預覽版發布日期:2023 年第四季。", "AbpStudio_PlannedPreviewDate": "計畫預覽版發布日期:2023 年第四季。",
"BetaRequest": "測試版請求", "BetaRequest": "測試版請求",
"CreateNewSolutions": "建立新的解決方案", "CreateNewSolutions": "建立新的解決方案",
@ -1100,6 +1099,7 @@
"WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!", "WatchTakeCodeGeneration": "观看“探索代码生成的潜力:ABP Suite”视频!",
"ExtendNow": "延长 / 续订", "ExtendNow": "延长 / 续订",
"PreBuiltApplicationModulesTitle": "预构建应用程序 <span class=\"gradient-commercial\">模块</span>", "PreBuiltApplicationModulesTitle": "预构建应用程序 <span class=\"gradient-commercial\">模块</span>",
"RegisterDemo": "登记" "RegisterDemo": "登记",
"AbpStudio_ComingSoon": "<span class=\"opacity-50 ms-0 ms-md-3 d-block d-md-inline-block \">如果您想先于其他人测试 ABP Studio,请成为 BETA 测试员</span>"
} }
} }

37
docs/en/API/API-Versioning.md

@ -8,11 +8,10 @@ ABP Framework integrates the [ASPNET-API-Versioning](https://github.com/dotnet/a
```cs ```cs
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}); });
@ -239,11 +238,10 @@ public override void ConfigureServices(ServiceConfigurationContext context)
preActions.Configure(options); preActions.Configure(options);
}); });
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
@ -263,27 +261,22 @@ public override void ConfigureServices(ServiceConfigurationContext context)
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}).AddApiExplorer(options => {
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
}); });
context.Services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
});
context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
context.Services.AddAbpSwaggerGen( context.Services.AddAbpSwaggerGen(
@ -322,7 +315,7 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
app.UseAbpRequestLocalization(); app.UseAbpRequestLocalization();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI( app.UseAbpSwaggerUI(
options => options =>
{ {
var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>(); var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();

11
docs/en/API/Application-Configuration.md

@ -55,7 +55,16 @@ namespace Acme.BookStore.Web
} }
``` ```
Add your contributor instance to the `AbpApplicationConfigurationOptions`
```csharp
Configure<AbpApplicationConfigurationOptions>(options =>
{
options.Contributors.AddIfNotContains(new MyApplicationConfigurationContributor());
});
```
* `IApplicationConfigurationContributor` defines the `ContributeAsync` method to extend the **application-configuration** endpoint with the specified additional data. * `IApplicationConfigurationContributor` defines the `ContributeAsync` method to extend the **application-configuration** endpoint with the specified additional data.
* You can inject services and perform any logic needed to extend the endpoint as you wish. * You can inject services and perform any logic needed to extend the endpoint as you wish.
> Application configuration contributors are automatically discovered by the ABP Framework and executed as a part of the application configuration initialization process. > Application configuration contributors are executed as a part of the application configuration initialization process.

BIN
docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/adding-incorrect-data.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 61 KiB

BIN
docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/error.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/en/Community-Articles/2024-05-07-using-fluent-validation-with-abp/images/validation.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 48 KiB

BIN
docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/automapper.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

BIN
docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/swagger1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/images/swagger2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

134
docs/en/Community-Articles/2024-05-09-what-is-object-to-object-mapping/post.md

@ -0,0 +1,134 @@
# What is Object to Object Mapping?
Mapping the properties of one object to the properties of another object is called **Object to Object Mapping**. Most of the time, you don't want to show the data you store in your database to end users as it is. Instead, you only return users the information they need for that operation and reduce the output size.
For example, in database tables that contain relationships, we analyze the relationships and present meaningful data to users. Suppose we have a product and a category object, we keep a property called `categoryId` in the `Product` entity. However, it would be illogical to show the `categoryId ` property to users. Therefore, we can create a DTO (data transfer object) and show the **category name** to the end users, instead of the `categoryId` directly.
DTOs are used to transfer data of objects from one object to another one. We often need to map our entities to DTOs and DTOs to entities. For example, consider the code below:
````csharp
public virtual async Task<CustomerDto> CreateAsync(CustomerCreateDto input)
{
var customer = await _customerManager.CreateAsync(
input.BirthDay, input.MembershipDate, input.FirstName, input.LastName
);
CustomerDto customerDto = new CustomerDto
{
Id = customer.Id,
FirstName = input.FirstName,
LastName = input.LastName,
// ...other
};
return customerDto;
}
````
As can be seen here, it's repetitive and tedious to manually map an object to another similar object. Also, it violates the [DRY principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself), makes your code more complicated and reduces readability. Instead of manually mapping objects, you can use the [AutoMapper](https://automapper.org/) library to automatically map two objects' properties:
````csharp
public virtual async Task<CustomerDto> CreateAsync(CustomerCreateDto input)
{
var customer = await _customerManager.CreateAsync(
input.BirthDay, input.MembershipDate, input.FirstName, input.LastName
);
return ObjectMapper.Map<Customer, CustomerDto>(customer);
}
````
The **ObjectMapper.Map** method allows you to convert your `Customer` entity to `CustomerDto`. `IObjectMapper` interface is a service, that comes from the **AutoMapper** library, so let's learn more about **AutoMapper** in the next section.
# What is AutoMapper?
Automapper is a .NET library that automates object-to-object mapping. ABP provides abstractions for object-to-object mapping and has an integration package to use [AutoMapper](http://automapper.org/) as the object mapper.
Automapper is a library that transforms similar objects into each other. We can imagine Automapper as a machine that transforms an apple with a hat into an apple without a hat:
![AutoMapper](./images/automapper.png)
In this chapter, I will show you how to use the AutoMapper library in an ABP-based application. For this reason, I assume that you already have an ABP-based application created. If you have not yet created an ABP-based application, please follow the [Getting Started documentation](https://docs.abp.io/en/abp/latest/Getting-Started-Create-Solution?UI=MVC&DB=EF&Tiered=No).
Create a domain entity similar to this one:
````csharp
public class Customer : FullAuditedAggregateRoot<Guid>
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
public DateTime BirthDay { get; set; }
public DateTime MembershipDate { get; set; }
}
````
`Customer` entity contains some properties (such as `FirstName`, `LastName`, ... and other audited properties coming from the base class - `DeleterId`, `IsDeleted`, `CreationTime` etc. -). Typically, you would not want to show/return all of these properties to end users, at that point, you can create a DTO class and only define the properties that you want to return to the end users.
Let's create the `CustomerGetDto` class in the `*.Application.Contracts` project as follows:
````csharp
public class CustomerGetDto
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
public DateTime BirthDay { get; set; }
}
````
After creating our entity and output DTO classes, now in the application service implementation, we can return the `CustomerGetDto` class, as a result of listing the customers. For that reason, we can write a code as follows:
````csharp
public virtual async Task<PagedResultDto<CustomerGetDto>> GetListAsync(GetCustomersInput input)
{
var totalCount = await _customerRepository.GetCountAsync(input.FilterText, input.FirstName, input.LastName, input.BirthDayMin, input.BirthDayMax, input.MembershipDateMin, input.MembershipDateMax);
var items = await _customerRepository.GetListAsync(input.FilterText, input.FirstName, input.LastName, input.BirthDayMin, input.BirthDayMax, input.MembershipDateMin, input.MembershipDateMax, input.Sorting, input.MaxResultCount, input.SkipCount);
return new PagedResultDto<CustomerGetDto>
{
TotalCount = totalCount,
Items = ObjectMapper.Map<List<Customer>, List<CustomerGetDto>>(items)
};
}
````
In this code, we first get the total number of our customers and all customers according to the specified filters, then we map `List<Customer>` to `List<CustomerGetDto>` using the `ObjectMapper.Map` method from the **ApplicationService** base class. This way we have full control over which properties are returned to the end users.
After mapping the `Customer` entity to the `CustomerGetDto` class. Before running our application, we should define the mappings in the `*AutoMapperProfile` class in the `*.Application` project as follows:
````csharp
public class YourApplicationAutoMapperProfile : Profile
{
public YourApplicationAutoMapperProfile()
{
CreateMap<Customer, CustomerGetDto>();
}
}
````
Finally, we can run our application and navigate to the **/swagger** endpoint to try our endpoint. When we send a request, we should get the result as follows:
![Swagger](./images/swagger1.png)
## Advanced: Mapping Configurations
In some scenarios, you may want to make some customizations when mapping two objects. For example, let's assume that you want to create the `CustomerGetDto` class as follows:
````csharp
public class CustomerGetDto
{
public string? FullName { get; set; }
public int Age { get; set; }
}
````
AutoMapper can't map these properties automatically, because they do not exist in the source object, which is the `Customer` entity. Therefore, you need to specify the exception and update your `YourApplicationAutoMapperProfile` class as follows:
````csharp
CreateMap<Customer, CustomerGetDto>().ForMember(c=>c.FullName,opt=> opt.MapFrom(src => src.FirstName + " " + src.LastName))
.ForMember(c=>c.Age, opt=> opt.MapFrom(src=> DateTime.UtcNow.Year -src.BirthDay.Year));
````
This configuration concatenates and matches **FirstName** and **LastName** properties into the **FullName** property and subtracts **BirthDate** from today's year and assigns it to the customer's **Age**.
After these configurations, if you make a request to the relevant endpoint, the output will look like:
![Swagger](./images/swagger2.png)
For more information on object-to-object mapping with [ABP Framework](https://abp.io/), see the [documentation](https://docs.abp.io/en/abp/latest/Object-To-Object-Mapping).

340
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/POST.md

@ -0,0 +1,340 @@
# Sentiment Analysis Within ABP-Based Application
In this article, first I will briefly explain what sentiment analysis is and then show you how you can apply sentiment analysis in an ABP-Based application (or any kind of .NET application).
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.
## 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.
To understand it better, let's check the following figure and examine the comments:
![](sentiment-analysis.png)
* If you look at these comments, you will notice that comments have ratings and it's easy to understand the emotion or thoughts of the users who commented about the related product.
* But even if there was not any rating specified for the given comments we still can get the emotion of the users. Because, as you can see, the comments specified some obvious words that express emotions, for example, in the first comment, the user says **he/she liked the product**, **it's easy to use** and **its battery is good**, and therefore this is obviously a positive comment.
* On the other hand, if we look at the second comment, we will notice some negative statements such as **useless phone**, **cannot maintain any data connection** and the user suggests **do not buy this phone**. Actually, this is what sentiment analysis is all about, abstracting the emotion from a given input, it's comment in that case but it can be any kind of input or input-group.
## Demo: Spam Detection (Applying Sentiment Analysis)
> You can get the source code of the demo from [https://github.com/EngincanV/SentimentAnalysisDemo](https://github.com/EngincanV/SentimentAnalysisDemo).
In this demo application, we will create an [ABP-based application](https://docs.abp.io/en/abp/8.1/Startup-Templates/Application) and integrate the [ABP's CMS Kit Module's Comment Feature](https://docs.abp.io/en/abp/latest/Modules/Cms-Kit/Comments), which provides a comment system to add a comment to any kind of resource, such as blog posts or products.
By default, CMS Kit's Comment Feature does not provide spam detection and therefore in this sample application, we will add [spam detection](https://github.com/EngincanV/SentimentAnalysisDemo/blob/master/src/SentimentAnalysisDemo.Application/ML/SpamDetector.cs) while creating or updating a comment. Thus, whenever a comment is being added or updated, the spam detection service will validate the comment and reject it if it contains spam content otherwise it will make the other validations and save the comment:
![](sentiment-analysis-steps.png)
To get started, we will first create an application, and add the CMS Kit Module to the solution and then we will enable the Comment Feature of the CMS Kit Module, and finally, we will add the Comment Component to the homepage and add spam detection by extending the behavior. Let's start with creating the application!
### Creating an ABP-Based Application
You can use the following command to create a layered ABP solution (with MongoDB as the database option):
```bash
abp new SentimentAnalysisDemo -t app -d mongodb --version 8.1.1
```
### Installing the CMS Kit Module
After creating the project, we can add the CMS Kit module to our project. [ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides the `add-module` command to install a specific module to a solution.
You can use the following command to install the CMS Kit module into your application (run this command in the solution directory):
```bash
abp add-module Volo.CmsKit --skip-db-migrations
```
After this command is executed, all related CMS Kit packages will be added to the correct layers and then you can enable any CMS Kit feature you want.
### Enabling the Comment Feature
By default, CMS Kit features are disabled. Therefore, you need to enable the features you want, before starting to use it. You can either enable all of them or enable them one by one. In our demo application, we only need the **Comment Feature**, therefore we can only enable it.
To enable the Comment Feature, you can open the `SentimentAnalysisDemoGlobalFeatureConfigurator` class (under the `*.Domain.Shared` project) and update it as follows:
```csharp
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Threading;
namespace SentimentAnalysisDemo;
public static class SentimentAnalysisDemoGlobalFeatureConfigurator
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
GlobalFeatureManager.Instance.Modules.CmsKit(cmsKit =>
{
cmsKit.Comments.Enable();
});
});
}
}
```
After enabling the feature, now we can make the final configurations and directly use it in our application.
### Configurations for Comment Feature
Open the `SentimentAnalysisDemoDomainModule` class and add the following code-block into the `ConfigureServices` method:
```csharp
Configure<CmsKitCommentOptions>(options =>
{
options.EntityTypes.Add(new CommentEntityTypeDefinition("Comment"));
options.IsRecaptchaEnabled = true;
});
```
Here, we simply defining what should be the entity-type name of our comment and also enable the reCaptcha for the comment system. After this configuration, now we can open the `Index.cshtml` file in the `*.Web` project and invoke the `CommentingViewComponent` as below:
```html
@page
@using Microsoft.AspNetCore.Mvc.Localization
@using SentimentAnalysisDemo.Localization
@using Volo.CmsKit.Public.Web.Pages.CmsKit.Shared.Components.Commenting
@model SentimentAnalysisDemo.Web.Pages.IndexModel
<div class="container">
<h5 class="display-5">Comments:</h5>
@await Component.InvokeAsync(typeof(CommentingViewComponent), new
{
entityType = "Comment",
entityId = "SentimentAnalysisDemo",
isReadOnly = false
})
</div>
```
After adding the related component, now you can run the web project and see the comment component if you want.
### Applying Sentiment Analysis (Creating the Spam Detection Service)
By default, CMS Kit's Comment Feature does not provide a spam detection system. In this demo application, we will override the `CommentPublicAppService`'s `CreateAsync` and `UpdateAsync` methods and then will add the spam detection control whenever a new comment has been submitted or an existing one is being updated.
To override the `CommentPublicAppService` and extend its use-case implementations, create a `MyCommentAppService` class and update its content as below:
```csharp
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using SentimentAnalysisDemo.ML;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.CmsKit.Comments;
using Volo.CmsKit.Public.Comments;
using Volo.CmsKit.Users;
namespace SentimentAnalysisDemo.Volo.CmsKit.Public.Comments;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(ICommentPublicAppService), typeof(CommentPublicAppService), typeof(MyCommentAppService))]
public class MyCommentAppService : CommentPublicAppService
{
protected ISpamDetector SpamDetector { get; }
public MyCommentAppService(
ICommentRepository commentRepository,
ICmsUserLookupService cmsUserLookupService,
IDistributedEventBus distributedEventBus,
CommentManager commentManager,
IOptionsSnapshot<CmsKitCommentOptions> cmsCommentOptions,
ISpamDetector spamDetector
)
: base(commentRepository, cmsUserLookupService, distributedEventBus, commentManager, cmsCommentOptions)
{
SpamDetector = spamDetector;
}
public override async Task<CommentDto> CreateAsync(string entityType, string entityId, CreateCommentInput input)
{
//Check message: spam or ham.
await SpamDetector.CheckAsync(input.Text);
return await base.CreateAsync(entityType, entityId, input);
}
public override async Task<CommentDto> UpdateAsync(Guid id, UpdateCommentInput input)
{
//Check message: spam or ham.
await SpamDetector.CheckAsync(input.Text);
return await base.UpdateAsync(id, input);
}
}
```
Here, we simply just inject the `ISpamDetector` service, which we will create in a minute, and use its `CheckAsync` method to make a spam check before the comment is created or updated.
Now, we can create the `ISpamDetector` service in the `*.Application.Contracts` project as follows:
```csharp
using System.Threading.Tasks;
namespace SentimentAnalysisDemo.ML;
public interface ISpamDetector
{
Task CheckAsync(string text);
}
```
Then, we can create the `SpamDetector` and implement the `ISpamDetector` interface (in the `*.Application` project):
```csharp
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.ML;
using SentimentAnalysisDemo.ML.Model;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace SentimentAnalysisDemo.ML;
public class SpamDetector : ISpamDetector, ITransientDependency
{
public async Task CheckAsync(string text)
{
//check if the text contains a spam content or not...
}
}
```
The `CheckAsync` method is where we need to make the sentiment analysis and detect if the comment contains spam content or not. If it's spam, then we should throw a [UserFriendlyException](https://docs.abp.io/en/abp/latest/Exception-Handling#user-friendly-exception) and notify the user that the comment should be updated and should not contain any spam content.
#### Spam Detection
Before, making the spam check, we should have a dataset to train a machine-learning model and add `Microsoft.ML` package into our project. For that purpose, I searched in [Kaggle](https://www.kaggle.com/) for spam datasets, found the **Spam-Mail-Detection-Dataset** from Kaggle, and downloaded the csv file to use in my application. Therefore, [you should also download the dataset from the link and put it under the **/ML/Data/spam_data.csv** directory of the `*.Web` project](https://github.com/EngincanV/SentimentAnalysisDemo/blob/master/src/SentimentAnalysisDemo.Web/ML/Data/spam_data.csv).
Here is what our dataset looks like (**0 -> not spam / 1 -> spam**):
| Category | Message |
|----------|---------|
| 0 | Is that seriously how you spell his name? |
| 1 | Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's |
| . | . |
| . | . |
| . | . |
> **Note:** This dataset is not ready-to use in a real-world solution. It's for mail spam detection but for the simplicity of the sample, it's not important and can be used for development purposes.
After, downloading the dataset and putting it in the directory of **/ML/Data**, now we can add the `Microsoft.ML` package into our `*.Application` project:
```bash
dotnet add package Microsoft.ML
```
Finally, we can implement the `CheckAsync` method and use sentiment analysis to make spam checks as follows:
```csharp
public async Task CheckAsync(string text)
{
var dataPath = Path.Combine(Environment.CurrentDirectory, "ML", "Data", "spam_data.csv");
var mlContext = new MLContext();
//Step 1: Load Data 👇
IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentAnalyzeInput>(dataPath, hasHeader: true, separatorChar: ',');
//Step 2: Split data to train-test data 👇
DataOperationsCatalog.TrainTestData trainTestSplit = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
IDataView trainingData = trainTestSplit.TrainSet; //80% of the data.
IDataView testData = trainTestSplit.TestSet; //20% of the data.
//Step 3: Common data process configuration with pipeline data transformations + choose and set the training algorithm 👇
var estimator = mlContext.Transforms.Text.FeaturizeText(outputColumnName: "Features", inputColumnName: nameof(SentimentAnalyzeInput.Message))
.Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(labelColumnName: "Label", featureColumnName: "Features"));
//Step 4: Train the model 👇
ITransformer model = estimator.Fit(trainingData);
//Step 5: Predict 👇
var sentimentAnalyzeInput = new SentimentAnalyzeInput
{
Message = text
};
var predictionEngine = mlContext.Model.CreatePredictionEngine<SentimentAnalyzeInput, SentimentAnalyzeResult>(model);
var result = predictionEngine.Predict(sentimentAnalyzeInput);
if (IsSpam(result))
{
throw new UserFriendlyException("Spam detected! Please update the message!");
}
}
private static bool IsSpam(SentimentAnalyzeResult result)
{
//1 -> spam / 0 -> ham (for 'Prediction' column)
return result is { Prediction: true, Probability: >= 0.5f };
}
```
Here, we have done the following things:
1. **First, we loaded the data**: For that reason, we created a `MLContext` object, which is a main class for all ML.NET operations. Then, we used its `LoadFromTextFile` method and specified the dataset path in our application. Also, we mapped the dataset columns to the `SentimentAnalyzeInput` class, which we will create later on.
2. **For the second step, we split the data as training and testing data**: To be able to train a machine learning model and then evaluate its accuracy, we should not use all the data for training purposes, instead, we should split the data as training and testing data and after training the model, compare the training data accuracy with the testing data.
3. **For the third step, we should make data transformation, convert the text-based data into numeric vectors and then choose a training algorithm**: After splitting the data for training and testing purposes, now we can apply some data transformations for the *Message* column in our dataset. Because, as you would see, messages are text-based inputs and machine-learning algorithms work best with the numeric vectors. So, we are making data transformations and representing the data as numeric values. Then, we can apply `BinaryClassification` with the **SdcaLogicticRegression** algorithm to our training data.
4. **Train the model**: Since we make the data transformations and chose the correct algorithm for our model, now we can train the model.
5. **Predict the sample data**: Finally, we can pass a comment to this method and make spam check and either approve our reject the comment according to the predicted result. (To make predictions, we need to create a **PredictionEngine** and get the final results in the output class that we specified, `SentimentAnalyzeResult` in our example)
Let's create the `SentimentAnalyzeInput` and `SentimentAnalyzeResult` classes as follows.
**SentimentAnalyzeInput.cs:**
```csharp
using Microsoft.ML.Data;
namespace SentimentAnalysisDemo.ML.Model;
public class SentimentAnalyzeInput
{
[LoadColumn(0), ColumnName("Label")]
public bool Category { get; set; }
[LoadColumn(1), ColumnName("Message")]
public string Message { get; set; }
}
```
**SentimentAnalyzeResult.cs:**
```csharp
using Microsoft.ML.Data;
namespace SentimentAnalysisDemo.ML.Model;
public class SentimentAnalyzeResult
{
[ColumnName("PredictedLabel")]
public bool Prediction { get; set; }
public float Probability { get; set; }
public float Score { get; set; }
}
```
Then, finally, we can run the application to see the final results:
![](demo.gif)
## Advanced: Reusing And Optimizing Machine Learning Models
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).
## 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)
Thanks for reading :)

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/cover-image.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/demo.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 KiB

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis-steps.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
docs/en/Community-Articles/2024-05-10-Sentiment-Analysis-within-ABP-Based-Application/sentiment-analysis.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

61
docs/en/Migration-Guides/Abp-8_2.md

@ -0,0 +1,61 @@
# ABP Version 8.2 Migration Guide
This document is a guide for upgrading ABP v8.x solutions to ABP v8.2. There are some changes in this version that may affect your applications, please read it carefully and apply the necessary changes to your application.
## Updated target frameworks to net8.0 for template projects
`TargetFrameworks` of the following template projects are upgraded to **net8.0**:
* `*.Application.Contracts`
* `*.Domain.Shared`
* `*.Domain`
* `*.MongoDB`
* `*.HttpApi.Client`
* `*.Host.Shared` (for module template)
Before this version, all of the projects above were targeting multiple frameworks (**netstandard2.0**, **netstandard2.1** and **net8.0**), with this version, we started to only target **net8.0** for these template projects. Note that, all other shared libraries still target multiple frameworks.
> This change should not affect your pre-existing solutions and you don't need to make any changes in your application. See the PR for more info: https://github.com/abpframework/abp/pull/19565
## Upgraded AutoMapper to 13.0.1
In this version, **AutoMapper** library version upgraded to 13.0.1. See [the release notes of AutoMapper v13.0.1](https://github.com/AutoMapper/AutoMapper/releases/tag/v13.0.1) for more information.
## Added default padding to `.tab-content` class for Basic Theme
In this version, default padding (padding-top: 1.5rem and padding-bottom: 1.5rem) has been added to the tab-content for the Basic Theme. See [#19475](https://github.com/abpframework/abp/pull/19475) for more information.
## Moved members page directory for Blogging Module
With this version on, ABP Framework allows you to use single blog mode, without needing to define a blog and a prefix. With this change, the following namespace changes were done:
* `Volo.Blogging.Pages.Blog` -> `Volo.Blogging.Pages.Blogs`
* `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.
If the flag icon has been specified while defining the localization languages, then it should be removed:
```diff
Configure<AbpLocalizationOptions>(options =>
{
- options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
+ options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi"));
//...
}
```
## Blazor Full-Stack Web UI
In this version, ABP Framework provides a new UI option called **Blazor Full-Stack WebApp**. We have already created an introduction/migration guide for you to check it: [Migrating to Blazor Web App](Abp-8-2-Blazor-Web-App.md)
> Please read the documentation carefully if you are considering migrating your existing **Blazor** project to **Blazor WebApp**.
## Session Management Infrastructure
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.

1
docs/en/Migration-Guides/Index.md

@ -2,6 +2,7 @@
The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md). The following documents explain how to migrate your existing ABP applications. We write migration documents only if you need to take an action while upgrading your solution. Otherwise, you can easily upgrade your solution using the [abp update command](../Upgrading.md).
- [8.x to 8.2](Abp-8_2.md)
- [8.0 to 8.1](Abp-8_1.md) - [8.0 to 8.1](Abp-8_1.md)
- [7.x to 8.0](Abp-8_0.md) - [7.x to 8.0](Abp-8_0.md)
- [7.3 to 7.4](Abp-7_4.md) - [7.3 to 7.4](Abp-7_4.md)

2
docs/en/Modules/Cms-Kit/Index.md

@ -2,6 +2,8 @@
This module provides CMS (Content Management System) capabilities for your application. It provides **core building blocks** and fully working **sub-systems** to create your own website with CMS features enabled, or use the building blocks in your web sites with any purpose. This module provides CMS (Content Management System) capabilities for your application. It provides **core building blocks** and fully working **sub-systems** to create your own website with CMS features enabled, or use the building blocks in your web sites with any purpose.
> You can see the live demo at [cms-kit-demo.abpdemo.com](https://cms-kit-demo.abpdemo.com/).
> **This module currently available only for the MVC / Razor Pages UI**. While there is no official Blazor package, it can also work in a Blazor Server UI since a Blazor Server UI is actually a hybrid application that runs in an ASP.NET Core MVC / Razor Pages application. > **This module currently available only for the MVC / Razor Pages UI**. While there is no official Blazor package, it can also work in a Blazor Server UI since a Blazor Server UI is actually a hybrid application that runs in an ASP.NET Core MVC / Razor Pages application.
The following features are currently available: The following features are currently available:

8
docs/en/Samples/Index.md

@ -12,8 +12,16 @@ Reference microservice solution built with the ABP Framework and .NET.
This is a reference application built with the ABP Framework. It implements the Domain Driven Design with multiple application layers. This is a reference application built with the ABP Framework. It implements the Domain Driven Design with multiple application layers.
* [Live](https://openeventhub.com/)
* [Source code](https://github.com/abpframework/eventhub) * [Source code](https://github.com/abpframework/eventhub)
## CMS Kit Demo
This reference application built with the ABP Framework and demonstrates the [CMS Kit Module's](../Modules/Cms-Kit/Index.md) capabilities.
* [Live](https://cms-kit-demo.abpdemo.com/)
* [Source code](https://github.com/abpframework/cms-kit-demo)
## Book Store ## Book Store
A simple CRUD application to show basic principles of developing an application with the ABP Framework. The same sample was implemented with different technologies: A simple CRUD application to show basic principles of developing an application with the ABP Framework. The same sample was implemented with different technologies:

59
docs/en/UI/Angular/Title-Strategy-Service.md

@ -0,0 +1,59 @@
# Title Strategy For Angular
## **ABP has a default title strategy for Angular UI**.
This strategy is based on the title property. Provide a title property when setting a new route.
**Example**
```ts
{
path: 'customers',
component: CustomersComponent,
title: 'AbpCustomers::Roles'
},
```
- It is better to use localized text in the title property. It will be translated by **LocalizationService**.
- The **`title`** property is already set in **ABP internal packages**.
## How it looks
When you create a new route and provide a **`title`** property, it will look like this **`<title> | <projectName>`**
### What is `projectName` and How to Customize
- **`projectName`** is the name of your application. By default, ABP sets a [**`projectName`**](https://github.com/abpframework/abp/blob/f48f78618a326644843c01424b093f0d79448769/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json#L4) for your application. This localization text is added for customization and can be changed for different languages.
### Disable `projectName`
- If you don't want to show **`projectName`** in the title, you can disable it.
**app.module.ts**
```ts
import { DISABLE_PROJECT_NAME } from '@abp/ng.core';
providers: [
...,
{ provide: DISABLE_PROJECT_NAME, useValue: true}
],
```
- Now only title will be shown.
## Override ABP's Default Title Strategy
**app.module.ts**
```ts
import { TitleStrategy } from '@angular/router';
import { YourCustomStrategy } from './title-strategy.service.ts';
providers: [
...,
{ provide: TitleStrategy, useExisting: YourCustomStrategy },
],
```
- You can check [Angular Documentation](https://angular.io/api/router/TitleStrategy) to write a custom **`TitleStrategy`**.

4
docs/en/docs-nav.json

@ -1188,6 +1188,10 @@
{ {
"text": "Abp Window Service", "text": "Abp Window Service",
"path": "UI/Angular/Abp-Window-Service.md" "path": "UI/Angular/Abp-Window-Service.md"
},
{
"text": "Title Strategy",
"path": "UI/Angular/Title-Strategy-Service.md"
} }
] ]
}, },

37
docs/zh-Hans/API/API-Versioning.md

@ -7,11 +7,10 @@ ABP框架集成了[ASPNET-API-版本控制](https://github.com/dotnet/aspnet-api
```cs ```cs
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}); });
@ -238,11 +237,10 @@ public override void ConfigureServices(ServiceConfigurationContext context)
preActions.Configure(options); preActions.Configure(options);
}); });
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
@ -262,27 +260,22 @@ public override void ConfigureServices(ServiceConfigurationContext context)
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
// Show neutral/versionless APIs.
context.Services.AddTransient<IApiControllerFilter, NoControllerFilter>();
context.Services.AddAbpApiVersioning(options => context.Services.AddAbpApiVersioning(options =>
{ {
// Show neutral/versionless APIs.
options.UseApiBehavior = false;
options.ReportApiVersions = true; options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;
}).AddApiExplorer(options => {
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
}); });
context.Services.AddVersionedApiExplorer(
options =>
{
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
// note: the specified format code will format the version as "'v'major[.minor][-status]"
options.GroupNameFormat = "'v'VVV";
// note: this option is only necessary when versioning by url segment. the SubstitutionFormat
// can also be used to control the format of the API version in route templates
options.SubstituteApiVersionInUrl = true;
});
context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); context.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
context.Services.AddAbpSwaggerGen( context.Services.AddAbpSwaggerGen(
@ -321,7 +314,7 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
app.UseAbpRequestLocalization(); app.UseAbpRequestLocalization();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI( app.UseAbpSwaggerUI(
options => options =>
{ {
var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>(); var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();

17
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/ClientProxyExceptionEventHandler.cs

@ -31,24 +31,11 @@ public class ClientProxyExceptionEventHandler : ILocalEventHandler<ClientProxyEx
case 401: case 401:
{ {
var options = scope.ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreComponentsWebOptions>>(); var options = scope.ServiceProvider.GetRequiredService<IOptions<AbpAspNetCoreComponentsWebOptions>>();
if (!options.Value.IsBlazorWebApp) if (!options.Value.IsBlazorWebApp)
{ {
var navigationManager = scope.ServiceProvider.GetRequiredService<NavigationManager>();
var accessTokenProvider = scope.ServiceProvider.GetRequiredService<IAccessTokenProvider>();
var authenticationOptions = scope.ServiceProvider.GetRequiredService<IOptions<AbpAuthenticationOptions>>(); var authenticationOptions = scope.ServiceProvider.GetRequiredService<IOptions<AbpAuthenticationOptions>>();
var result = await accessTokenProvider.RequestAccessToken(); var navigationManager = scope.ServiceProvider.GetRequiredService<NavigationManager>();
if (result.Status != AccessTokenResultStatus.Success) navigationManager.NavigateToLogout(authenticationOptions.Value.LogoutUrl, "/");
{
navigationManager.NavigateToLogout(authenticationOptions.Value.LogoutUrl);
return;
}
result.TryGetToken(out var token);
if (token != null && DateTimeOffset.Now >= token.Expires.AddMinutes(-5))
{
navigationManager.NavigateToLogout(authenticationOptions.Value.LogoutUrl);
}
} }
else else
{ {

6
framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/Extensions/DependencyInjection/AbpApiVersioningExtensions.cs

@ -11,7 +11,7 @@ namespace Microsoft.Extensions.DependencyInjection;
public static class AbpApiVersioningExtensions public static class AbpApiVersioningExtensions
{ {
public static IServiceCollection AddAbpApiVersioning( public static IApiVersioningBuilder AddAbpApiVersioning(
this IServiceCollection services, this IServiceCollection services,
Action<ApiVersioningOptions>? apiVersioningOptionsSetupAction = null, Action<ApiVersioningOptions>? apiVersioningOptionsSetupAction = null,
Action<MvcApiVersioningOptions>? mvcApiVersioningOptionsSetupAction = null) Action<MvcApiVersioningOptions>? mvcApiVersioningOptionsSetupAction = null)
@ -21,9 +21,7 @@ public static class AbpApiVersioningExtensions
apiVersioningOptionsSetupAction ??= _ => { }; apiVersioningOptionsSetupAction ??= _ => { };
mvcApiVersioningOptionsSetupAction ??= _ => { }; mvcApiVersioningOptionsSetupAction ??= _ => { };
services.AddApiVersioning(apiVersioningOptionsSetupAction).AddMvc(mvcApiVersioningOptionsSetupAction); return services.AddApiVersioning(apiVersioningOptionsSetupAction).AddMvc(mvcApiVersioningOptionsSetupAction);
return services;
} }
public static void ConfigureAbp(this MvcApiVersioningOptions options, AbpAspNetCoreMvcOptions mvcOptions) public static void ConfigureAbp(this MvcApiVersioningOptions options, AbpAspNetCoreMvcOptions mvcOptions)

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj

@ -32,6 +32,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" />
<PackageReference Include="Asp.Versioning.Mvc" /> <PackageReference Include="Asp.Versioning.Mvc" />
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" />
</ItemGroup> </ItemGroup>
</Project> </Project>

7
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs

@ -29,14 +29,17 @@ public class AbpAuditActionFilter : IAsyncActionFilter, IAbpFilter, ITransientDe
{ {
var result = await next(); var result = await next();
if (result.Exception != null && !result.ExceptionHandled) if (result.Exception != null && !auditLog!.Exceptions.Contains(result.Exception))
{ {
auditLog!.Exceptions.Add(result.Exception); auditLog!.Exceptions.Add(result.Exception);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
auditLog!.Exceptions.Add(ex); if (!auditLog!.Exceptions.Contains(ex))
{
auditLog!.Exceptions.Add(ex);
}
throw; throw;
} }
finally finally

7
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs

@ -34,14 +34,17 @@ public class AbpAuditPageFilter : IAsyncPageFilter, IAbpFilter, ITransientDepend
{ {
var result = await next(); var result = await next();
if (result.Exception != null && !result.ExceptionHandled) if (result.Exception != null && !auditLog!.Exceptions.Contains(result.Exception))
{ {
auditLog!.Exceptions.Add(result.Exception); auditLog!.Exceptions.Add(result.Exception);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
auditLog!.Exceptions.Add(ex); if (!auditLog!.Exceptions.Contains(ex))
{
auditLog!.Exceptions.Add(ex);
}
throw; throw;
} }
finally finally

14
framework/src/Volo.Abp.BlazoriseUI/Components/AbpExtensibleDataGrid.razor

@ -45,9 +45,9 @@
<EntityAction TItem="TItem" <EntityAction TItem="TItem"
Color="@(action.Color != null ? (Blazorise.Color)action.Color : Blazorise.Color.Primary)" Color="@(action.Color != null ? (Blazorise.Color)action.Color : Blazorise.Color.Primary)"
Icon="@action.Icon" Icon="@action.Icon"
Clicked="async () => await action.Clicked(context)" Clicked="async () => await action.Clicked(context!)"
ConfirmationMessage="() => action.ConfirmationMessage.Invoke(context)" ConfirmationMessage="() => action.ConfirmationMessage.Invoke(context!)"
Visible="@(action.Visible != null ? action.Visible(context) : true)" Visible="@(action.Visible != null ? action.Visible(context!) : true)"
Text="@action.Text" Text="@action.Text"
Disabled="@action.Disabled"> Disabled="@action.Disabled">
</EntityAction> </EntityAction>
@ -55,10 +55,10 @@
else else
{ {
<EntityAction TItem="TItem" <EntityAction TItem="TItem"
Clicked="async () => await action.Clicked(context)" Clicked="async () => await action.Clicked(context!)"
Color="@(action.Color != null ? (Blazorise.Color)action.Color : Blazorise.Color.Primary)" Color="@(action.Color != null ? (Blazorise.Color)action.Color : Blazorise.Color.Primary)"
Icon="@action.Icon" Icon="@action.Icon"
Visible="@(action.Visible != null ? action.Visible(context) : true)" Visible="@(action.Visible != null ? action.Visible(context!) : true)"
Text="@action.Text" Text="@action.Text"
Disabled="@action.Disabled"> Disabled="@action.Disabled">
</EntityAction> </EntityAction>
@ -76,7 +76,7 @@
{ {
<DataGridColumn TItem="TItem" Field="@column.Data" Caption="@column.Title" Sortable="@column.Sortable" DisplayFormat="@column.DisplayFormat" DisplayFormatProvider="@column.DisplayFormatProvider" Displayable="column.Visible" > <DataGridColumn TItem="TItem" Field="@column.Data" Caption="@column.Title" Sortable="@column.Sortable" DisplayFormat="@column.DisplayFormat" DisplayFormatProvider="@column.DisplayFormatProvider" Displayable="column.Visible" >
<DisplayTemplate> <DisplayTemplate>
@RenderCustomTableColumnComponent(column.Component, context) @RenderCustomTableColumnComponent(column.Component, context!)
</DisplayTemplate> </DisplayTemplate>
</DataGridColumn> </DataGridColumn>
} }
@ -84,7 +84,7 @@
{ {
<DataGridColumn TItem="TItem" Field="@column.Data" Caption="@column.Title" Sortable="@column.Sortable" Displayable="column.Visible"> <DataGridColumn TItem="TItem" Field="@column.Data" Caption="@column.Title" Sortable="@column.Sortable" Displayable="column.Visible">
<DisplayTemplate> <DisplayTemplate>
@RenderCustomTableColumnComponent(column.Component, context) @RenderCustomTableColumnComponent(column.Component, context!)
</DisplayTemplate> </DisplayTemplate>
</DataGridColumn> </DataGridColumn>
} }

2
framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/LookupExtensionProperty.razor

@ -10,7 +10,7 @@
TItem="SelectItem<object>" TItem="SelectItem<object>"
TValue="object" TValue="object"
TextField="item => item?.Text!" TextField="item => item?.Text!"
ValueField="item => item?.Value" ValueField="item => item?.Value!"
SelectedValue="@SelectedValue" SelectedValue="@SelectedValue"
SelectedValueChanged="@SelectedValueChanged" SelectedValueChanged="@SelectedValueChanged"
SearchChanged="@SearchFilterChangedAsync" SearchChanged="@SearchFilterChangedAsync"

1
framework/src/Volo.Abp.Cli.Core/Volo.Abp.Cli.Core.csproj

@ -15,7 +15,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" /> <PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" />
<PackageReference Include="SharpZipLib" /> <PackageReference Include="SharpZipLib" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<PackageReference Include="NuGet.Versioning" /> <PackageReference Include="NuGet.Versioning" />
<PackageReference Include="System.Text.Encoding.CodePages" /> <PackageReference Include="System.Text.Encoding.CodePages" />
<PackageReference Include="System.Security.Permissions" /> <PackageReference Include="System.Security.Permissions" />

11
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs

@ -158,9 +158,16 @@ public class AbpIoSourceCodeStore : ISourceCodeStore, ITransientDependency
throw new Exception("There is no version found with given version: " + version); throw new Exception("There is no version found with given version: " + version);
} }
var nugetVersion = version; var nugetVersion = await GetTemplateNugetVersionAsync(name, type, version) ?? version;
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name.Replace("/", ".") + ".zip"); if (!string.IsNullOrWhiteSpace(templateSource) && !IsNetworkSource(templateSource))
{
Logger.LogInformation("Using local " + type + ": " + name + ", version: " + version);
return new TemplateFile(File.ReadAllBytes(Path.Combine(templateSource, name + "-" + version + ".zip")),
version, latestVersion, nugetVersion);
}
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name.Replace("/", ".") + "-" + version + ".zip");
#if DEBUG #if DEBUG
if (File.Exists(localCacheFile) && templateSource.IsNullOrWhiteSpace()) if (File.Exists(localCacheFile) && templateSource.IsNullOrWhiteSpace())

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStyleStep.cs

@ -31,7 +31,7 @@ public class ChangeThemeStyleStep : ProjectBuildPipelineStep
var defaultThemeStyleName = "LeptonXStyleNames.System"; var defaultThemeStyleName = "LeptonXStyleNames.System";
var newThemeStyleName = $"LeptonXStyleNames.{themeStyleName}"; var newThemeStyleName = $"LeptonXStyleNames.{themeStyleName}";
var filePaths = new List<string> var filePaths = new List<string>
{ {
"/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs", "/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs",
"/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs", "/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs",
@ -40,6 +40,10 @@ public class ChangeThemeStyleStep : ProjectBuildPipelineStep
"/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs", "/MyCompanyName.MyProjectName.Blazor/MyProjectNameBlazorModule.cs",
"/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs", "/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs",
"/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameModule.cs", "/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameModule.cs",
"/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs",
"/MyCompanyName.MyProjectName.Blazor.WebApp.Client/MyProjectNameBlazorClientModule.cs",
"/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs",
"/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client/MyProjectNameBlazorClientModule.cs",
"/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyProjectNameModule.cs", "/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyProjectNameModule.cs",
"/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs", "/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs",
"/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs", "/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs",
@ -76,4 +80,4 @@ public class ChangeThemeStyleStep : ProjectBuildPipelineStep
file.SetLines(lines); file.SetLines(lines);
} }
} }

23
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateSwitchEntityFrameworkCoreToMongoDbStep.cs

@ -106,6 +106,29 @@ public class AppTemplateSwitchEntityFrameworkCoreToMongoDbStep : ProjectBuildPip
"/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/appsettings.json" "/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/appsettings.json"
); );
//MyCompanyName.MyProjectName.Blazor.WebApp
ChangeProjectReference(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyCompanyName.MyProjectName.Blazor.WebApp.csproj",
_hasDbMigrations ? "EntityFrameworkCore.DbMigrations" : "EntityFrameworkCore",
"MongoDB"
);
ChangeNamespaceAndKeyword(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs",
"MyCompanyName.MyProjectName.EntityFrameworkCore",
"MyCompanyName.MyProjectName.MongoDB",
_hasDbMigrations ? "MyProjectNameEntityFrameworkCoreDbMigrationsModule" : "MyProjectNameEntityFrameworkCoreModule",
"MyProjectNameMongoDbModule"
);
ChangeConnectionStringToMongoDb(
context,
"/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/appsettings.json"
);
//MyCompanyName.MyProjectName.HttpApi.HostWithIds //MyCompanyName.MyProjectName.HttpApi.HostWithIds
ChangeProjectReference( ChangeProjectReference(

21
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -192,9 +192,9 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext,
{ {
try try
{ {
if (EntityChangeOptions.Value.PublishEntityUpdatedEventWhenNavigationChanges) foreach (var entityEntry in AbpEfCoreNavigationHelper.GetChangedEntityEntries())
{ {
foreach (var entityEntry in AbpEfCoreNavigationHelper.GetChangedEntityEntries()) if (EntityChangeOptions.Value.PublishEntityUpdatedEventWhenNavigationChanges)
{ {
if (entityEntry.Entity is ISoftDelete && entityEntry.Entity.As<ISoftDelete>().IsDeleted) if (entityEntry.Entity is ISoftDelete && entityEntry.Entity.As<ISoftDelete>().IsDeleted)
{ {
@ -205,6 +205,23 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext,
EntityChangeEventHelper.PublishEntityUpdatedEvent(entityEntry.Entity); EntityChangeEventHelper.PublishEntityUpdatedEvent(entityEntry.Entity);
} }
} }
else if (entityEntry.Properties.Any(x => x.IsModified && (x.Metadata.ValueGenerated == ValueGenerated.Never || x.Metadata.ValueGenerated == ValueGenerated.OnAdd)))
{
if (entityEntry.Properties.Where(x => x.IsModified).All(x => x.Metadata.IsForeignKey()))
{
// Skip `PublishEntityDeletedEvent/PublishEntityUpdatedEvent` if only foreign keys have changed.
break;
}
if (entityEntry.Entity is ISoftDelete && entityEntry.Entity.As<ISoftDelete>().IsDeleted)
{
EntityChangeEventHelper.PublishEntityDeletedEvent(entityEntry.Entity);
}
else
{
EntityChangeEventHelper.PublishEntityUpdatedEvent(entityEntry.Entity);
}
}
} }
var auditLog = AuditingManager?.Current?.Log; var auditLog = AuditingManager?.Current?.Log;

8
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/TestMigrationsDbContext.cs

@ -28,6 +28,8 @@ public class TestMigrationsDbContext : AbpDbContext<TestMigrationsDbContext>
public DbSet<AppEntityWithNavigations> AppEntityWithNavigations { get; set; } public DbSet<AppEntityWithNavigations> AppEntityWithNavigations { get; set; }
public DbSet<AppEntityWithNavigationsForeign> AppEntityWithNavigationsForeign { get; set; }
public TestMigrationsDbContext(DbContextOptions<TestMigrationsDbContext> options) public TestMigrationsDbContext(DbContextOptions<TestMigrationsDbContext> options)
: base(options) : base(options)
{ {
@ -74,6 +76,7 @@ public class TestMigrationsDbContext : AbpDbContext<TestMigrationsDbContext>
b.HasOne(x => x.OneToOne).WithOne().HasForeignKey<AppEntityWithNavigationChildOneToOne>(x => x.Id); b.HasOne(x => x.OneToOne).WithOne().HasForeignKey<AppEntityWithNavigationChildOneToOne>(x => x.Id);
b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationId); b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationId);
b.HasMany(x => x.ManyToMany).WithMany(x => x.ManyToMany).UsingEntity<AppEntityWithNavigationsAndAppEntityWithNavigationChildManyToMany>(); b.HasMany(x => x.ManyToMany).WithMany(x => x.ManyToMany).UsingEntity<AppEntityWithNavigationsAndAppEntityWithNavigationChildManyToMany>();
b.HasOne<AppEntityWithNavigationsForeign>().WithMany().HasForeignKey(x => x.AppEntityWithNavigationForeignId).IsRequired(false);
}); });
modelBuilder.Entity<AppEntityWithNavigationChildOneToOne>(b => modelBuilder.Entity<AppEntityWithNavigationChildOneToOne>(b =>
@ -87,5 +90,10 @@ public class TestMigrationsDbContext : AbpDbContext<TestMigrationsDbContext>
b.ConfigureByConvention(); b.ConfigureByConvention();
b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationChildOneToManyId); b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationChildOneToManyId);
}); });
modelBuilder.Entity<AppEntityWithNavigationsForeign>(b =>
{
b.ConfigureByConvention();
});
} }
} }

8
framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs

@ -36,6 +36,8 @@ public class TestAppDbContext : AbpDbContext<TestAppDbContext>, IThirdDbContext,
public DbSet<AppEntityWithNavigations> AppEntityWithNavigations { get; set; } public DbSet<AppEntityWithNavigations> AppEntityWithNavigations { get; set; }
public DbSet<AppEntityWithNavigationsForeign> AppEntityWithNavigationsForeign { get; set; }
public TestAppDbContext(DbContextOptions<TestAppDbContext> options) public TestAppDbContext(DbContextOptions<TestAppDbContext> options)
: base(options) : base(options)
{ {
@ -101,6 +103,7 @@ public class TestAppDbContext : AbpDbContext<TestAppDbContext>, IThirdDbContext,
b.HasOne(x => x.OneToOne).WithOne().HasForeignKey<AppEntityWithNavigationChildOneToOne>(x => x.Id); b.HasOne(x => x.OneToOne).WithOne().HasForeignKey<AppEntityWithNavigationChildOneToOne>(x => x.Id);
b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationId); b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationId);
b.HasMany(x => x.ManyToMany).WithMany(x => x.ManyToMany).UsingEntity<AppEntityWithNavigationsAndAppEntityWithNavigationChildManyToMany>(); b.HasMany(x => x.ManyToMany).WithMany(x => x.ManyToMany).UsingEntity<AppEntityWithNavigationsAndAppEntityWithNavigationChildManyToMany>();
b.HasOne<AppEntityWithNavigationsForeign>().WithMany().HasForeignKey(x => x.AppEntityWithNavigationForeignId).IsRequired(false);
}); });
modelBuilder.Entity<AppEntityWithNavigationChildOneToOne>(b => modelBuilder.Entity<AppEntityWithNavigationChildOneToOne>(b =>
@ -115,6 +118,11 @@ public class TestAppDbContext : AbpDbContext<TestAppDbContext>, IThirdDbContext,
b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationChildOneToManyId); b.HasMany(x => x.OneToMany).WithOne().HasForeignKey(x => x.AppEntityWithNavigationChildOneToManyId);
}); });
modelBuilder.Entity<AppEntityWithNavigationsForeign>(b =>
{
b.ConfigureByConvention();
});
modelBuilder.TryConfigureObjectExtensions<TestAppDbContext>(); modelBuilder.TryConfigureObjectExtensions<TestAppDbContext>();
} }
} }

19
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Domain/AppEntityWithNavigations.cs

@ -23,6 +23,7 @@ public class AppEntityWithNavigations : AggregateRoot<Guid>
public string FullName { get; set; } public string FullName { get; set; }
public AppEntityWithValueObjectAddress AppEntityWithValueObjectAddress { get; set; } public AppEntityWithValueObjectAddress AppEntityWithValueObjectAddress { get; set; }
public virtual AppEntityWithNavigationChildOneToOne OneToOne { get; set; } public virtual AppEntityWithNavigationChildOneToOne OneToOne { get; set; }
@ -30,6 +31,8 @@ public class AppEntityWithNavigations : AggregateRoot<Guid>
public virtual List<AppEntityWithNavigationChildOneToMany> OneToMany { get; set; } public virtual List<AppEntityWithNavigationChildOneToMany> OneToMany { get; set; }
public virtual List<AppEntityWithNavigationChildManyToMany> ManyToMany { get; set; } public virtual List<AppEntityWithNavigationChildManyToMany> ManyToMany { get; set; }
public virtual Guid? AppEntityWithNavigationForeignId { get; set; }
} }
public class AppEntityWithValueObjectAddress : ValueObject public class AppEntityWithValueObjectAddress : ValueObject
@ -88,3 +91,19 @@ public class AppEntityWithNavigationsAndAppEntityWithNavigationChildManyToMany
public Guid AppEntityWithNavigationChildManyToManyId { get; set; } public Guid AppEntityWithNavigationChildManyToManyId { get; set; }
} }
public class AppEntityWithNavigationsForeign : AggregateRoot<Guid>
{
protected AppEntityWithNavigationsForeign()
{
}
public AppEntityWithNavigationsForeign(Guid id, string name)
: base(id)
{
Name = name;
}
public string Name { get; set; }
}

101
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Testing/DomainEvents_Tests.cs

@ -191,11 +191,13 @@ public abstract class AbpEntityChangeOptions_DomainEvents_Tests<TStartupModule>
where TStartupModule : IAbpModule where TStartupModule : IAbpModule
{ {
protected readonly IRepository<AppEntityWithNavigations, Guid> AppEntityWithNavigationsRepository; protected readonly IRepository<AppEntityWithNavigations, Guid> AppEntityWithNavigationsRepository;
protected readonly IRepository<AppEntityWithNavigationsForeign, Guid> AppEntityWithNavigationForeignRepository;
protected readonly ILocalEventBus LocalEventBus; protected readonly ILocalEventBus LocalEventBus;
protected AbpEntityChangeOptions_DomainEvents_Tests() protected AbpEntityChangeOptions_DomainEvents_Tests()
{ {
AppEntityWithNavigationsRepository = GetRequiredService<IRepository<AppEntityWithNavigations, Guid>>(); AppEntityWithNavigationsRepository = GetRequiredService<IRepository<AppEntityWithNavigations, Guid>>();
AppEntityWithNavigationForeignRepository = GetRequiredService<IRepository<AppEntityWithNavigationsForeign, Guid>>();
LocalEventBus = GetRequiredService<ILocalEventBus>(); LocalEventBus = GetRequiredService<ILocalEventBus>();
} }
@ -288,4 +290,103 @@ public abstract class AbpEntityChangeOptions_DomainEvents_Tests<TStartupModule>
}); });
entityUpdatedEventTriggered.ShouldBeFalse(); entityUpdatedEventTriggered.ShouldBeFalse();
} }
[Fact]
public async Task Should_Trigger_EntityUpdatedEvent_For_Aggregate_Root_When_Property_And_Navigation_Changes_Tests()
{
var entityId = Guid.NewGuid();
await AppEntityWithNavigationsRepository.InsertAsync(new AppEntityWithNavigations(entityId, "TestEntity"));
var entityWithNavigationForeignId = Guid.NewGuid();
var entityWithNavigationForeignId2 = Guid.NewGuid();
await AppEntityWithNavigationForeignRepository.InsertAsync(new AppEntityWithNavigationsForeign(entityWithNavigationForeignId, "TestEntityWithNavigationForeign"));
await AppEntityWithNavigationForeignRepository.InsertAsync(new AppEntityWithNavigationsForeign(entityWithNavigationForeignId2, "TestEntityWithNavigationForeign2"));
var entityUpdatedEventTriggered = false;
LocalEventBus.Subscribe<EntityUpdatedEventData<AppEntityWithNavigations>>(data =>
{
entityUpdatedEventTriggered = !entityUpdatedEventTriggered;
return Task.CompletedTask;
});
// Test with simple property with foreign key
await WithUnitOfWorkAsync(async () =>
{
var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId);
entity.Name = Guid.NewGuid().ToString();
entity.AppEntityWithNavigationForeignId = entityWithNavigationForeignId;
await AppEntityWithNavigationsRepository.UpdateAsync(entity);
});
entityUpdatedEventTriggered.ShouldBeTrue();
// Test only foreign key changed
entityUpdatedEventTriggered = false;
await WithUnitOfWorkAsync(async () =>
{
var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId);
entity.AppEntityWithNavigationForeignId = entityWithNavigationForeignId2;
await AppEntityWithNavigationsRepository.UpdateAsync(entity);
});
entityUpdatedEventTriggered.ShouldBeFalse();
// Test with simple property with value object
await WithUnitOfWorkAsync(async () =>
{
var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId);
entity.Name = Guid.NewGuid().ToString();
entity.AppEntityWithValueObjectAddress = new AppEntityWithValueObjectAddress("Turkey");
await AppEntityWithNavigationsRepository.UpdateAsync(entity);
});
entityUpdatedEventTriggered.ShouldBeTrue();
// Test with simple property with one to one
entityUpdatedEventTriggered = false;
await WithUnitOfWorkAsync(async () =>
{
var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId);
entity.Name = Guid.NewGuid().ToString();
entity.OneToOne = new AppEntityWithNavigationChildOneToOne
{
ChildName = "ChildName"
};
await AppEntityWithNavigationsRepository.UpdateAsync(entity);
});
entityUpdatedEventTriggered.ShouldBeTrue();
// Test with simple property with one to many
entityUpdatedEventTriggered = false;
await WithUnitOfWorkAsync(async () =>
{
var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId);
entity.Name = Guid.NewGuid().ToString();
entity.OneToMany = new List<AppEntityWithNavigationChildOneToMany>()
{
new AppEntityWithNavigationChildOneToMany
{
AppEntityWithNavigationId = entity.Id,
ChildName = "ChildName1"
}
};
await AppEntityWithNavigationsRepository.UpdateAsync(entity);
});
entityUpdatedEventTriggered.ShouldBeTrue();
// Test with simple property with many to many
entityUpdatedEventTriggered = false;
await WithUnitOfWorkAsync(async () =>
{
var entity = await AppEntityWithNavigationsRepository.GetAsync(entityId);
entity.Name = Guid.NewGuid().ToString();
entity.ManyToMany = new List<AppEntityWithNavigationChildManyToMany>()
{
new AppEntityWithNavigationChildManyToMany
{
ChildName = "ChildName1"
}
};
await AppEntityWithNavigationsRepository.UpdateAsync(entity);
});
entityUpdatedEventTriggered.ShouldBeTrue();
}
} }

2
latest-versions.json

@ -1,6 +1,6 @@
[ [
{ {
"version": "8.1.1", "version": "8.1.3",
"releaseDate": "", "releaseDate": "",
"type": "stable", "type": "stable",
"message": "" "message": ""

6
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/package.json

@ -3,8 +3,8 @@
"name": "asp.net", "name": "asp.net",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@abp/aspnetcore.mvc.ui.theme.shared": "~8.1.1", "@abp/aspnetcore.mvc.ui.theme.shared": "~8.2.0-rc.3",
"@abp/prismjs": "~8.1.1", "@abp/prismjs": "~8.2.0-rc.3",
"@abp/highlight.js": "~8.1.1" "@abp/highlight.js": "~8.2.0-rc.3"
} }
} }

8003
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/all.css

File diff suppressed because it is too large

2194
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/css/v4-shims.css

File diff suppressed because it is too large

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.ttf

Binary file not shown.

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2

Binary file not shown.

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.ttf

Binary file not shown.

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2

Binary file not shown.

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.ttf

Binary file not shown.

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2

Binary file not shown.

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.ttf

Binary file not shown.

BIN
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.woff2

Binary file not shown.

56
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.css

@ -1,56 +0,0 @@
@keyframes spin {
0% {
transform: translateZ(0) rotate(0deg);
}
100% {
transform: translateZ(0) rotate(360deg);
}
}
.abp-block-area {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 102;
background-color: #fff;
opacity: .8;
transition: opacity .25s;
}
.abp-block-area.abp-block-area-disappearing {
opacity: 0;
}
.abp-block-area.abp-block-area-busy:after {
content: attr(data-text);
display: block;
max-width: 125px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 20px;
font-family: sans-serif;
color: #343a40;
text-align: center;
text-transform: uppercase;
}
.abp-block-area.abp-block-area-busy:before {
content: "";
display: block;
width: 150px;
height: 150px;
border-radius: 50%;
border-width: 2px;
border-style: solid;
border-color: transparent #228ae6 #228ae6 #228ae6;
position: absolute;
top: calc(50% - 75px);
left: calc(50% - 75px);
will-change: transform;
animation: spin .75s infinite ease-in-out;
}

823
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/core/abp.js

@ -1,823 +0,0 @@
var abp = abp || {};
(function () {
/* Application paths *****************************************/
//Current application root path (including virtual directory if exists).
abp.appPath = abp.appPath || '/';
abp.pageLoadTime = new Date();
//Converts given path to absolute path using abp.appPath variable.
abp.toAbsAppPath = function (path) {
if (path.indexOf('/') == 0) {
path = path.substring(1);
}
return abp.appPath + path;
};
/* LOGGING ***************************************************/
//Implements Logging API that provides secure & controlled usage of console.log
abp.log = abp.log || {};
abp.log.levels = {
DEBUG: 1,
INFO: 2,
WARN: 3,
ERROR: 4,
FATAL: 5
};
abp.log.level = abp.log.levels.DEBUG;
abp.log.log = function (logObject, logLevel) {
if (!window.console || !window.console.log) {
return;
}
if (logLevel != undefined && logLevel < abp.log.level) {
return;
}
console.log(logObject);
};
abp.log.debug = function (logObject) {
abp.log.log("DEBUG: ", abp.log.levels.DEBUG);
abp.log.log(logObject, abp.log.levels.DEBUG);
};
abp.log.info = function (logObject) {
abp.log.log("INFO: ", abp.log.levels.INFO);
abp.log.log(logObject, abp.log.levels.INFO);
};
abp.log.warn = function (logObject) {
abp.log.log("WARN: ", abp.log.levels.WARN);
abp.log.log(logObject, abp.log.levels.WARN);
};
abp.log.error = function (logObject) {
abp.log.log("ERROR: ", abp.log.levels.ERROR);
abp.log.log(logObject, abp.log.levels.ERROR);
};
abp.log.fatal = function (logObject) {
abp.log.log("FATAL: ", abp.log.levels.FATAL);
abp.log.log(logObject, abp.log.levels.FATAL);
};
/* LOCALIZATION ***********************************************/
abp.localization = abp.localization || {};
abp.localization.internal = abp.localization.internal || {};
abp.localization.values = abp.localization.values || {};
abp.localization.resources = abp.localization.resources || {};
abp.localization.internal.getResource = function (resourceName) {
var resource = abp.localization.resources[resourceName];
if (resource) {
return resource;
}
var legacySource = abp.localization.values[resourceName];
if (legacySource) {
return {
texts: abp.localization.values[resourceName],
baseResources: []
};
}
abp.log.warn('Could not find localization source: ' + resourceName);
return null;
};
abp.localization.internal.localize = function (key, sourceName) {
var resource = abp.localization.internal.getResource(sourceName);
if (!resource){
return {
value: key,
found: false
};
}
var value = resource.texts[key];
if (value === undefined) {
for (var i = 0; i < resource.baseResources.length; i++){
var basedArguments = Array.prototype.slice.call(arguments, 0);
basedArguments[1] = resource.baseResources[i];
var result = abp.localization.internal.localize.apply(this, basedArguments);
if (result.found){
return result;
}
}
return {
value: key,
found: false
};
}
var copiedArguments = Array.prototype.slice.call(arguments, 0);
copiedArguments.splice(1, 1);
copiedArguments[0] = value;
return {
value: abp.utils.formatString.apply(this, copiedArguments),
found: true
};
};
abp.localization.localize = function (key, sourceName) {
if (sourceName === '_') { //A convention to suppress the localization
return key;
}
if (sourceName) {
return abp.localization.internal.localize.apply(this, arguments).value;
}
if (!abp.localization.defaultResourceName) {
abp.log.warn('Localization source name is not specified and the defaultResourceName was not defined!');
return key;
}
var copiedArguments = Array.prototype.slice.call(arguments, 0);
copiedArguments.splice(1, 1, abp.localization.defaultResourceName);
return abp.localization.internal.localize.apply(this, copiedArguments).value;
};
abp.localization.isLocalized = function (key, sourceName) {
if (sourceName === '_') { //A convention to suppress the localization
return true;
}
sourceName = sourceName || abp.localization.defaultResourceName;
if (!sourceName) {
return false;
}
return abp.localization.internal.localize(key, sourceName).found;
};
abp.localization.getResource = function (name) {
return function () {
var copiedArguments = Array.prototype.slice.call(arguments, 0);
copiedArguments.splice(1, 0, name);
return abp.localization.localize.apply(this, copiedArguments);
};
};
abp.localization.defaultResourceName = undefined;
abp.localization.currentCulture = {
cultureName: undefined
};
var getMapValue = function (packageMaps, packageName, language) {
language = language || abp.localization.currentCulture.name;
if (!packageMaps || !packageName || !language) {
return language;
}
var packageMap = packageMaps[packageName];
if (!packageMap) {
return language;
}
for (var i = 0; i < packageMap.length; i++) {
var map = packageMap[i];
if (map.name === language){
return map.value;
}
}
return language;
};
abp.localization.getLanguagesMap = function (packageName, language) {
return getMapValue(abp.localization.languagesMap, packageName, language);
};
abp.localization.getLanguageFilesMap = function (packageName, language) {
return getMapValue(abp.localization.languageFilesMap, packageName, language);
};
/* AUTHORIZATION **********************************************/
abp.auth = abp.auth || {};
abp.auth.grantedPolicies = abp.auth.grantedPolicies || {};
abp.auth.isGranted = function (policyName) {
return abp.auth.grantedPolicies[policyName] != undefined;
};
abp.auth.isAnyGranted = function () {
if (!arguments || arguments.length <= 0) {
return true;
}
for (var i = 0; i < arguments.length; i++) {
if (abp.auth.isGranted(arguments[i])) {
return true;
}
}
return false;
};
abp.auth.areAllGranted = function () {
if (!arguments || arguments.length <= 0) {
return true;
}
for (var i = 0; i < arguments.length; i++) {
if (!abp.auth.isGranted(arguments[i])) {
return false;
}
}
return true;
};
abp.auth.tokenCookieName = 'Abp.AuthToken';
abp.auth.setToken = function (authToken, expireDate) {
abp.utils.setCookieValue(abp.auth.tokenCookieName, authToken, expireDate, abp.appPath, abp.domain);
};
abp.auth.getToken = function () {
return abp.utils.getCookieValue(abp.auth.tokenCookieName);
}
abp.auth.clearToken = function () {
abp.auth.setToken();
}
/* SETTINGS *************************************************/
abp.setting = abp.setting || {};
abp.setting.values = abp.setting.values || {};
abp.setting.get = function (name) {
return abp.setting.values[name];
};
abp.setting.getBoolean = function (name) {
var value = abp.setting.get(name);
return value == 'true' || value == 'True';
};
abp.setting.getInt = function (name) {
return parseInt(abp.setting.values[name]);
};
/* NOTIFICATION *********************************************/
//Defines Notification API, not implements it
abp.notify = abp.notify || {};
abp.notify.success = function (message, title, options) {
abp.log.warn('abp.notify.success is not implemented!');
};
abp.notify.info = function (message, title, options) {
abp.log.warn('abp.notify.info is not implemented!');
};
abp.notify.warn = function (message, title, options) {
abp.log.warn('abp.notify.warn is not implemented!');
};
abp.notify.error = function (message, title, options) {
abp.log.warn('abp.notify.error is not implemented!');
};
/* MESSAGE **************************************************/
//Defines Message API, not implements it
abp.message = abp.message || {};
abp.message._showMessage = function (message, title) {
alert((title || '') + ' ' + message);
};
abp.message.info = function (message, title) {
abp.log.warn('abp.message.info is not implemented!');
return abp.message._showMessage(message, title);
};
abp.message.success = function (message, title) {
abp.log.warn('abp.message.success is not implemented!');
return abp.message._showMessage(message, title);
};
abp.message.warn = function (message, title) {
abp.log.warn('abp.message.warn is not implemented!');
return abp.message._showMessage(message, title);
};
abp.message.error = function (message, title) {
abp.log.warn('abp.message.error is not implemented!');
return abp.message._showMessage(message, title);
};
abp.message.confirm = function (message, titleOrCallback, callback) {
abp.log.warn('abp.message.confirm is not properly implemented!');
if (titleOrCallback && !(typeof titleOrCallback == 'string')) {
callback = titleOrCallback;
}
var result = confirm(message);
callback && callback(result);
};
/* UI *******************************************************/
abp.ui = abp.ui || {};
/* UI BLOCK */
//Defines UI Block API and implements basically
var $abpBlockArea = document.createElement('div');
$abpBlockArea.classList.add('abp-block-area');
/* opts: { //Can be an object with options or a string for query a selector
* elm: a query selector (optional - default: document.body)
* busy: boolean (optional - default: false)
* promise: A promise with always or finally handler (optional - auto unblocks the ui if provided)
* }
*/
abp.ui.block = function (opts) {
if (!opts) {
opts = {};
} else if (typeof opts == 'string') {
opts = {
elm: opts
};
}
var $elm = document.querySelector(opts.elm) || document.body;
if (opts.busy) {
$abpBlockArea.classList.add('abp-block-area-busy');
} else {
$abpBlockArea.classList.remove('abp-block-area-busy');
}
if (document.querySelector(opts.elm)) {
$abpBlockArea.style.position = 'absolute';
} else {
$abpBlockArea.style.position = 'fixed';
}
$elm.appendChild($abpBlockArea);
if (opts.promise) {
if (opts.promise.always) { //jQuery.Deferred style
opts.promise.always(function () {
abp.ui.unblock({
$elm: opts.elm
});
});
} else if (opts.promise['finally']) { //Q style
opts.promise['finally'](function () {
abp.ui.unblock({
$elm: opts.elm
});
});
}
}
};
/* opts: {
*
* }
*/
abp.ui.unblock = function (opts) {
var element = document.querySelector('.abp-block-area');
if (element) {
element.classList.add('abp-block-area-disappearing');
setTimeout(function () {
if (element) {
element.classList.remove('abp-block-area-disappearing');
if (element.parentElement) {
element.parentElement.removeChild(element);
}
}
}, 250);
}
};
/* UI BUSY */
//Defines UI Busy API, not implements it
abp.ui.setBusy = function (opts) {
if (!opts) {
opts = {
busy: true
};
} else if (typeof opts == 'string') {
opts = {
elm: opts,
busy: true
};
}
abp.ui.block(opts);
};
abp.ui.clearBusy = function (opts) {
abp.ui.unblock(opts);
};
/* SIMPLE EVENT BUS *****************************************/
abp.event = (function () {
var _callbacks = {};
var on = function (eventName, callback) {
if (!_callbacks[eventName]) {
_callbacks[eventName] = [];
}
_callbacks[eventName].push(callback);
};
var off = function (eventName, callback) {
var callbacks = _callbacks[eventName];
if (!callbacks) {
return;
}
var index = -1;
for (var i = 0; i < callbacks.length; i++) {
if (callbacks[i] === callback) {
index = i;
break;
}
}
if (index < 0) {
return;
}
_callbacks[eventName].splice(index, 1);
};
var trigger = function (eventName) {
var callbacks = _callbacks[eventName];
if (!callbacks || !callbacks.length) {
return;
}
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < callbacks.length; i++) {
callbacks[i].apply(this, args);
}
};
// Public interface ///////////////////////////////////////////////////
return {
on: on,
off: off,
trigger: trigger
};
})();
/* UTILS ***************************************************/
abp.utils = abp.utils || {};
/* Creates a name namespace.
* Example:
* var taskService = abp.utils.createNamespace(abp, 'services.task');
* taskService will be equal to abp.services.task
* first argument (root) must be defined first
************************************************************/
abp.utils.createNamespace = function (root, ns) {
var parts = ns.split('.');
for (var i = 0; i < parts.length; i++) {
if (typeof root[parts[i]] == 'undefined') {
root[parts[i]] = {};
}
root = root[parts[i]];
}
return root;
};
/* Find and replaces a string (search) to another string (replacement) in
* given string (str).
* Example:
* abp.utils.replaceAll('This is a test string', 'is', 'X') = 'ThX X a test string'
************************************************************/
abp.utils.replaceAll = function (str, search, replacement) {
var fix = search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
return str.replace(new RegExp(fix, 'g'), replacement);
};
/* Formats a string just like string.format in C#.
* Example:
* abp.utils.formatString('Hello {0}','Tuana') = 'Hello Tuana'
************************************************************/
abp.utils.formatString = function () {
if (arguments.length < 1) {
return null;
}
var str = arguments[0];
for (var i = 1; i < arguments.length; i++) {
var placeHolder = '{' + (i - 1) + '}';
str = abp.utils.replaceAll(str, placeHolder, arguments[i]);
}
return str;
};
abp.utils.toPascalCase = function (str) {
if (!str || !str.length) {
return str;
}
if (str.length === 1) {
return str.charAt(0).toUpperCase();
}
return str.charAt(0).toUpperCase() + str.substr(1);
}
abp.utils.toCamelCase = function (str) {
if (!str || !str.length) {
return str;
}
if (str.length === 1) {
return str.charAt(0).toLowerCase();
}
return str.charAt(0).toLowerCase() + str.substr(1);
}
abp.utils.truncateString = function (str, maxLength) {
if (!str || !str.length || str.length <= maxLength) {
return str;
}
return str.substr(0, maxLength);
};
abp.utils.truncateStringWithPostfix = function (str, maxLength, postfix) {
postfix = postfix || '...';
if (!str || !str.length || str.length <= maxLength) {
return str;
}
if (maxLength <= postfix.length) {
return postfix.substr(0, maxLength);
}
return str.substr(0, maxLength - postfix.length) + postfix;
};
abp.utils.isFunction = function (obj) {
return !!(obj && obj.constructor && obj.call && obj.apply);
};
/**
* parameterInfos should be an array of { name, value } objects
* where name is query string parameter name and value is it's value.
* includeQuestionMark is true by default.
*/
abp.utils.buildQueryString = function (parameterInfos, includeQuestionMark) {
if (includeQuestionMark === undefined) {
includeQuestionMark = true;
}
var qs = '';
function addSeperator() {
if (!qs.length) {
if (includeQuestionMark) {
qs = qs + '?';
}
} else {
qs = qs + '&';
}
}
for (var i = 0; i < parameterInfos.length; ++i) {
var parameterInfo = parameterInfos[i];
if (parameterInfo.value === undefined) {
continue;
}
if (parameterInfo.value === null) {
parameterInfo.value = '';
}
addSeperator();
if (parameterInfo.value.toJSON && typeof parameterInfo.value.toJSON === "function") {
qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value.toJSON());
} else if (Array.isArray(parameterInfo.value) && parameterInfo.value.length) {
for (var j = 0; j < parameterInfo.value.length; j++) {
if (j > 0) {
addSeperator();
}
qs = qs + parameterInfo.name + '[' + j + ']=' + encodeURIComponent(parameterInfo.value[j]);
}
} else {
qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value);
}
}
return qs;
}
/**
* Sets a cookie value for given key.
* This is a simple implementation created to be used by ABP.
* Please use a complete cookie library if you need.
* @param {string} key
* @param {string} value
* @param {Date} expireDate (optional). If not specified the cookie will expire at the end of session.
* @param {string} path (optional)
*/
abp.utils.setCookieValue = function (key, value, expireDate, path) {
var cookieValue = encodeURIComponent(key) + '=';
if (value) {
cookieValue = cookieValue + encodeURIComponent(value);
}
if (expireDate) {
cookieValue = cookieValue + "; expires=" + expireDate.toUTCString();
}
if (path) {
cookieValue = cookieValue + "; path=" + path;
}
document.cookie = cookieValue;
};
/**
* Gets a cookie with given key.
* This is a simple implementation created to be used by ABP.
* Please use a complete cookie library if you need.
* @param {string} key
* @returns {string} Cookie value or null
*/
abp.utils.getCookieValue = function (key) {
var equalities = document.cookie.split('; ');
for (var i = 0; i < equalities.length; i++) {
if (!equalities[i]) {
continue;
}
var splitted = equalities[i].split('=');
if (splitted.length != 2) {
continue;
}
if (decodeURIComponent(splitted[0]) === key) {
return decodeURIComponent(splitted[1] || '');
}
}
return null;
};
/**
* Deletes cookie for given key.
* This is a simple implementation created to be used by ABP.
* Please use a complete cookie library if you need.
* @param {string} key
* @param {string} path (optional)
*/
abp.utils.deleteCookie = function (key, path) {
var cookieValue = encodeURIComponent(key) + '=';
cookieValue = cookieValue + "; expires=" + (new Date(new Date().getTime() - 86400000)).toUTCString();
if (path) {
cookieValue = cookieValue + "; path=" + path;
}
document.cookie = cookieValue;
}
/**
* Escape HTML to help prevent XSS attacks.
*/
abp.utils.htmlEscape = function (html) {
return typeof html === 'string' ? html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') : html;
}
/* SECURITY ***************************************/
abp.security = abp.security || {};
abp.security.antiForgery = abp.security.antiForgery || {};
abp.security.antiForgery.tokenCookieName = 'XSRF-TOKEN';
abp.security.antiForgery.tokenHeaderName = 'RequestVerificationToken';
abp.security.antiForgery.getToken = function () {
return abp.utils.getCookieValue(abp.security.antiForgery.tokenCookieName);
};
/* CLOCK *****************************************/
abp.clock = abp.clock || {};
abp.clock.kind = 'Unspecified';
abp.clock.supportsMultipleTimezone = function () {
return abp.clock.kind === 'Utc';
};
var toLocal = function (date) {
return new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds()
);
};
var toUtc = function (date) {
return Date.UTC(
date.getUTCFullYear(),
date.getUTCMonth(),
date.getUTCDate(),
date.getUTCHours(),
date.getUTCMinutes(),
date.getUTCSeconds(),
date.getUTCMilliseconds()
);
};
abp.clock.now = function () {
if (abp.clock.kind === 'Utc') {
return toUtc(new Date());
}
return new Date();
};
abp.clock.normalize = function (date) {
var kind = abp.clock.kind;
if (kind === 'Unspecified') {
return date;
}
if (kind === 'Local') {
return toLocal(date);
}
if (kind === 'Utc') {
return toUtc(date);
}
};
/* FEATURES *************************************************/
abp.features = abp.features || {};
abp.features.values = abp.features.values || {};
abp.features.isEnabled = function(name){
var value = abp.features.get(name);
return value == 'true' || value == 'True';
}
abp.features.get = function (name) {
return abp.features.values[name];
};
/* GLOBAL FEATURES *************************************************/
abp.globalFeatures = abp.globalFeatures || {};
abp.globalFeatures.enabledFeatures = abp.globalFeatures.enabledFeatures || [];
abp.globalFeatures.isEnabled = function(name){
return abp.globalFeatures.enabledFeatures.indexOf(name) != -1;
}
})();

411
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/jquery/abp.jquery.js

@ -1,411 +0,0 @@
var abp = abp || {};
(function($) {
if (!$) {
throw "abp/jquery library requires the jquery library included to the page!";
}
// ABP CORE OVERRIDES /////////////////////////////////////////////////////
abp.message._showMessage = function (message, title) {
alert((title || '') + ' ' + message);
return $.Deferred(function ($dfd) {
$dfd.resolve();
});
};
abp.message.confirm = function (message, titleOrCallback, callback) {
if (titleOrCallback && !(typeof titleOrCallback == 'string')) {
callback = titleOrCallback;
}
var result = confirm(message);
callback && callback(result);
return $.Deferred(function ($dfd) {
$dfd.resolve(result);
});
};
abp.utils.isFunction = function (obj) {
return $.isFunction(obj);
};
// JQUERY EXTENSIONS //////////////////////////////////////////////////////
$.fn.findWithSelf = function (selector) {
return this.filter(selector).add(this.find(selector));
};
// DOM ////////////////////////////////////////////////////////////////////
abp.dom = abp.dom || {};
abp.dom.onNodeAdded = function (callback) {
abp.event.on('abp.dom.nodeAdded', callback);
};
abp.dom.onNodeRemoved = function (callback) {
abp.event.on('abp.dom.nodeRemoved', callback);
};
var mutationObserverCallback = function (mutationsList) {
for (var i = 0; i < mutationsList.length; i++) {
var mutation = mutationsList[i];
if (mutation.type === 'childList') {
if (mutation.addedNodes && mutation.removedNodes.length) {
for (var k = 0; k < mutation.removedNodes.length; k++) {
abp.event.trigger(
'abp.dom.nodeRemoved',
{
$el: $(mutation.removedNodes[k])
}
);
}
}
if (mutation.addedNodes && mutation.addedNodes.length) {
for (var j = 0; j < mutation.addedNodes.length; j++) {
abp.event.trigger(
'abp.dom.nodeAdded',
{
$el: $(mutation.addedNodes[j])
}
);
}
}
}
}
};
$(function(){
new MutationObserver(mutationObserverCallback).observe(
$('body')[0],
{
subtree: true,
childList: true
}
);
});
// AJAX ///////////////////////////////////////////////////////////////////
abp.ajax = function (userOptions) {
userOptions = userOptions || {};
var options = $.extend(true, {}, abp.ajax.defaultOpts, userOptions);
options.success = undefined;
options.error = undefined;
var xhr = null;
var promise = $.Deferred(function ($dfd) {
xhr = $.ajax(options)
.done(function (data, textStatus, jqXHR) {
$dfd.resolve(data);
userOptions.success && userOptions.success(data);
}).fail(function (jqXHR) {
if(jqXHR.statusText === 'abort') {
//ajax request is abort, ignore error handle.
return;
}
if (jqXHR.getResponseHeader('_AbpErrorFormat') === 'true') {
abp.ajax.handleAbpErrorResponse(jqXHR, userOptions, $dfd);
} else {
abp.ajax.handleNonAbpErrorResponse(jqXHR, userOptions, $dfd);
}
});
}).promise();
promise['jqXHR'] = xhr;
return promise;
};
$.extend(abp.ajax, {
defaultOpts: {
dataType: 'json',
type: 'POST',
contentType: 'application/json',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
},
defaultError: {
message: 'An error has occurred!',
details: 'Error detail not sent by server.'
},
defaultError401: {
message: 'You are not authenticated!',
details: 'You should be authenticated (sign in) in order to perform this operation.'
},
defaultError403: {
message: 'You are not authorized!',
details: 'You are not allowed to perform this operation.'
},
defaultError404: {
message: 'Resource not found!',
details: 'The resource requested could not found on the server.'
},
logError: function (error) {
abp.log.error(error);
},
showError: function (error) {
if (error.details) {
return abp.message.error(error.details, error.message);
} else {
return abp.message.error(error.message || abp.ajax.defaultError.message);
}
},
handleTargetUrl: function (targetUrl) {
if (!targetUrl) {
location.href = abp.appPath;
} else {
location.href = targetUrl;
}
},
handleErrorStatusCode: function (status) {
switch (status) {
case 401:
abp.ajax.handleUnAuthorizedRequest(
abp.ajax.showError(abp.ajax.defaultError401),
abp.appPath
);
break;
case 403:
abp.ajax.showError(abp.ajax.defaultError403);
break;
case 404:
abp.ajax.showError(abp.ajax.defaultError404);
break;
default:
abp.ajax.showError(abp.ajax.defaultError);
break;
}
},
handleNonAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
if (userOptions.abpHandleError !== false) {
abp.ajax.handleErrorStatusCode(jqXHR.status);
}
$dfd.reject.apply(this, arguments);
userOptions.error && userOptions.error.apply(this, arguments);
},
handleAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
var messagePromise = null;
var responseJSON = jqXHR.responseJSON ? jqXHR.responseJSON : JSON.parse(jqXHR.responseText);
if (userOptions.abpHandleError !== false) {
messagePromise = abp.ajax.showError(responseJSON.error);
}
abp.ajax.logError(responseJSON.error);
$dfd && $dfd.reject(responseJSON.error, jqXHR);
userOptions.error && userOptions.error(responseJSON.error, jqXHR);
if (jqXHR.status === 401 && userOptions.abpHandleError !== false) {
abp.ajax.handleUnAuthorizedRequest(messagePromise);
}
},
handleUnAuthorizedRequest: function (messagePromise, targetUrl) {
if (messagePromise) {
messagePromise.done(function () {
abp.ajax.handleTargetUrl(targetUrl);
});
} else {
abp.ajax.handleTargetUrl(targetUrl);
}
},
blockUI: function (options) {
if (options.blockUI) {
if (options.blockUI === true) { //block whole page
abp.ui.setBusy();
} else { //block an element
abp.ui.setBusy(options.blockUI);
}
}
},
unblockUI: function (options) {
if (options.blockUI) {
if (options.blockUI === true) { //unblock whole page
abp.ui.clearBusy();
} else { //unblock an element
abp.ui.clearBusy(options.blockUI);
}
}
},
ajaxSendHandler: function (event, request, settings) {
var token = abp.security.antiForgery.getToken();
if (!token) {
return;
}
if (!settings.headers || settings.headers[abp.security.antiForgery.tokenHeaderName] === undefined) {
request.setRequestHeader(abp.security.antiForgery.tokenHeaderName, token);
}
}
});
$(document).ajaxSend(function (event, request, settings) {
return abp.ajax.ajaxSendHandler(event, request, settings);
});
abp.event.on('abp.configurationInitialized', function () {
var l = abp.localization.getResource('AbpUi');
abp.ajax.defaultError.message = l('DefaultErrorMessage');
abp.ajax.defaultError.details = l('DefaultErrorMessageDetail');
abp.ajax.defaultError401.message = l('DefaultErrorMessage401');
abp.ajax.defaultError401.details = l('DefaultErrorMessage401Detail');
abp.ajax.defaultError403.message = l('DefaultErrorMessage403');
abp.ajax.defaultError403.details = l('DefaultErrorMessage403Detail');
abp.ajax.defaultError404.message = l('DefaultErrorMessage404');
abp.ajax.defaultError404.details = l('DefaultErrorMessage404Detail');
});
// RESOURCE LOADER ////////////////////////////////////////////////////////
/* UrlStates enum */
var UrlStates = {
LOADING: 'LOADING',
LOADED: 'LOADED',
FAILED: 'FAILED'
};
/* UrlInfo class */
function UrlInfo(url) {
this.url = url;
this.state = UrlStates.LOADING;
this.loadCallbacks = [];
this.failCallbacks = [];
}
UrlInfo.prototype.succeed = function () {
this.state = UrlStates.LOADED;
for (var i = 0; i < this.loadCallbacks.length; i++) {
this.loadCallbacks[i]();
}
};
UrlInfo.prototype.failed = function () {
this.state = UrlStates.FAILED;
for (var i = 0; i < this.failCallbacks.length; i++) {
this.failCallbacks[i]();
}
};
UrlInfo.prototype.handleCallbacks = function (loadCallback, failCallback) {
switch (this.state) {
case UrlStates.LOADED:
loadCallback && loadCallback();
break;
case UrlStates.FAILED:
failCallback && failCallback();
break;
case UrlStates.LOADING:
this.addCallbacks(loadCallback, failCallback);
break;
}
};
UrlInfo.prototype.addCallbacks = function (loadCallback, failCallback) {
loadCallback && this.loadCallbacks.push(loadCallback);
failCallback && this.failCallbacks.push(failCallback);
};
/* ResourceLoader API */
abp.ResourceLoader = (function () {
var _urlInfos = {};
function getCacheKey(url) {
return url;
}
function appendTimeToUrl(url) {
if (url.indexOf('?') < 0) {
url += '?';
} else {
url += '&';
}
url += '_=' + new Date().getTime();
return url;
}
var _loadFromUrl = function (url, loadCallback, failCallback, serverLoader) {
var cacheKey = getCacheKey(url);
var urlInfo = _urlInfos[cacheKey];
if (urlInfo) {
urlInfo.handleCallbacks(loadCallback, failCallback);
return;
}
_urlInfos[cacheKey] = urlInfo = new UrlInfo(url);
urlInfo.addCallbacks(loadCallback, failCallback);
serverLoader(urlInfo);
};
var _loadScript = function (url, loadCallback, failCallback) {
var nonce = document.body.nonce || document.body.getAttribute('nonce');
_loadFromUrl(url, loadCallback, failCallback, function (urlInfo) {
$.get({
url: url,
dataType: 'text'
})
.done(function (script) {
if(nonce){
$.globalEval(script, { nonce: nonce});
}else{
$.globalEval(script);
}
urlInfo.succeed();
})
.fail(function () {
urlInfo.failed();
});
});
};
var _loadStyle = function (url) {
_loadFromUrl(url, undefined, undefined, function (urlInfo) {
$('<link/>', {
rel: 'stylesheet',
type: 'text/css',
href: appendTimeToUrl(url)
}).appendTo('head');
});
};
return {
loadScript: _loadScript,
loadStyle: _loadStyle
}
})();
})(jQuery);

46
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/luxon/abp.luxon.js

@ -1,46 +0,0 @@
var abp = abp || {};
(function () {
if (!luxon) {
throw "abp/luxon library requires the luxon library included to the page!";
}
/* TIMING *************************************************/
abp.timing = abp.timing || {};
var setObjectValue = function (obj, property, value) {
if (typeof property === "string") {
property = property.split('.');
}
if (property.length > 1) {
var p = property.shift();
setObjectValue(obj[p], property, value);
} else {
obj[property[0]] = value;
}
}
var getObjectValue = function (obj, property) {
return property.split('.').reduce((a, v) => a[v], obj)
}
abp.timing.convertFieldsToIsoDate = function (form, fields) {
for (var field of fields) {
var dateTime = luxon.DateTime
.fromFormat(
getObjectValue(form, field),
abp.localization.currentCulture.dateTimeFormat.shortDatePattern,
{locale: abp.localization.currentCulture.cultureName}
);
if (!dateTime.invalid) {
setObjectValue(form, field, dateTime.toFormat("yyyy-MM-dd HH:mm:ss"))
}
}
return form;
}
})(jQuery);

694
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js

@ -1,694 +0,0 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('just-compare')) :
typeof define === 'function' && define.amd ? define('@abp/utils', ['exports', 'just-compare'], factory) :
(global = global || self, factory((global.abp = global.abp || {}, global.abp.utils = global.abp.utils || {}, global.abp.utils.common = {}), global.compare));
}(this, (function (exports, compare) { 'use strict';
compare = compare && Object.prototype.hasOwnProperty.call(compare, 'default') ? compare['default'] : compare;
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (b.hasOwnProperty(p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if (d = decorators[i])
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); };
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
return Reflect.metadata(metadataKey, metadataValue);
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try {
step(generator.next(value));
}
catch (e) {
reject(e);
} }
function rejected(value) { try {
step(generator["throw"](value));
}
catch (e) {
reject(e);
} }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function () { if (t[0] & 1)
throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f)
throw new TypeError("Generator is already executing.");
while (_)
try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
return t;
if (y = 0, t)
op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return { value: op[1], done: false };
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2])
_.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
}
catch (e) {
op = [6, e];
y = 0;
}
finally {
f = t = 0;
}
if (op[0] & 5)
throw op[1];
return { value: op[0] ? op[1] : void 0, done: true };
}
}
var __createBinding = Object.create ? (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
}) : (function (o, m, k, k2) {
if (k2 === undefined)
k2 = k;
o[k2] = m[k];
});
function __exportStar(m, exports) {
for (var p in m)
if (p !== "default" && !exports.hasOwnProperty(p))
__createBinding(exports, m, p);
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m)
return m.call(o);
if (o && typeof o.length === "number")
return {
next: function () {
if (o && i >= o.length)
o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
;
function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n])
i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try {
step(g[n](v));
}
catch (e) {
settle(q[0][3], e);
} }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length)
resume(q[0][0], q[0][1]); }
}
function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
}
function __asyncValues(o) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
}
function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) {
Object.defineProperty(cooked, "raw", { value: raw });
}
else {
cooked.raw = raw;
}
return cooked;
}
;
var __setModuleDefault = Object.create ? (function (o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function (o, v) {
o["default"] = v;
};
function __importStar(mod) {
if (mod && mod.__esModule)
return mod;
var result = {};
if (mod != null)
for (var k in mod)
if (Object.hasOwnProperty.call(mod, k))
__createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
}
function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
}
function __classPrivateFieldGet(receiver, privateMap) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver);
}
function __classPrivateFieldSet(receiver, privateMap, value) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
privateMap.set(receiver, value);
return value;
}
var ListNode = /** @class */ (function () {
function ListNode(value) {
this.value = value;
}
return ListNode;
}());
var LinkedList = /** @class */ (function () {
function LinkedList() {
this.size = 0;
}
Object.defineProperty(LinkedList.prototype, "head", {
get: function () {
return this.first;
},
enumerable: false,
configurable: true
});
Object.defineProperty(LinkedList.prototype, "tail", {
get: function () {
return this.last;
},
enumerable: false,
configurable: true
});
Object.defineProperty(LinkedList.prototype, "length", {
get: function () {
return this.size;
},
enumerable: false,
configurable: true
});
LinkedList.prototype.attach = function (value, previousNode, nextNode) {
if (!previousNode)
return this.addHead(value);
if (!nextNode)
return this.addTail(value);
var node = new ListNode(value);
node.previous = previousNode;
previousNode.next = node;
node.next = nextNode;
nextNode.previous = node;
this.size++;
return node;
};
LinkedList.prototype.attachMany = function (values, previousNode, nextNode) {
if (!values.length)
return [];
if (!previousNode)
return this.addManyHead(values);
if (!nextNode)
return this.addManyTail(values);
var list = new LinkedList();
list.addManyTail(values);
list.first.previous = previousNode;
previousNode.next = list.first;
list.last.next = nextNode;
nextNode.previous = list.last;
this.size += values.length;
return list.toNodeArray();
};
LinkedList.prototype.detach = function (node) {
if (!node.previous)
return this.dropHead();
if (!node.next)
return this.dropTail();
node.previous.next = node.next;
node.next.previous = node.previous;
this.size--;
return node;
};
LinkedList.prototype.add = function (value) {
var _this = this;
return {
after: function () {
var _a;
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
return (_a = _this.addAfter).call.apply(_a, __spread([_this, value], params));
},
before: function () {
var _a;
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
return (_a = _this.addBefore).call.apply(_a, __spread([_this, value], params));
},
byIndex: function (position) { return _this.addByIndex(value, position); },
head: function () { return _this.addHead(value); },
tail: function () { return _this.addTail(value); },
};
};
LinkedList.prototype.addMany = function (values) {
var _this = this;
return {
after: function () {
var _a;
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
return (_a = _this.addManyAfter).call.apply(_a, __spread([_this, values], params));
},
before: function () {
var _a;
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
return (_a = _this.addManyBefore).call.apply(_a, __spread([_this, values], params));
},
byIndex: function (position) { return _this.addManyByIndex(values, position); },
head: function () { return _this.addManyHead(values); },
tail: function () { return _this.addManyTail(values); },
};
};
LinkedList.prototype.addAfter = function (value, previousValue, compareFn) {
if (compareFn === void 0) { compareFn = compare; }
var previous = this.find(function (node) { return compareFn(node.value, previousValue); });
return previous ? this.attach(value, previous, previous.next) : this.addTail(value);
};
LinkedList.prototype.addBefore = function (value, nextValue, compareFn) {
if (compareFn === void 0) { compareFn = compare; }
var next = this.find(function (node) { return compareFn(node.value, nextValue); });
return next ? this.attach(value, next.previous, next) : this.addHead(value);
};
LinkedList.prototype.addByIndex = function (value, position) {
if (position < 0)
position += this.size;
else if (position >= this.size)
return this.addTail(value);
if (position <= 0)
return this.addHead(value);
var next = this.get(position);
return this.attach(value, next.previous, next);
};
LinkedList.prototype.addHead = function (value) {
var node = new ListNode(value);
node.next = this.first;
if (this.first)
this.first.previous = node;
else
this.last = node;
this.first = node;
this.size++;
return node;
};
LinkedList.prototype.addTail = function (value) {
var node = new ListNode(value);
if (this.first) {
node.previous = this.last;
this.last.next = node;
this.last = node;
}
else {
this.first = node;
this.last = node;
}
this.size++;
return node;
};
LinkedList.prototype.addManyAfter = function (values, previousValue, compareFn) {
if (compareFn === void 0) { compareFn = compare; }
var previous = this.find(function (node) { return compareFn(node.value, previousValue); });
return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values);
};
LinkedList.prototype.addManyBefore = function (values, nextValue, compareFn) {
if (compareFn === void 0) { compareFn = compare; }
var next = this.find(function (node) { return compareFn(node.value, nextValue); });
return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values);
};
LinkedList.prototype.addManyByIndex = function (values, position) {
if (position < 0)
position += this.size;
if (position <= 0)
return this.addManyHead(values);
if (position >= this.size)
return this.addManyTail(values);
var next = this.get(position);
return this.attachMany(values, next.previous, next);
};
LinkedList.prototype.addManyHead = function (values) {
var _this = this;
return values.reduceRight(function (nodes, value) {
nodes.unshift(_this.addHead(value));
return nodes;
}, []);
};
LinkedList.prototype.addManyTail = function (values) {
var _this = this;
return values.map(function (value) { return _this.addTail(value); });
};
LinkedList.prototype.drop = function () {
var _this = this;
return {
byIndex: function (position) { return _this.dropByIndex(position); },
byValue: function () {
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
return _this.dropByValue.apply(_this, params);
},
byValueAll: function () {
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
return _this.dropByValueAll.apply(_this, params);
},
head: function () { return _this.dropHead(); },
tail: function () { return _this.dropTail(); },
};
};
LinkedList.prototype.dropMany = function (count) {
var _this = this;
return {
byIndex: function (position) { return _this.dropManyByIndex(count, position); },
head: function () { return _this.dropManyHead(count); },
tail: function () { return _this.dropManyTail(count); },
};
};
LinkedList.prototype.dropByIndex = function (position) {
if (position < 0)
position += this.size;
var current = this.get(position);
return current ? this.detach(current) : undefined;
};
LinkedList.prototype.dropByValue = function (value, compareFn) {
if (compareFn === void 0) { compareFn = compare; }
var position = this.findIndex(function (node) { return compareFn(node.value, value); });
return position < 0 ? undefined : this.dropByIndex(position);
};
LinkedList.prototype.dropByValueAll = function (value, compareFn) {
if (compareFn === void 0) { compareFn = compare; }
var dropped = [];
for (var current = this.first, position = 0; current; position++, current = current.next) {
if (compareFn(current.value, value)) {
dropped.push(this.dropByIndex(position - dropped.length));
}
}
return dropped;
};
LinkedList.prototype.dropHead = function () {
var head = this.first;
if (head) {
this.first = head.next;
if (this.first)
this.first.previous = undefined;
else
this.last = undefined;
this.size--;
return head;
}
return undefined;
};
LinkedList.prototype.dropTail = function () {
var tail = this.last;
if (tail) {
this.last = tail.previous;
if (this.last)
this.last.next = undefined;
else
this.first = undefined;
this.size--;
return tail;
}
return undefined;
};
LinkedList.prototype.dropManyByIndex = function (count, position) {
if (count <= 0)
return [];
if (position < 0)
position = Math.max(position + this.size, 0);
else if (position >= this.size)
return [];
count = Math.min(count, this.size - position);
var dropped = [];
while (count--) {
var current = this.get(position);
dropped.push(this.detach(current));
}
return dropped;
};
LinkedList.prototype.dropManyHead = function (count) {
if (count <= 0)
return [];
count = Math.min(count, this.size);
var dropped = [];
while (count--)
dropped.unshift(this.dropHead());
return dropped;
};
LinkedList.prototype.dropManyTail = function (count) {
if (count <= 0)
return [];
count = Math.min(count, this.size);
var dropped = [];
while (count--)
dropped.push(this.dropTail());
return dropped;
};
LinkedList.prototype.find = function (predicate) {
for (var current = this.first, position = 0; current; position++, current = current.next) {
if (predicate(current, position, this))
return current;
}
return undefined;
};
LinkedList.prototype.findIndex = function (predicate) {
for (var current = this.first, position = 0; current; position++, current = current.next) {
if (predicate(current, position, this))
return position;
}
return -1;
};
LinkedList.prototype.forEach = function (iteratorFn) {
for (var node = this.first, position = 0; node; position++, node = node.next) {
iteratorFn(node, position, this);
}
};
LinkedList.prototype.get = function (position) {
return this.find(function (_, index) { return position === index; });
};
LinkedList.prototype.indexOf = function (value, compareFn) {
if (compareFn === void 0) { compareFn = compare; }
return this.findIndex(function (node) { return compareFn(node.value, value); });
};
LinkedList.prototype.toArray = function () {
var array = new Array(this.size);
this.forEach(function (node, index) { return (array[index] = node.value); });
return array;
};
LinkedList.prototype.toNodeArray = function () {
var array = new Array(this.size);
this.forEach(function (node, index) { return (array[index] = node); });
return array;
};
LinkedList.prototype.toString = function (mapperFn) {
if (mapperFn === void 0) { mapperFn = JSON.stringify; }
return this.toArray()
.map(function (value) { return mapperFn(value); })
.join(' <-> ');
};
// Cannot use Generator type because of ng-packagr
LinkedList.prototype[Symbol.iterator] = function () {
var node, position;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
node = this.first, position = 0;
_a.label = 1;
case 1:
if (!node) return [3 /*break*/, 4];
return [4 /*yield*/, node.value];
case 2:
_a.sent();
_a.label = 3;
case 3:
position++, node = node.next;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
};
return LinkedList;
}());
/*
* Public API Surface of utils
*/
/**
* Generated bundle index. Do not edit.
*/
exports.LinkedList = LinkedList;
exports.ListNode = ListNode;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=abp-utils.umd.js.map

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.js.map

File diff suppressed because one or more lines are too long

2
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js

File diff suppressed because one or more lines are too long

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/abp/utils/abp-utils.umd.min.js.map

File diff suppressed because one or more lines are too long

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.css.map

File diff suppressed because one or more lines are too long

7
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.css

File diff suppressed because one or more lines are too long

8
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/bootstrap-datepicker.min.js

File diff suppressed because one or more lines are too long

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker-en-CA.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates["en-CA"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:0,format:"yyyy-mm-dd"},a.fn.datepicker.deprecated("This filename doesn't follow the convention, use bootstrap-datepicker.en-CA.js instead.")}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-DZ.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates["ar-DZ"]={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0,monthsTitle:"أشهر",clear:"إزالة",format:"yyyy/mm/dd",weekStart:0}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar-tn.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates["ar-tn"]={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ar.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.ar={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.az.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1,clear:"Təmizlə",monthsTitle:"Aylar"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bg.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.bg={days:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"],daysShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб"],daysMin:["Н","П","В","С","Ч","П","С"],months:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Ян","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],today:"днес"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bm.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.bm={days:["Kari","Ntɛnɛn","Tarata","Araba","Alamisa","Juma","Sibiri"],daysShort:["Kar","Ntɛ","Tar","Ara","Ala","Jum","Sib"],daysMin:["Ka","Nt","Ta","Ar","Al","Ju","Si"],months:["Zanwuyekalo","Fewuruyekalo","Marisikalo","Awirilikalo","Mɛkalo","Zuwɛnkalo","Zuluyekalo","Utikalo","Sɛtanburukalo","ɔkutɔburukalo","Nowanburukalo","Desanburukalo"],monthsShort:["Zan","Few","Mar","Awi","Mɛ","Zuw","Zul","Uti","Sɛt","ɔku","Now","Des"],today:"Bi",monthsTitle:"Kalo",clear:"Ka jɔsi",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bn.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.bn={days:["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],daysShort:["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],daysMin:["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],months:["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],monthsShort:["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],today:"আজ",monthsTitle:"মাস",clear:"পরিষ্কার",weekStart:0,format:"mm/dd/yyyy"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.br.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.br={days:["Sul","Lun","Meurzh","Merc'her","Yaou","Gwener","Sadorn"],daysShort:["Sul","Lun","Meu.","Mer.","Yao.","Gwe.","Sad."],daysMin:["Su","L","Meu","Mer","Y","G","Sa"],months:["Genver","C'hwevrer","Meurzh","Ebrel","Mae","Mezheven","Gouere","Eost","Gwengolo","Here","Du","Kerzu"],monthsShort:["Genv.","C'hw.","Meur.","Ebre.","Mae","Mezh.","Goue.","Eost","Gwen.","Here","Du","Kerz."],today:"Hiziv",monthsTitle:"Miz",clear:"Dilemel",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.bs.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.bs={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Juni","Juli","August","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.ca.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.ca={days:["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],daysShort:["dg.","dl.","dt.","dc.","dj.","dv.","ds."],daysMin:["dg","dl","dt","dc","dj","dv","ds"],months:["gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],monthsShort:["gen.","febr.","març","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],today:"Avui",monthsTitle:"Mesos",clear:"Esborra",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cs.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob"],daysMin:["Ne","Po","Út","St","Čt","Pá","So"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",monthsTitle:"Měsíc",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.cy.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.cy={days:["Sul","Llun","Mawrth","Mercher","Iau","Gwener","Sadwrn"],daysShort:["Sul","Llu","Maw","Mer","Iau","Gwe","Sad"],daysMin:["Su","Ll","Ma","Me","Ia","Gwe","Sa"],months:["Ionawr","Chewfror","Mawrth","Ebrill","Mai","Mehefin","Gorfennaf","Awst","Medi","Hydref","Tachwedd","Rhagfyr"],monthsShort:["Ion","Chw","Maw","Ebr","Mai","Meh","Gor","Aws","Med","Hyd","Tach","Rha"],today:"Heddiw"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.da.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.da={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"I Dag",weekStart:1,clear:"Nulstil",format:"dd/mm/yyyy",monthsTitle:"Måneder"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["So","Mo","Di","Mi","Do","Fr","Sa"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",monthsTitle:"Monate",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);

1
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/wwwroot/libs/bootstrap-datepicker/locales/bootstrap-datepicker.el.min.js

@ -1 +0,0 @@
!function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery);

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save