Browse Source

Merge branch 'dev' into salihozkara/auto-renewal

pull/18729/head
Gizem Mutu Kurt 3 years ago
parent
commit
6491a1485b
  1. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ar.json
  2. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/cs.json
  3. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/de.json
  4. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json
  5. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json
  6. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json
  7. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fi.json
  8. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/fr.json
  9. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hi.json
  10. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hr.json
  11. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hu.json
  12. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/is.json
  13. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/it.json
  14. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/nl.json
  15. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pl-PL.json
  16. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/pt-BR.json
  17. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ro-RO.json
  18. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ru.json
  19. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sk.json
  20. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/sl.json
  21. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json
  22. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/vi.json
  23. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json
  24. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json
  25. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json
  26. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json
  27. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json
  28. 32
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
  29. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json
  30. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json
  31. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json
  32. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json
  33. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json
  34. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json
  35. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json
  36. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json
  37. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json
  38. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json
  39. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json
  40. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json
  41. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json
  42. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json
  43. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json
  44. 30
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json
  45. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json
  46. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
  47. 28
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json
  48. 1
      docs/en/Audit-Logging.md
  49. 4
      docs/en/Startup-Templates/Application.md
  50. 2
      docs/en/Startup-Templates/Module.md
  51. 2
      docs/en/Testing.md
  52. 2
      docs/en/Tutorials/Part-4.md
  53. 2
      docs/en/UI/Angular/Permission-Management.md
  54. 4
      docs/en/UI/Blazor/Basic-Theme.md
  55. 2
      docs/pt-BR/Startup-Templates/Application.md
  56. 2
      docs/pt-BR/Startup-Templates/Module.md
  57. 4
      docs/zh-Hans/Startup-Templates/Application.md
  58. 2
      docs/zh-Hans/Startup-Templates/Module.md
  59. 2
      docs/zh-Hans/Testing.md
  60. 114
      docs/zh-Hans/Tutorials/Part-10.md
  61. 78
      docs/zh-Hans/Tutorials/Part-4.md
  62. 139
      docs/zh-Hans/Tutorials/Part-8.md
  63. 46
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs
  64. 52
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs
  65. 5
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs
  66. 19
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelperService.cs
  67. 42
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js
  68. 6
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs
  69. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  70. 89
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/RecreateInitialMigrationCommand.cs
  71. 35
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs
  72. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs
  73. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
  74. 31
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs
  75. 24
      framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs
  76. 255
      framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs
  77. 2
      latest-versions.json
  78. 26
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Navigation/BasicThemeNavigationExtensions.cs
  79. 3
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor
  80. 3
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor
  81. 41
      modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/Default.cshtml
  82. 45
      modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/_MenuItem.cshtml
  83. 2352
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20230504122708_Initial.Designer.cs
  84. 1334
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20230504122708_Initial.cs
  85. 2349
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs
  86. 10
      modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20240108043816_Initial.Designer.cs
  87. 4
      modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20240108043816_Initial.cs
  88. 8
      modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs
  89. 5
      modules/permission-management/src/Volo.Abp.PermissionManagement.Application/Volo/Abp/PermissionManagement/PermissionAppService.cs
  90. 34
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs
  91. 16
      modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs
  92. 13
      modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionDefinitionProvider.cs
  93. 22
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/20240108025904_Initial.Designer.cs
  94. 24
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/20240108025904_Initial.cs
  95. 20
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs
  96. 4
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/SettingDefinitionRecordConsts.cs
  97. 2
      npm/packs/font-awesome/package.json
  98. 2
      npm/publish-mvc.ps1
  99. 10
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240108044306_Initial.Designer.cs
  100. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240108044306_Initial.cs

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

@ -229,6 +229,7 @@
"ManageAccount": "إدارة الحساب",
"CommunityProfile": "ملف تعريف المجتمع",
"BlogProfile": "الملف الشخصي للمدونة",
"Tickets": "التذاكر"
"Tickets": "التذاكر",
"DisplayName:CommunityIndexPagePoll": "استطلاع"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Spravovat účet",
"CommunityProfile": "Profil komunity",
"BlogProfile": "Profil blogu",
"Tickets": "Vstupenky"
"Tickets": "Vstupenky",
"DisplayName:CommunityIndexPagePoll": "Anketa na stránce s indexem komunity"
}
}

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

@ -228,6 +228,7 @@
"ManageAccount": "Konto verwalten",
"CommunityProfile": "Community-Profil",
"BlogProfile": "Blog-Profil",
"Tickets": "Tickets"
"Tickets": "Tickets",
"DisplayName:CommunityIndexPagePoll": "Community-Indexseite-Umfrage"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en-GB.json

@ -33,6 +33,7 @@
"Samples": "Samples",
"FreeDDDBook": "Free DDD E-book",
"New": "New",
"Volo.AbpIo.Domain:020005": "License extend year can not be lower than {MinExtendLicenseYear} year and greater than {MaxExtendLicenseYear} years "
"Volo.AbpIo.Domain:020005": "License extend year can not be lower than {MinExtendLicenseYear} year and greater than {MaxExtendLicenseYear} years ",
"DisplayName:CommunityIndexPagePoll": "Community Index Page Poll"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/en.json

@ -235,6 +235,7 @@
"Resources": "Resources",
"Video Courses": "Video Courses",
"Packages": "Packages",
"Trainings": "Trainings"
"Trainings": "Trainings",
"DisplayName:CommunityIndexPagePoll": "Community Index Page Poll"
}
}

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

@ -228,6 +228,7 @@
"ManageAccount": "Administrar cuenta",
"CommunityProfile": "Perfil de la comunidad",
"BlogProfile": "Perfil del blog",
"Tickets": "Entradas"
"Tickets": "Entradas",
"DisplayName:CommunityIndexPagePoll": "Encuesta de la página de índice de la comunidad"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Hallitse tiliä",
"CommunityProfile": "Yhteisön profiili",
"BlogProfile": "Blogin profiili",
"Tickets": "Liput"
"Tickets": "Liput",
"DisplayName:CommunityIndexPagePoll": "Yhteisön indeksointisivun kysely"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Gérer son compte",
"CommunityProfile": "Profil de la communauté",
"BlogProfile": "Profil du blog",
"Tickets": "Des billets"
"Tickets": "Des billets",
"DisplayName:CommunityIndexPagePoll": "Sondage de la page d'accueil de la communauté"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "खाते का प्रबंधन करें",
"CommunityProfile": "सामुदायिक प्रोफ़ाइल",
"BlogProfile": "ब्लॉग प्रोफ़ाइल",
"Tickets": "टिकट"
"Tickets": "टिकट",
"DisplayName:CommunityIndexPagePoll": "सामुदायिक अनुभाग मतदान"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/hr.json

@ -229,6 +229,7 @@
"ManageAccount": "Upravljaj računom",
"CommunityProfile": "Profil zajednice",
"BlogProfile": "Blog profil",
"Tickets": "Ulaznice"
"Tickets": "Ulaznice",
"DisplayName:CommunityIndexPagePoll": "Anketa na stranici indeksa zajednice"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Fiók kezelése",
"CommunityProfile": "Közösségi profil",
"BlogProfile": "Blog profil",
"Tickets": "Jegyek"
"Tickets": "Jegyek",
"DisplayName:CommunityIndexPagePoll": "Közösségi Indexoldal Szavazás"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Stjórna reikningi",
"CommunityProfile": "Samfélagssnið",
"BlogProfile": "Bloggprófíll",
"Tickets": "Miðar"
"Tickets": "Miðar",
"DisplayName:CommunityIndexPagePoll": "Samfélagssnið"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Gestisci profilo",
"CommunityProfile": "Profilo della comunità",
"BlogProfile": "Profilo del blog",
"Tickets": "Biglietti"
"Tickets": "Biglietti",
"DisplayName:CommunityIndexPagePoll": "Sondaggio della pagina indice della comunità"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Beheer account",
"CommunityProfile": "Gemeenschapsprofiel",
"BlogProfile": "Blogprofiel",
"Tickets": "Kaartjes"
"Tickets": "Kaartjes",
"DisplayName:CommunityIndexPagePoll": "Gemeenschapsindexpagina-enquête"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Zarządzać kontem",
"CommunityProfile": "Profil społeczności",
"BlogProfile": "Profil bloga",
"Tickets": "Bilety"
"Tickets": "Bilety",
"DisplayName:CommunityIndexPagePoll": "Ankieta na stronie głównej społeczności"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Gerenciar conta",
"CommunityProfile": "Perfil da comunidade",
"BlogProfile": "Perfil do blog",
"Tickets": "Ingressos"
"Tickets": "Ingressos",
"DisplayName:CommunityIndexPagePoll": "Enquete da página inicial da comunidade"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Gestionează contul",
"CommunityProfile": "Profilul comunității",
"BlogProfile": "Profil blog",
"Tickets": "bilete"
"Tickets": "bilete",
"DisplayName:CommunityIndexPagePoll": "Sondajul de pe pagina de index a comunității"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/ru.json

@ -235,6 +235,7 @@
"Resources": "Ресурсы",
"Video Courses": "Видео курсы",
"Packages": "Пакеты",
"Trainings": "Тренинги"
"Trainings": "Тренинги",
"DisplayName:CommunityIndexPagePoll": "Опрос на главной странице сообщества"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Spravovať účet",
"CommunityProfile": "Profil komunity",
"BlogProfile": "Profil blogu",
"Tickets": "Vstupenky"
"Tickets": "Vstupenky",
"DisplayName:CommunityIndexPagePoll": "Anketa na stránke indexu komunity"
}
}

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

@ -229,6 +229,7 @@
"ManageAccount": "Upravljanje računa",
"CommunityProfile": "Profil skupnosti",
"BlogProfile": "Blog profil",
"Tickets": "Vstopnice"
"Tickets": "Vstopnice",
"DisplayName:CommunityIndexPagePoll": "Anketa na strani z indeksom skupnosti"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/tr.json

@ -170,6 +170,7 @@
"ExploreTheEBook": "E-Kitabı Keşfedin",
"LatestVideos": "Son Videolar",
"Videos": "Videolar",
"More": "Daha Fazla"
"More": "Daha Fazla",
"DisplayName:CommunityIndexPagePoll": "Topluluk Anasayfası Anketi"
}
}

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

@ -228,6 +228,7 @@
"ManageAccount": "Quản lý tài khoản",
"CommunityProfile": "Hồ sơ cộng đồng",
"BlogProfile": "Hồ sơ blog",
"Tickets": "Vé"
"Tickets": "Vé",
"DisplayName:CommunityIndexPagePoll": "Bình chọn trang chủ cộng đồng"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json

@ -229,6 +229,7 @@
"ManageAccount": "管理账户",
"CommunityProfile": "社区概况",
"BlogProfile": "博客简介",
"Tickets": "门票"
"Tickets": "门票",
"DisplayName:CommunityIndexPagePoll": "社区首页投票"
}
}

3
abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hant.json

@ -229,6 +229,7 @@
"ManageAccount": "管理帳號",
"CommunityProfile": "社區簡介",
"BlogProfile": "部落格簡介",
"Tickets": "門票"
"Tickets": "門票",
"DisplayName:CommunityIndexPagePoll": "社區首頁調查"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ar.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "إطار عمل ABP ليس مجرد إطار عمل، بل هو أيضًا دليل لتطوير/إدارة المشروع، لأنه يوفر تدريبات DDD وGenericRepository وDI وMicroservice وModularity. حتى لو كنت لن تستخدم إطار العمل نفسه، يمكنك تطوير نفسك باستخدام docs.abp.io الذي تم إعداده جيدًا واحترافيًا. (OpenIddict، وRedis، وQuartz، وما إلى ذلك) \n نظرًا لأن العديد من الأشياء تم إنشاؤها مسبقًا، فإنها تقلل من وقت تطوير المشروع بشكل كبير. (مثل صفحة تسجيل الدخول، ومعالجة الاستثناءات، وتصفية البيانات، وتسجيل التدقيق، والترجمة، ووحدة التحكم التلقائية في API وما إلى ذلك) \n كمثال من تطبيقنا، استخدمت ناقل الأحداث المحلي للتحكم في المخزون. لذلك، أنا قادر على إدارة حركات الطلب عن طريق كتابة معالج الأسهم. \n إنه لأمر رائع ألا نضيع الوقت في CreationTime، CreatorId. يتم ملؤها تلقائيًا.",
"VideosLoginAndRegisterMessage": "يجب عليك تسجيل الدخول لمشاهدة مقاطع الفيديو. يمكنك إنشاء حساب للمشاهدة إذا لم تقم بذلك.",
"Filter": "منقي",
"VideoCourses": "دورات الفيديو"
"VideoCourses": "دورات الفيديو",
"TestimonialText": "شهادتك",
"Position": "الوظيفة",
"ExperienceYear": "سنوات الخبرة",
"FullName": "الاسم الكامل",
"CompanySize": "حجم الشركة",
"Image": "صورتك الشخصية",
"TestimonialTitle": "لنسمع شهادتك",
"TestimonialInfo": "رأي عملائنا يهم! أخبرنا عن تجربتك مع منتجنا وخدمتنا.",
"Country": "البلد",
"TestimonialTextPlaceholder": "اكتب قصة موجزة حول كيف ساعدك ABP في بناء وتسليم مشروعك.",
"PositionPlaceholder": "وظيفتك في شركتك.",
"SelectExperienceYearPlaceholder": "كم عدد سنوات خبرتك في مجال البرمجيات؟",
"FullNamePlaceholder": "اسمك الكامل.",
"CompanyNamePlaceholder": "اسم شركتك.",
"SelectCompanySizePlaceholder": "عدد الموظفين",
"ImagePlaceholder": "صورتك.",
"SelectCountryPlaceholder": "بلدك.",
"YouAreNotAuthorizedToWriteTestimonial": "لا يُسمح لك بكتابة الشهادة إلا إذا قمت بتسجيل الدخول.",
"UnAuthorizeTestimonialInfo": "رأيك مهم! قم بتسجيل الدخول لمشاركته.",
"TheFileIsTooLargeForImage": "لا يمكن أن تكون صورتك الشخصية أكبر من 1 ميغابايت.",
"ThisExtensionIsNotAllowedForImage": "هذا الامتداد غير مسموح به.",
"FileUploadError": "خطأ في تحميل الملف",
"TestimonialSend": "شكرًا لك! لقد تلقينا شهادتك. سنقوم بمراجعتها واتخاذ الخطوة التالية قريبًا.",
"Title": "العنوان",
"TitlePlaceholder": "مطور برامج، مدير تكنولوجيا المعلومات، إلخ.",
"Characters": "الأحرف"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/cs.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework není jen rámec, je to také návod pro vývoj/řízení projektů, protože poskytuje školení DDD, GenericRepository, DI, Microservice, Modularity. I když se nechystáte používat samotný framework, můžete se vyvíjet s docs.abp.io, který je dobře a profesionálně připraven. (OpenIddict, Redis, Quartz atd.) \n Protože je mnoho věcí předpřipravených, výrazně to zkracuje dobu vývoje projektu. (Jako přihlašovací stránka, zpracování výjimek, filtrování dat-seedování, protokolování auditu, lokalizace, automatický api řadič atd.) \n Jako příklad z naší aplikace jsem pro řízení zásob použil místní sběrnici událostí. Takže jsem schopen řídit pohyby objednávek psaním skladového manipulátoru. \n Je skvělé neztrácet čas pro CreationTime, CreatorId. Vyplňují se automaticky.",
"VideosLoginAndRegisterMessage": "Chcete-li sledovat videa, musíte se přihlásit. Můžete si vytvořit účet pro hodinky, pokud ještě nemáte.",
"Filter": "Filtr",
"VideoCourses": "Video kurzy"
"VideoCourses": "Video kurzy",
"TestimonialText": "Vaše hodnocení",
"Position": "Pozice",
"ExperienceYear": "Roky zkušeností",
"FullName": "Celé jméno",
"CompanySize": "Velikost společnosti",
"Image": "Vaše profilová fotografie",
"TestimonialTitle": "Pojďme slyšet vaše hodnocení",
"TestimonialInfo": "To, co naši zákazníci říkají, má význam! Dejte nám vědět o své zkušenosti s naším produktem a servisem.",
"Country": "Země",
"TestimonialTextPlaceholder": "Napište stručný příběh o tom, jak vám ABP pomohlo stavět a dodávat váš projekt.",
"PositionPlaceholder": "Vaše pozice ve vaší společnosti.",
"SelectExperienceYearPlaceholder": "Kolik let jste ve softwarovém odvětví?",
"FullNamePlaceholder": "Vaše celé jméno.",
"CompanyNamePlaceholder": "Název vaší společnosti.",
"SelectCompanySizePlaceholder": "Počet zaměstnanců",
"ImagePlaceholder": "Vaše fotka.",
"SelectCountryPlaceholder": "Vaše země.",
"YouAreNotAuthorizedToWriteTestimonial": "Chcete-li napsat svědectví, musíte se přihlásit.",
"UnAuthorizeTestimonialInfo": "Vaše názor je důležitý! Přihlaste se pro sdílení.",
"TheFileIsTooLargeForImage": "Vaše profilová fotografie nesmí být větší než 1 MB",
"ThisExtensionIsNotAllowedForImage": "Tento typ souboru není povolen.",
"FileUploadError": "Chyba při nahrávání souboru",
"TestimonialSend": "Děkujeme! Obdrželi jsme vaše svědectví. Brzy to zkontrolujeme a přijmeme další kroky.",
"Title": "Titul",
"TitlePlaceholder": "Vývojář softwaru, CTO atd.",
"Characters": "znaky"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/de.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework ist nicht nur ein Framework, sondern auch eine Anleitung für die Projektentwicklung/-verwaltung, da es DDD-, GenericRepository-, DI-, Microservice- und Modularitätsschulungen bereitstellt. Auch wenn Sie das Framework selbst nicht verwenden, können Sie sich mit docs.abp.io selbst entwickeln, das gut und professionell vorbereitet ist. (OpenIddict, Redis, Quartz usw.) \n Da viele Dinge vorgefertigt sind, verkürzt es die Projektentwicklungszeit erheblich. (Zum Beispiel Anmeldeseite, Ausnahmebehandlung, Datenfilterung/Seeding, Audit-Protokollierung, Lokalisierung, automatischer API-Controller usw.) \n Als Beispiel aus unserer App habe ich Local Event Bus für die Bestandskontrolle verwendet. Daher bin ich in der Lage, Auftragsbewegungen zu verwalten, indem ich „Stock Handler“ schreibe. \n Es ist wunderbar, keine Zeit für CreationTime und CreatorId zu verlieren. Sie werden automatisch ausgefüllt.",
"VideosLoginAndRegisterMessage": "Sie müssen sich anmelden, um Videos anzusehen. Sie können ein Konto für die Uhr erstellen, wenn Sie noch kein Konto haben.",
"Filter": "Filter",
"VideoCourses": "Videokurse"
"VideoCourses": "Videokurse",
"TestimonialText": "Ihre Bewertung",
"Position": "Position",
"ExperienceYear": "Jahre Erfahrung",
"FullName": "Vollständiger Name",
"CompanySize": "Firmengröße",
"Image": "Ihr Profilbild",
"TestimonialTitle": "Lassen Sie uns Ihre Bewertung hören",
"TestimonialInfo": "Was unsere Kunden sagen, ist wichtig! Erzählen Sie uns von Ihrer Erfahrung mit unserem Produkt und Service.",
"Country": "Land",
"TestimonialTextPlaceholder": "Schreiben Sie eine kurze Geschichte darüber, wie Ihnen ABP geholfen hat, Ihr Projekt zu entwickeln und zu liefern.",
"PositionPlaceholder": "Ihre Position in Ihrem Unternehmen.",
"SelectExperienceYearPlaceholder": "Wie viele Jahre haben Sie Erfahrung in der Softwarebranche?",
"FullNamePlaceholder": "Ihr vollständiger Name.",
"CompanyNamePlaceholder": "Der Name Ihres Unternehmens.",
"SelectCompanySizePlaceholder": "Anzahl der Mitarbeiter",
"ImagePlaceholder": "Ihr Bild.",
"SelectCountryPlaceholder": "Ihr Land.",
"YouAreNotAuthorizedToWriteTestimonial": "Um eine Bewertung zu schreiben, müssen Sie angemeldet sein.",
"UnAuthorizeTestimonialInfo": "Ihre Meinung ist wichtig! Melden Sie sich an, um sie zu teilen.",
"TheFileIsTooLargeForImage": "Ihr Profilbild darf nicht größer als 1 MB sein.",
"ThisExtensionIsNotAllowedForImage": "Diese Erweiterung ist nicht erlaubt.",
"FileUploadError": "Fehler beim Hochladen der Datei",
"TestimonialSend": "Vielen Dank! Wir haben Ihre Bewertung erhalten. Wir werden sie bald überprüfen und den nächsten Schritt unternehmen.",
"Title": "Titel",
"TitlePlaceholder": "Softwareentwickler, CTO usw.",
"Characters": "zeichen"
}
}

32
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json

@ -260,7 +260,7 @@
"TellUsAboutYourself": "Tell us a little bit about yourself",
"Name": "Name",
"Surname": "Surname",
"CompanyName": "Company Name",
"CompanyName": "Company name",
"DoYouAgreePrivacyPolicy": "I agree to the <a href=\"https://account.abp.io/Account/TermsConditions\">Terms & Conditions</a> and <a href=\"https://account.abp.io/Account/Privacy\">Privacy Policy</a>.",
"Free": "Free",
"DDDEBook": "DDD E-Book",
@ -443,26 +443,30 @@
"VideoCourses": "Video Courses",
"TestimonialText": "Your testimonial",
"Position": "Position",
"ExperienceYear": "Years of Experience",
"FullName": "Full Name",
"CompanySize": "Company Size",
"Image": "Your profile picture",
"ExperienceYear": "Years of experience",
"FullName": "Full name",
"CompanySize": "Company size",
"TestimonialTitle": "Let's hear your testimonial",
"TestimonialInfo": "What our customers say matters! Tell us about your experience with our product and service.",
"Country": "Country",
"TestimonialTextPlaceholder": "Write a brief story about how ABP helped you build and deliver your project. ",
"PositionPlaceholder": "Your position at your company.",
"TestimonialTextPlaceholder": "Write a brief story about how ABP helped you build and deliver your project.",
"PositionPlaceholder": "Your position at your company",
"SelectExperienceYearPlaceholder": "How many years have you been in software stuff",
"FullNamePlaceholder": "Your full name.",
"CompanyNamePlaceholder": "Your company name.",
"FullNamePlaceholder": "Your full name",
"CompanyNamePlaceholder": "Your company name",
"SelectCompanySizePlaceholder": "Employee count",
"ImagePlaceholder": "Your image.",
"SelectCountryPlaceholder": "Your country.",
"ImagePlaceholder": "Your image",
"SelectCountryPlaceholder": "Your country",
"YouAreNotAuthorizedToWriteTestimonial": "To be able to write testimonial letter, you must be sign in.",
"UnAuthorizeTestimonialInfo": "If you want to share your opinion, you must be <a id='signin-btn'>sign in</a>",
"TheFileIsTooLargeForImage": "Your profile picture cannot be more than 1 MB",
"UnAuthorizeTestimonialInfo": "Your opinion matters! Log in to share it.",
"TheFileIsTooLargeForImage": "Your profile picture cannot be more than {0} MB",
"ThisExtensionIsNotAllowedForImage": "This extension is not allowed.",
"FileUploadError": "File upload error"
"FileUploadError": "File upload error",
"TestimonialSend": "Thank you! We've received your testimonial. <br> We'll review and take the next step soon.",
"Title": "Title",
"TitlePlaceholder": "Software Developer, CTO etc.",
"Characters": "characters",
"Testimonial_YourProfilePicture": "Your profile picture (only {0})"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework no es solo un marco, también es una guía para el desarrollo/gestión de proyectos, porque proporciona capacitaciones sobre DDD, GenericRepository, DI, Microservice y Modularity. Incluso si no va a utilizar el marco en sí, puede desarrollarlo usted mismo con docs.abp.io, que está bien preparado y profesionalmente. (OpenIddict, Redis, Quartz, etc.) \n Debido a que muchos elementos están prediseñados, acorta significativamente el tiempo de desarrollo del proyecto. (Como página de inicio de sesión, manejo de excepciones, filtrado y siembra de datos, registro de auditoría, localización, controlador de API automático, etc.) \n Como ejemplo de nuestra aplicación, he utilizado Local Event Bus para el control de existencias. Por lo tanto, puedo gestionar los movimientos de pedidos escribiendo el controlador de stock. \n Es maravilloso no perder tiempo con CreationTime, CreatorId. Se llenan automáticamente.",
"VideosLoginAndRegisterMessage": "Debes iniciar sesión para ver videos. Puedes crear una cuenta para ver si aún no lo has hecho.",
"Filter": "Filtrar",
"VideoCourses": "Cursos en vídeo"
"VideoCourses": "Cursos en vídeo",
"TestimonialText": "Tu testimonio",
"Position": "Cargo",
"ExperienceYear": "Años de experiencia",
"FullName": "Nombre completo",
"CompanySize": "Tamaño de la empresa",
"Image": "Tu foto de perfil",
"TestimonialTitle": "Escuchemos tu testimonio",
"TestimonialInfo": "¡Lo que dicen nuestros clientes es importante! Cuéntanos tu experiencia con nuestro producto y servicio.",
"Country": "País",
"TestimonialTextPlaceholder": "Escribe una breve historia sobre cómo ABP te ayudó a construir y entregar tu proyecto.",
"PositionPlaceholder": "Tu posición en tu empresa.",
"SelectExperienceYearPlaceholder": "¿Cuántos años llevas en el campo del software?",
"FullNamePlaceholder": "Tu nombre completo.",
"CompanyNamePlaceholder": "Nombre de tu empresa.",
"SelectCompanySizePlaceholder": "Cantidad de empleados",
"ImagePlaceholder": "Tu imagen.",
"SelectCountryPlaceholder": "Tu país.",
"YouAreNotAuthorizedToWriteTestimonial": "Para poder escribir un testimonio, debes iniciar sesión.",
"UnAuthorizeTestimonialInfo": "¡Tu opinión es importante! Inicia sesión para compartirla.",
"TheFileIsTooLargeForImage": "Tu foto de perfil no puede superar 1 MB.",
"ThisExtensionIsNotAllowedForImage": "Esta extensión no está permitida.",
"FileUploadError": "Error al cargar el archivo",
"TestimonialSend": "¡Gracias! Hemos recibido tu testimonio. Lo revisaremos y daremos el próximo paso pronto.",
"Title": "Título",
"TitlePlaceholder": "Desarrollador de software, CTO, etc.",
"Characters": "caracteres"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fi.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework ei ole vain viitekehys, se on myös opastus projektien kehittämiseen/hallintaan, koska se tarjoaa DDD-, GenericRepository-, DI-, Microservice- ja Modularity-koulutuksia. Vaikka et itse käyttäisikään kehystä, voit kehittää itseäsi docs.abp.io:lla, joka on hyvin ja ammattimaisesti valmisteltu. (OpenIddict, Redis, Quartz jne.) \n Koska monet asiat on rakennettu valmiiksi, se lyhentää projektin kehitysaikaa merkittävästi. (Kuten kirjautumissivu, poikkeusten käsittely, tietojen suodatus-kylvö, tarkastusloki, lokalisointi, automaattinen api-ohjain jne.) \n Esimerkkinä sovelluksestamme, olen käyttänyt Local Event Busia varaston hallintaan. Pystyn siis hallitsemaan tilausliikkeitä kirjoittamalla varastokäsittelijäksi. \n On hienoa olla hukkaamatta aikaa CreationTime, CreatorId. Ne täytetään automaattisesti.",
"VideosLoginAndRegisterMessage": "Sinun on kirjauduttava sisään katsoaksesi videoita. Voit luoda tilin kellolle, jos et ole vielä tehnyt sitä.",
"Filter": "Suodattaa",
"VideoCourses": "Videokurssit"
"VideoCourses": "Videokurssit",
"TestimonialText": "Arvostelusi",
"Position": "Asema",
"ExperienceYear": "Vuoden kokemus",
"FullName": "Koko nimi",
"CompanySize": "Yrityksen koko",
"Image": "Profiilikuvasi",
"TestimonialTitle": "Kuunnellaan arvosteluasi",
"TestimonialInfo": "Mitä asiakkaamme sanovat, on tärkeää! Kerro meille kokemuksestasi tuotteemme ja palvelumme parissa.",
"Country": "Maa",
"TestimonialTextPlaceholder": "Kirjoita lyhyt tarina siitä, miten ABP auttoi sinua rakentamaan ja toimittamaan projektisi.",
"PositionPlaceholder": "Asemasi yrityksessäsi.",
"SelectExperienceYearPlaceholder": "Kuinka monta vuotta olet työskennellyt ohjelmistoteollisuudessa?",
"FullNamePlaceholder": "Koko nimesi.",
"CompanyNamePlaceholder": "Yrityksesi nimi.",
"SelectCompanySizePlaceholder": "Työntekijöiden määrä",
"ImagePlaceholder": "Kuvasi.",
"SelectCountryPlaceholder": "Maasi.",
"YouAreNotAuthorizedToWriteTestimonial": "Voit kirjoittaa arvostelun vain kirjautuneena sisään.",
"UnAuthorizeTestimonialInfo": "Mielipiteesi on tärkeä! Kirjaudu sisään jakaaaksesi sen.",
"TheFileIsTooLargeForImage": "Profiilikuvasi ei saa olla yli 1 Mt.",
"ThisExtensionIsNotAllowedForImage": "Tätä tiedostotyyppiä ei sallita.",
"FileUploadError": "Tiedoston latausvirhe",
"TestimonialSend": "Kiitos! Olemme vastaanottaneet arvostelusi. Käymme sen läpi ja otamme seuraavan askeleen pian.",
"Title": "Titteli",
"TitlePlaceholder": "Ohjelmistokehittäjä, CTO, jne.",
"Characters": "hahmot"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/fr.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework n&#39;est pas seulement un framework, c&#39;est aussi un guide pour le développement/gestion de projets, car il propose des formations DDD, GenericRepository, DI, Microservice, Modularité. Même si vous n&#39;utilisez pas le framework lui-même, vous pouvez vous développer avec docs.abp.io qui est bien préparé de manière professionnelle. (OpenIddict, Redis, Quartz, etc.) \n Parce que de nombreux éléments sont pré-construits, cela réduit considérablement le temps de développement du projet. (Tels que la page de connexion, la gestion des exceptions, le filtrage-ensemencement des données, la journalisation d&#39;audit, la localisation, le contrôleur API automatique, etc.) \n À titre d&#39;exemple de notre application, j&#39;ai utilisé Local Event Bus pour le contrôle des stocks. Ainsi, je suis capable de gérer les mouvements de commandes en écrivant stock handler. \n C&#39;est merveilleux de ne pas perdre de temps pour CreationTime, CreatorId. Ils sont remplis automatiquement.",
"VideosLoginAndRegisterMessage": "Vous devez vous connecter pour regarder des vidéos. Vous pouvez créer un compte pour regarder si vous ne l&#39;avez pas encore fait.",
"Filter": "Filtre",
"VideoCourses": "Cours vidéo"
"VideoCourses": "Cours vidéo",
"TestimonialText": "Votre témoignage",
"Position": "Poste",
"ExperienceYear": "Années d'expérience",
"FullName": "Nom complet",
"CompanySize": "Taille de l'entreprise",
"Image": "Votre photo de profil",
"TestimonialTitle": "Écoutons votre témoignage",
"TestimonialInfo": "Ce que disent nos clients est important ! Parlez-nous de votre expérience avec notre produit et notre service.",
"Country": "Pays",
"TestimonialTextPlaceholder": "Rédigez une brève histoire sur la manière dont ABP vous a aidé à construire et livrer votre projet.",
"PositionPlaceholder": "Votre poste dans votre entreprise.",
"SelectExperienceYearPlaceholder": "Combien d'années avez-vous d'expérience dans le domaine du logiciel ?",
"FullNamePlaceholder": "Votre nom complet.",
"CompanyNamePlaceholder": "Nom de votre entreprise.",
"SelectCompanySizePlaceholder": "Nombre d'employés",
"ImagePlaceholder": "Votre image.",
"SelectCountryPlaceholder": "Votre pays.",
"YouAreNotAuthorizedToWriteTestimonial": "Pour pouvoir écrire un témoignage, vous devez être connecté(e).",
"UnAuthorizeTestimonialInfo": "Votre avis compte ! Connectez-vous pour le partager.",
"TheFileIsTooLargeForImage": "Votre photo de profil ne peut pas dépasser 1 Mo.",
"ThisExtensionIsNotAllowedForImage": "Cette extension n'est pas autorisée.",
"FileUploadError": "Erreur lors du téléchargement du fichier",
"TestimonialSend": "Merci ! Nous avons bien reçu votre témoignage. Nous le passerons en revue et prendrons la prochaine étape bientôt.",
"Title": "Titre",
"TitlePlaceholder": "Développeur de logiciels, CTO, etc.",
"Characters": "caractères"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hi.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "एबीपी फ्रेमवर्क न केवल एक ढांचा है, यह परियोजना विकास/प्रबंधन के लिए एक मार्गदर्शन भी है, क्योंकि यह डीडीडी, जेनेरिक रिपोजिटरी, डीआई, माइक्रोसर्विस, मॉड्यूलरिटी प्रशिक्षण प्रदान करता है। भले ही आप स्वयं फ्रेमवर्क का उपयोग नहीं करने जा रहे हैं, आप docs.abp.io के साथ स्वयं को विकसित कर सकते हैं जो अच्छी तरह से और पेशेवर रूप से तैयार है। (OpenIddict, Redis, Quartz आदि) \n चूंकि कई चीजें पहले से निर्मित होती हैं, इसलिए यह परियोजना के विकास के समय को काफी कम कर देता है। (जैसे लॉगिन पेज, अपवाद हैंडलिंग, डेटा फ़िल्टरिंग-सीडिंग, ऑडिट लॉगिंग, स्थानीयकरण, ऑटो एपीआई नियंत्रक इत्यादि) \n हमारे ऐप से एक उदाहरण के रूप में, मैंने स्टॉक नियंत्रण के लिए स्थानीय इवेंट बस का उपयोग किया है। इसलिए, मैं स्टॉक हैंडलर लिखकर ऑर्डर मूवमेंट को प्रबंधित करने में सक्षम हूं। \n CreationTime, CreatorId के लिए समय न बर्बाद करना अद्भुत है। वे स्वचालित रूप से भर जाते हैं.",
"VideosLoginAndRegisterMessage": "वीडियो देखने के लिए आपको साइन इन करना होगा. यदि आपने नहीं बनाया है तो आप घड़ी के लिए एक खाता बना सकते हैं।",
"Filter": "फ़िल्टर",
"VideoCourses": "वीडियो पाठ्यक्रम"
"VideoCourses": "वीडियो पाठ्यक्रम",
"TestimonialText": "आपका साक्षात्कार",
"Position": "पद",
"ExperienceYear": "अनुभव के वर्ष",
"FullName": "पूरा नाम",
"CompanySize": "कंपनी का आकार",
"Image": "आपकी प्रोफ़ाइल तस्वीर",
"TestimonialTitle": "हम आपका साक्षात्कार सुनें",
"TestimonialInfo": "हमारे ग्राहकों की कहानियाँ महत्वपूर्ण हैं! हमें अपने उत्पाद और सेवा के साथ अपने अनुभव के बारे में बताएं।",
"Country": "देश",
"TestimonialTextPlaceholder": "एक संक्षेप कहानी लिखें कि ABP ने आपको अपने परियोजना को बनाने और पहुंचाने में कैसे मदद की।",
"PositionPlaceholder": "आपका पद आपकी कंपनी में।",
"SelectExperienceYearPlaceholder": "आप सॉफ़्टवेयर क्षेत्र में कितने वर्षों से हैं?",
"FullNamePlaceholder": "आपका पूरा नाम।",
"CompanyNamePlaceholder": "आपकी कंपनी का नाम।",
"SelectCompanySizePlaceholder": "कर्मचारी संख्या",
"ImagePlaceholder": "आपकी छवि।",
"SelectCountryPlaceholder": "आपका देश।",
"YouAreNotAuthorizedToWriteTestimonial": "एक साक्षात्कार लिखने के लिए, आपको लॉग इन करना होगा।",
"UnAuthorizeTestimonialInfo": "आपकी राय महत्वपूर्ण है! इसे साझा करने के लिए लॉग इन करें।",
"TheFileIsTooLargeForImage": "आपकी प्रोफ़ाइल तस्वीर 1 MB से अधिक नहीं हो सकती।",
"ThisExtensionIsNotAllowedForImage": "यह एक्सटेंशन अनुमति नहीं है।",
"FileUploadError": "फ़ाइल अपलोड की गई में त्रुटि",
"TestimonialSend": "धन्यवाद! हमने आपका साक्षात्कार प्राप्त किया है। हम इसे समीक्षा करेंगे और शीघ्र अगला कदम उठाएंगे।",
"Title": "शीर्षक",
"TitlePlaceholder": "सॉफ़्टवेयर डेवेलपर, सीटीओ, आदि।",
"Characters": "अक्षर"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hr.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework nije samo okvir, već je i smjernica za razvoj/upravljanje projektom, jer pruža DDD, GenericRepository, DI, Microservice, Modularity treninge. Čak i ako nećete koristiti sam framework, možete se razvijati s docs.abp.io koji je dobro i profesionalno pripremljen. (OpenIddict, Redis, Quartz itd.) \n Budući da su mnoge stvari unaprijed izgrađene, značajno skraćuje vrijeme razvoja projekta. (Kao što je stranica za prijavu, rukovanje iznimkama, filtriranje-sijanje podataka, bilježenje revizije, lokalizacija, automatski API kontroler itd.) \n Kao primjer iz naše aplikacije, koristio sam lokalnu sabirnicu događaja za kontrolu zaliha. Dakle, mogu upravljati kretanjem narudžbi pisanjem rukovatelja zalihama. \n Divno je ne gubiti vrijeme za CreationTime, CreatorId. Pune se automatski.",
"VideosLoginAndRegisterMessage": "Morate se prijaviti za gledanje videa. Možete stvoriti račun za sat ako niste.",
"Filter": "filtar",
"VideoCourses": "Video tečajevi"
"VideoCourses": "Video tečajevi",
"TestimonialText": "Vaša preporuka",
"Position": "Pozicija",
"ExperienceYear": "Godine iskustva",
"FullName": "Puno ime",
"CompanySize": "Veličina tvrtke",
"Image": "Vaša profilna slika",
"TestimonialTitle": "Poslušajmo vašu preporuku",
"TestimonialInfo": "Ono što naši klijenti kažu važno je! Podijelite s nama svoje iskustvo s našim proizvodom i uslugom.",
"Country": "Država",
"TestimonialTextPlaceholder": "Napišite kratku priču o tome kako vam je ABP pomogao izgraditi i isporučiti vaš projekt.",
"PositionPlaceholder": "Vaša pozicija u tvrtki.",
"SelectExperienceYearPlaceholder": "Koliko godina imate iskustva u području softvera?",
"FullNamePlaceholder": "Vaše puno ime.",
"CompanyNamePlaceholder": "Naziv vaše tvrtke.",
"SelectCompanySizePlaceholder": "Broj zaposlenika",
"ImagePlaceholder": "Vaša slika.",
"SelectCountryPlaceholder": "Vaša država.",
"YouAreNotAuthorizedToWriteTestimonial": "Da biste mogli napisati preporuku, morate biti prijavljeni.",
"UnAuthorizeTestimonialInfo": "Vaše mišljenje je važno! Prijavite se kako biste ga podijelili.",
"TheFileIsTooLargeForImage": "Vaša profilna slika ne smije biti veća od 1 MB.",
"ThisExtensionIsNotAllowedForImage": "Ovo proširenje nije dopušteno.",
"FileUploadError": "Pogreška prilikom prijenosa datoteke",
"TestimonialSend": "Hvala vam! Primili smo vašu preporuku. Provjerit ćemo je i uskoro poduzeti sljedeći korak.",
"Title": "Naslov",
"TitlePlaceholder": "Razvojni inženjer, CTO, itd.",
"Characters": "znakovi"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/hu.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "Az ABP Framework nem csak keretrendszer, hanem útmutató is a projektfejlesztéshez/menedzsmenthez, mert DDD, GenericRepository, DI, Microservice, Modularity képzéseket biztosít. Még ha nem is magát a keretrendszert használja, fejlesztheti magát a docs.abp.io segítségével, amely jól és szakmailag felkészült. (OpenIddict, Redis, Quartz stb.) \n Mivel sok minden előre be van építve, jelentősen lerövidíti a projektfejlesztési időt. (Például bejelentkezési oldal, kivételkezelés, adatszűrés-seeding, audit naplózás, lokalizáció, automatikus api-vezérlő stb.) \n Alkalmazásunkból példaként a Local Event Bus-t használtam készletkezelésre. Így a rendelési mozgásokat készletkezelő írással tudom kezelni. \n Csodálatos, hogy nem veszít időt a CreationTime, CreatorId használatára. Automatikusan kitöltődnek.",
"VideosLoginAndRegisterMessage": "A videók megtekintéséhez be kell jelentkeznie. Ha még nem tette meg, létrehozhat fiókot az órához.",
"Filter": "Szűrő",
"VideoCourses": "Videó tanfolyamok"
"VideoCourses": "Videó tanfolyamok",
"TestimonialText": "Ajánlásod",
"Position": "Pozíció",
"ExperienceYear": "Tapasztalati év",
"FullName": "Teljes név",
"CompanySize": "Cég mérete",
"Image": "Profilképed",
"TestimonialTitle": "Halljuk ajánlásod",
"TestimonialInfo": "Ami ügyfeleinktől származik, az fontos! Mesélj nekünk tapasztalataidról a termékünkkel és szolgáltatásunkkal kapcsolatban.",
"Country": "Ország",
"TestimonialTextPlaceholder": "Írj rövid történetet arról, hogyan segített neked az ABP projektépítésben és szállításban.",
"PositionPlaceholder": "Pozíciód a vállalatodban.",
"SelectExperienceYearPlaceholder": "Mennyi éves tapasztalatod van a szoftverek területén?",
"FullNamePlaceholder": "Teljes neved.",
"CompanyNamePlaceholder": "Céged neve.",
"SelectCompanySizePlaceholder": "Alkalmazottak száma",
"ImagePlaceholder": "Profilképed.",
"SelectCountryPlaceholder": "Országod.",
"YouAreNotAuthorizedToWriteTestimonial": "Ahhoz, hogy ajánlást írhass, be kell jelentkezned.",
"UnAuthorizeTestimonialInfo": "A véleménye számít! Jelentkezzen be, hogy megossza.",
"TheFileIsTooLargeForImage": "A profilképed nem lehet nagyobb, mint 1 MB.",
"ThisExtensionIsNotAllowedForImage": "Ez a kiterjesztés nem engedélyezett.",
"FileUploadError": "Hiba történt a fájl feltöltése közben",
"TestimonialSend": "Köszönjük! Megkaptuk az ajánlásod. Hamarosan átnézzük és következő lépéseket teszünk.",
"Title": "Cím",
"TitlePlaceholder": "Szoftvertervező, CTO, stb.",
"Characters": "karakterek"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/is.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework er ekki aðeins rammi, það er líka leiðsögn fyrir þróun/stjórnun verkefna, vegna þess að það veitir DDD, GenericRepository, DI, Microservice, Modularity þjálfun. Jafnvel þó þú ætlir ekki að nota ramma sjálfan þig geturðu þróað sjálfan þig með docs.abp.io sem er vel og faglega undirbúið. (OpenIddict, Redis, Quartz o.s.frv.) \n Þar sem margt er forsmíðað styttir það þróunartíma verkefna verulega. (Svo sem innskráningarsíðu, undantekningarmeðferð, gagnasíun-sáningu, endurskoðunarskráningu, staðfærslu, sjálfvirkan API stjórnandi o.s.frv.) \n Sem dæmi úr appinu okkar hef ég notað Local Event Bus fyrir lagerstýringu. Þannig að ég get stjórnað pöntunarhreyfingum með því að skrifa lager meðhöndlun. \n Það er dásamlegt að missa ekki tíma fyrir CreationTime, CreatorId. Þau fyllast sjálfkrafa.",
"VideosLoginAndRegisterMessage": "Þú verður að skrá þig inn til að horfa á myndbönd. Þú getur búið til reikning fyrir úrið ef þú hefur ekki gert það.",
"Filter": "Sía",
"VideoCourses": "Vídeónámskeið"
"VideoCourses": "Vídeónámskeið",
"TestimonialText": "Viðmiðun þín",
"Position": "Staða",
"ExperienceYear": "Reynsluár",
"FullName": "Fullt Nafn",
"CompanySize": "Fyrirtækisstærð",
"Image": "Prófílmynd þín",
"TestimonialTitle": "Hlýtur að heyra viðmiðu þína",
"TestimonialInfo": "Það sem viðskiptavinir okkar segja skiptir máli! Segið okkur frá reynslu þinni með vörum okkar og þjónustu.",
"Country": "Land",
"TestimonialTextPlaceholder": "Skrifið stutta sögu um hvernig ABP hjálpaði yður að byggja og afhenda verkefnið ykkar.",
"PositionPlaceholder": "Staða þín í fyrirtækinu þínu.",
"SelectExperienceYearPlaceholder": "Hversu mörg ár hefur þú starfað í hugbúnaðarverkfræði?",
"FullNamePlaceholder": "Fullt nafn þitt.",
"CompanyNamePlaceholder": "Nafn fyrirtækisins þíns.",
"SelectCompanySizePlaceholder": "Fjöldi starfsmanna",
"ImagePlaceholder": "Prófílmynd þín.",
"SelectCountryPlaceholder": "Landið þitt.",
"YouAreNotAuthorizedToWriteTestimonial": "Til að geta skrifað viðmiðun, verður þú að skrá þig inn.",
"UnAuthorizeTestimonialInfo": "Þín skoðun er mikilvæg! Skráðu þig inn til að deila henni.",
"TheFileIsTooLargeForImage": "Prófílmynd þín má ekki vera stærri en 1 MB.",
"ThisExtensionIsNotAllowedForImage": "Þessi viðbót er ekki leyfð.",
"FileUploadError": "Villa við upphleðslu skráar",
"TestimonialSend": "Þakka þér! Við höfum fengið viðmiðuna þína. Við munum fara yfir hana fljótt og taka næsta skref.",
"Title": "Titill",
"TitlePlaceholder": "Hugbúnaðarþróunarmiðill, CTO o.s.frv.",
"Characters": "stafir"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/it.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework non è solo un framework, è anche una guida per lo sviluppo/gestione del progetto, poiché fornisce corsi di formazione su DDD, GenericRepository, DI, Microservice e Modularità. Anche se non utilizzerai il framework stesso, puoi svilupparti con docs.abp.io che è ben preparato e professionalmente. (OpenIddict, Redis, Quartz ecc.) \n Poiché molte cose sono precostruite, riduce significativamente i tempi di sviluppo del progetto. (Come pagina di accesso, gestione delle eccezioni, seeding del filtraggio dei dati, registrazione di controllo, localizzazione, controller API automatico ecc.) \n Come esempio tratto dalla nostra app, ho utilizzato Local Event Bus per il controllo delle scorte. Quindi, sono in grado di gestire i movimenti degli ordini scrivendo stock handler. \n È meraviglioso non perdere tempo con CreationTime, CreatorId. Si riempiono automaticamente.",
"VideosLoginAndRegisterMessage": "Devi accedere per guardare i video. Se non lo hai già fatto, puoi creare un account per Watch.",
"Filter": "Filtro",
"VideoCourses": "Videocorsi"
"VideoCourses": "Videocorsi",
"TestimonialText": "La tua testimonianza",
"Position": "Posizione",
"ExperienceYear": "Anni di esperienza",
"FullName": "Nome e cognome",
"CompanySize": "Dimensione aziendale",
"Image": "La tua immagine del profilo",
"TestimonialTitle": "Ascoltiamo la tua testimonianza",
"TestimonialInfo": "Ciò che dicono i nostri clienti è importante! ",
"Country": "Paese",
"TestimonialTextPlaceholder": "Scrivi una breve storia su come ABP ti ha aiutato a costruire e realizzare il tuo progetto. ",
"PositionPlaceholder": "La tua posizione nella tua azienda.",
"SelectExperienceYearPlaceholder": "Da quanti anni ti occupi di software?",
"FullNamePlaceholder": "Il tuo nome completo.",
"CompanyNamePlaceholder": "Il nome della tua azienda.",
"SelectCompanySizePlaceholder": "Conteggio dei dipendenti",
"ImagePlaceholder": "La tua immagine.",
"SelectCountryPlaceholder": "Il tuo paese.",
"YouAreNotAuthorizedToWriteTestimonial": "Per poter scrivere una lettera di testimonianza, devi effettuare l'accesso.",
"UnAuthorizeTestimonialInfo": "La tua opinione conta! Accedi per condividerla.",
"TheFileIsTooLargeForImage": "La tua immagine del profilo non può essere più di 1 MB",
"ThisExtensionIsNotAllowedForImage": "Questa estensione non è consentita.",
"FileUploadError": "Errore nel caricamento del file",
"TestimonialSend": "Grazie! ",
"Title": "Titolo",
"TitlePlaceholder": "Sviluppatore di software, CTO ecc.",
"Characters": "caratteri"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/nl.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework is niet alleen een raamwerk, het is ook een leidraad voor projectontwikkeling/management, omdat het DDD, GenericRepository, DI, Microservice, Modularity trainingen biedt. Zelfs als je het framework zelf niet gaat gebruiken, kun je jezelf ontwikkelen met docs.abp.io dat goed en professioneel is voorbereid. (OpenIddict, Redis, Quartz etc.) \n Omdat veel dingen vooraf zijn gebouwd, verkort dit de projectontwikkelingstijd aanzienlijk. (Zoals inlogpagina, afhandeling van uitzonderingen, gegevensfiltering-zaaien, auditlogboekregistratie, lokalisatie, automatische API-controller enz.) \n Als voorbeeld uit onze app heb ik Local Event Bus gebruikt voor voorraadbeheer. Ik kan dus orderbewegingen beheren door voorraadbeheer te schrijven. \n Het is geweldig om geen tijd te verliezen voor CreationTime, CreatorId. Ze worden automatisch gevuld.",
"VideosLoginAndRegisterMessage": "Je moet inloggen om video&#39;s te bekijken. Als u dat nog niet heeft gedaan, kunt u een account voor Watch aanmaken.",
"Filter": "Filter",
"VideoCourses": "Videocursussen"
"VideoCourses": "Videocursussen",
"TestimonialText": "Jouw getuigenis",
"Position": "Positie",
"ExperienceYear": "Jarenlange ervaring",
"FullName": "Voor-en achternaam",
"CompanySize": "Bedrijfsomvang",
"Image": "Jouw profiel foto",
"TestimonialTitle": "Laten we uw getuigenis horen",
"TestimonialInfo": "Wat onze klanten zeggen, doet ertoe! ",
"Country": "Land",
"TestimonialTextPlaceholder": "Schrijf een kort verhaal over hoe ABP u heeft geholpen bij het opzetten en opleveren van uw project. ",
"PositionPlaceholder": "Jouw functie binnen jouw bedrijf.",
"SelectExperienceYearPlaceholder": "Hoeveel jaar ben je al bezig met softwaredingen?",
"FullNamePlaceholder": "Je volledige naam.",
"CompanyNamePlaceholder": "Je bedrijfsnaam.",
"SelectCompanySizePlaceholder": "Aantal medewerkers",
"ImagePlaceholder": "Jou foto.",
"SelectCountryPlaceholder": "Jouw land.",
"YouAreNotAuthorizedToWriteTestimonial": "Om een getuigenisbrief te kunnen schrijven, moet u ingelogd zijn.",
"UnAuthorizeTestimonialInfo": "Jouw mening is belangrijk! Log in om het te delen.",
"TheFileIsTooLargeForImage": "Je profielfoto mag niet groter zijn dan 1 MB",
"ThisExtensionIsNotAllowedForImage": "Deze verlenging is niet toegestaan.",
"FileUploadError": "Fout bij het uploaden van bestanden",
"TestimonialSend": "Bedankt! ",
"Title": "Titel",
"TitlePlaceholder": "Softwareontwikkelaar, CTO enz.",
"Characters": "tekens"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pl-PL.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework to nie tylko framework, to także wytyczne dotyczące opracowywania/zarządzania projektami, ponieważ zapewnia szkolenia z DDD, GenericRepository, DI, Microservice, Modularity. Nawet jeśli nie będziesz korzystał z samego frameworka, możesz rozwijać się dzięki dobrze i profesjonalnie przygotowanemu docs.abp.io. (OpenIddict, Redis, Quartz itp.) \n Ponieważ wiele rzeczy jest gotowych, znacznie skraca to czas opracowywania projektu. (Takie jak strona logowania, obsługa wyjątków, filtrowanie danych, rejestrowanie audytu, lokalizacja, automatyczny kontroler API itp.) \n Jako przykład z naszej aplikacji użyłem lokalnej magistrali zdarzeń do kontroli zapasów. Mogę więc zarządzać ruchami zamówień, pisząc moduł obsługi zapasów. \n Wspaniale jest nie tracić czasu na CreationTime, CreatorId. Są one wypełniane automatycznie.",
"VideosLoginAndRegisterMessage": "Aby oglądać filmy, musisz się zalogować. Jeśli jeszcze tego nie zrobiłeś, możesz utworzyć konto na zegarku.",
"Filter": "Filtr",
"VideoCourses": "Kursy wideo"
"VideoCourses": "Kursy wideo",
"TestimonialText": "Twoje świadectwo",
"Position": "Pozycja",
"ExperienceYear": "lata doświadczenia",
"FullName": "Pełne imię i nazwisko",
"CompanySize": "Rozmiar firmy",
"Image": "Twoje zdjęcie profilowe",
"TestimonialTitle": "Posłuchajmy Twojej opinii",
"TestimonialInfo": "To, co mówią nasi klienci, ma znaczenie! ",
"Country": "Kraj",
"TestimonialTextPlaceholder": "Napisz krótką historię o tym, jak firma ABP pomogła Ci w budowie i realizacji projektu. ",
"PositionPlaceholder": "Twoje stanowisko w Twojej firmie.",
"SelectExperienceYearPlaceholder": "Ile lat zajmujesz się oprogramowaniem?",
"FullNamePlaceholder": "Twoje pełne imię.",
"CompanyNamePlaceholder": "Nazwa Twojej firmy.",
"SelectCompanySizePlaceholder": "Liczba pracowników",
"ImagePlaceholder": "Twój obraz.",
"SelectCountryPlaceholder": "Twój kraj.",
"YouAreNotAuthorizedToWriteTestimonial": "Aby móc napisać list referencyjny, musisz się zalogować.",
"UnAuthorizeTestimonialInfo": "Twoja opinia ma znaczenie. Zaloguj się, aby ją udostępnić.",
"TheFileIsTooLargeForImage": "Twoje zdjęcie profilowe nie może przekraczać 1 MB",
"ThisExtensionIsNotAllowedForImage": "To rozszerzenie jest niedozwolone.",
"FileUploadError": "Błąd przesyłania pliku",
"TestimonialSend": "Dziękuję! ",
"Title": "Tytuł",
"TitlePlaceholder": "Programista, CTO itp.",
"Characters": "znaki"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/pt-BR.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "O ABP Framework não é apenas um framework, é também uma orientação para desenvolvimento/gerenciamento de projetos, pois fornece treinamentos em DDD, GenericRepository, DI, Microservice, Modularidade. Mesmo que você não vá usar o framework em si, você pode se desenvolver com o docs.abp.io que está bem preparado e profissionalmente. (OpenIddict, Redis, Quartz etc.) \n Como muitas coisas são pré-construídas, ele reduz significativamente o tempo de desenvolvimento do projeto. (Como página de login, tratamento de exceções, propagação de filtragem de dados, registro de auditoria, localização, controlador automático de API, etc.) \n Como exemplo de nosso aplicativo, usei o Local Event Bus para controle de estoque. Portanto, sou capaz de gerenciar os movimentos dos pedidos escrevendo o gerenciador de estoque. \n É maravilhoso não perder tempo com CreationTime, CreatorId. Eles são preenchidos automaticamente.",
"VideosLoginAndRegisterMessage": "Você deve fazer login para assistir aos vídeos. Você pode criar uma conta para assistir, caso ainda não o tenha feito.",
"Filter": "Filtro",
"VideoCourses": "Cursos em vídeo"
"VideoCourses": "Cursos em vídeo",
"TestimonialText": "Seu depoimento",
"Position": "Posição",
"ExperienceYear": "anos de experiência",
"FullName": "Nome completo",
"CompanySize": "Tamanho da empresa",
"Image": "Sua foto de perfil",
"TestimonialTitle": "Vamos ouvir seu depoimento",
"TestimonialInfo": "O que nossos clientes dizem é importante! ",
"Country": "País",
"TestimonialTextPlaceholder": "Escreva uma breve história sobre como a ABP ajudou você a construir e entregar seu projeto. ",
"PositionPlaceholder": "Sua posição na sua empresa.",
"SelectExperienceYearPlaceholder": "Há quantos anos você trabalha com software",
"FullNamePlaceholder": "Seu nome completo.",
"CompanyNamePlaceholder": "O nome da sua empresa.",
"SelectCompanySizePlaceholder": "Contagem de funcionários",
"ImagePlaceholder": "Sua imagem.",
"SelectCountryPlaceholder": "Seu país.",
"YouAreNotAuthorizedToWriteTestimonial": "Para poder escrever uma carta de depoimento, você deve estar logado.",
"UnAuthorizeTestimonialInfo": "Sua opinião é importante, faça login para compartilhá-la.",
"TheFileIsTooLargeForImage": "Sua foto de perfil não pode ter mais de 1 MB",
"ThisExtensionIsNotAllowedForImage": "Esta extensão não é permitida.",
"FileUploadError": "Erro no upload do arquivo",
"TestimonialSend": "Obrigado! ",
"Title": "Título",
"TitlePlaceholder": "Desenvolvedor de software, CTO etc.",
"Characters": "caracteres"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework nu este doar un cadru, este și un ghid pentru dezvoltarea/managementul proiectelor, deoarece oferă cursuri DDD, GenericRepository, DI, Microservice, Modularity. Chiar dacă nu veți folosi framework-ul în sine, vă puteți dezvolta cu docs.abp.io, care este bine și pregătit profesional. (OpenIddict, Redis, Quartz etc.) \n Deoarece multe lucruri pre-construite, scurtează semnificativ timpul de dezvoltare a proiectului. (De exemplu, pagina de autentificare, gestionarea excepțiilor, filtrarea datelor, înregistrarea auditului, localizarea, controlerul auto api etc.) \n Ca exemplu din aplicația noastră, am folosit Local Event Bus pentru controlul stocurilor. Așadar, pot gestiona mișcările comenzilor scriind handler de stoc. \n Este minunat să nu pierzi timp pentru CreationTime, CreatorId. Acestea sunt completate automat.",
"VideosLoginAndRegisterMessage": "Trebuie să vă conectați pentru a viziona videoclipuri. Puteți crea un cont pentru ceas dacă nu ați făcut-o.",
"Filter": "Filtru",
"VideoCourses": "Cursuri video"
"VideoCourses": "Cursuri video",
"TestimonialText": "Marturia ta",
"Position": "Poziţie",
"ExperienceYear": "Ani de experienta",
"FullName": "Numele complet",
"CompanySize": "Marimea companiei",
"Image": "Fotografia de profil",
"TestimonialTitle": "Să auzim mărturia ta",
"TestimonialInfo": "Ceea ce spun clienții noștri contează! ",
"Country": "Țară",
"TestimonialTextPlaceholder": "Scrieți o scurtă poveste despre modul în care ABP v-a ajutat să vă construiți și să vă livrați proiectul. ",
"PositionPlaceholder": "Poziția ta la compania ta.",
"SelectExperienceYearPlaceholder": "Câți ani ai fost în chestii de software",
"FullNamePlaceholder": "Numele tău complet.",
"CompanyNamePlaceholder": "Numele companiei tale.",
"SelectCompanySizePlaceholder": "Numărul de angajați",
"ImagePlaceholder": "Imaginea ta.",
"SelectCountryPlaceholder": "Tara ta.",
"YouAreNotAuthorizedToWriteTestimonial": "Pentru a putea scrie o scrisoare de mărturie, trebuie să vă conectați.",
"UnAuthorizeTestimonialInfo": "Părerea ta contează, conectează-te pentru a o împărtăși.",
"TheFileIsTooLargeForImage": "Fotografia dvs. de profil nu poate depăși 1 MB",
"ThisExtensionIsNotAllowedForImage": "Această extensie nu este permisă.",
"FileUploadError": "Eroare de încărcare a fișierului",
"TestimonialSend": "Mulțumesc! ",
"Title": "Titlu",
"TitlePlaceholder": "Dezvoltator software, CTO etc.",
"Characters": "caractere"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ru.json

@ -438,6 +438,32 @@
"Index_Page_Testimonial_2": "ABP Framework — это не только платформа, но и руководство по разработке/управлению проектами, поскольку оно обеспечивает обучение DDD, GenericRepository, DI, Microservice и Modularity. ",
"VideosLoginAndRegisterMessage": "Чтобы иметь возможность смотреть видео, вам необходимо войти в систему.",
"Filter": "Фильтр",
"VideoCourses": "Видео курсы"
"VideoCourses": "Видео курсы",
"TestimonialText": "Ваш отзыв",
"Position": "Позиция",
"ExperienceYear": "Годы опыта",
"FullName": "Полное имя",
"CompanySize": "Размер компании",
"Image": "Изображение вашего профиля",
"TestimonialTitle": "Давайте послушаем ваше свидетельство",
"TestimonialInfo": "То, что говорят наши клиенты, имеет значение! ",
"Country": "Страна",
"TestimonialTextPlaceholder": "Напишите краткую историю о том, как ABP помогла вам создать и реализовать ваш проект. ",
"PositionPlaceholder": "Ваша должность в вашей компании.",
"SelectExperienceYearPlaceholder": "Сколько лет вы занимаетесь программным обеспечением?",
"FullNamePlaceholder": "Ваше полное имя.",
"CompanyNamePlaceholder": "Название вашей компании.",
"SelectCompanySizePlaceholder": "Количество сотрудников",
"ImagePlaceholder": "Ваш имидж.",
"SelectCountryPlaceholder": "Твоя страна.",
"YouAreNotAuthorizedToWriteTestimonial": "Чтобы иметь возможность написать рекомендательное письмо, вам необходимо войти в систему.",
"UnAuthorizeTestimonialInfo": "Ваше мнение имеет значение. Войдите, чтобы поделиться им.",
"TheFileIsTooLargeForImage": "Размер изображения вашего профиля не может превышать 1 МБ.",
"ThisExtensionIsNotAllowedForImage": "Это расширение не разрешено.",
"FileUploadError": "Ошибка загрузки файла",
"TestimonialSend": "Спасибо! ",
"Title": "Заголовок",
"TitlePlaceholder": "Разработчик программного обеспечения, технический директор и т. д.",
"Characters": "Символы"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sk.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework nie je len rámec, je to aj návod na vývoj/riadenie projektov, pretože poskytuje školenia DDD, GenericRepository, DI, Microservice, Modularity. Aj keď samotný framework nebudete používať, môžete sa rozvíjať pomocou docs.abp.io, ktoré je dobre a profesionálne pripravené. (OpenIddict, Redis, Quartz atď.) \n Pretože je veľa vecí vopred vytvorených, výrazne to skracuje čas vývoja projektu. (Ako prihlasovacia stránka, spracovanie výnimiek, filtrovanie údajov, zaznamenávanie auditov, lokalizácia, automatický api ovládač atď.) \n Ako príklad z našej aplikácie som použil lokálnu zbernicu udalostí na riadenie zásob. Takže som schopný riadiť pohyby objednávok napísaním skladového manipulátora. \n Je úžasné nestrácať čas pre CreationTime, CreatorId. Plnia sa automaticky.",
"VideosLoginAndRegisterMessage": "Ak chcete pozerať videá, musíte sa prihlásiť. Ak ešte nemáte účet pre hodinky, môžete si ho vytvoriť.",
"Filter": "Filter",
"VideoCourses": "Video kurzy"
"VideoCourses": "Video kurzy",
"TestimonialText": "Tvoje svedectvo",
"Position": "pozícia",
"ExperienceYear": "roky skúseností",
"FullName": "Celé meno",
"CompanySize": "Veľkosť spoločnosti",
"Image": "Váš profilový obrázok",
"TestimonialTitle": "Vypočujme si vaše svedectvo",
"TestimonialInfo": "Záleží na tom, čo hovoria naši zákazníci! ",
"Country": "Krajina",
"TestimonialTextPlaceholder": "Napíšte krátky príbeh o tom, ako vám ABP pomohla vybudovať a zrealizovať váš projekt. ",
"PositionPlaceholder": "Vaša pozícia vo vašej spoločnosti.",
"SelectExperienceYearPlaceholder": "Koľko rokov sa venuješ softvérovým veciam",
"FullNamePlaceholder": "Tvoje celé meno.",
"CompanyNamePlaceholder": "Názov vašej spoločnosti.",
"SelectCompanySizePlaceholder": "Počet zamestnancov",
"ImagePlaceholder": "Váš obraz.",
"SelectCountryPlaceholder": "Tvoja krajina.",
"YouAreNotAuthorizedToWriteTestimonial": "Aby ste mohli napísať posudkový list, musíte sa prihlásiť.",
"UnAuthorizeTestimonialInfo": "Váš názor je dôležitý! ",
"TheFileIsTooLargeForImage": "Váš profilový obrázok nemôže byť väčší ako 1 MB",
"ThisExtensionIsNotAllowedForImage": "Toto rozšírenie nie je povolené.",
"FileUploadError": "Chyba pri nahrávaní súboru",
"TestimonialSend": "Ďakujem! ",
"Title": "Názov",
"TitlePlaceholder": "Vývojár softvéru, CTO atď.",
"Characters": "znaky"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/sl.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "Ogrodje ABP ni le ogrodje, je tudi vodilo za razvoj/upravljanje projektov, saj zagotavlja usposabljanja DDD, GenericRepository, DI, Microservice, Modularity. Tudi če ne boste uporabljali samega ogrodja, se lahko razvijate z docs.abp.io, ki je dobro in strokovno pripravljen. (OpenIddict, Redis, Quartz itd.) \n Ker je veliko stvari vnaprej zgrajenih, znatno skrajša čas razvoja projekta. (Kot so prijavna stran, obravnavanje izjem, filtriranje-sejanje podatkov, revizijsko beleženje, lokalizacija, samodejni krmilnik api itd.) \n Kot primer iz naše aplikacije sem za nadzor zalog uporabil lokalno vodilo dogodkov. Tako lahko upravljam premike naročil s pisanjem programa za obdelavo zalog. \n Čudovito je ne izgubljati časa za CreationTime, CreatorId. Polnijo se samodejno.",
"VideosLoginAndRegisterMessage": "Za ogled videoposnetkov se morate prijaviti. Če ga še niste, lahko ustvarite račun za uro.",
"Filter": "Filter",
"VideoCourses": "Video tečaji"
"VideoCourses": "Video tečaji",
"TestimonialText": "Vaše pričevanje",
"Position": "Položaj",
"ExperienceYear": "leta izkušenj",
"FullName": "Polno ime",
"CompanySize": "Velikost podjetja",
"Image": "Vaša profilna slika",
"TestimonialTitle": "Slišimo vaše pričevanje",
"TestimonialInfo": "Pomembno je, kaj pravijo naše stranke! ",
"Country": "Država",
"TestimonialTextPlaceholder": "Napišite kratko zgodbo o tem, kako vam je ABP pomagal zgraditi in izvesti vaš projekt. ",
"PositionPlaceholder": "Vaš položaj v vašem podjetju.",
"SelectExperienceYearPlaceholder": "Koliko let se že ukvarjate s programsko opremo",
"FullNamePlaceholder": "Tvoje polno ime.",
"CompanyNamePlaceholder": "Ime vašega podjetja.",
"SelectCompanySizePlaceholder": "Število zaposlenih",
"ImagePlaceholder": "Vaša slika.",
"SelectCountryPlaceholder": "Tvoja država.",
"YouAreNotAuthorizedToWriteTestimonial": "Če želite napisati izjavno pismo, se morate prijaviti.",
"UnAuthorizeTestimonialInfo": "Vaše mnenje je pomembno! ",
"TheFileIsTooLargeForImage": "Vaša profilna slika ne sme biti večja od 1 MB",
"ThisExtensionIsNotAllowedForImage": "Ta razširitev ni dovoljena.",
"FileUploadError": "Napaka pri nalaganju datoteke",
"TestimonialSend": "Hvala vam! ",
"Title": "Naslov",
"TitlePlaceholder": "Razvijalec programske opreme, tehnični direktor itd.",
"Characters": "znaki"
}
}

30
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/tr.json

@ -303,7 +303,7 @@
"Back": "Geri",
"SeeMore": "Daha fazla göster",
"DetailsOfTheEBook": "E-kitap detayları",
"JoinOurMarketingNewsletter": "Pazarlama bültenimize katılın",
"JoinOurMarketingNewsletter": "Pazarlama bültenimize katılın",
"FrameworkNewsletterConfirmationMessage": "<a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/TermsConditions\">Şartlar ve Koşulları</a> ve <a class=\"text-white fw-6 text-decoration-underline opacity-50\" href=\"https://commercial.abp.io/Privacy\">Gizlilik Politikasını</a> kabul ediyorum.",
"GetYourFreeEBook": "<span class=\"gradient-framework d-block\">Ücretsiz DDD E-kitabınızı</span> Alın ",
"EverythingYouNeedToKnow": "Bilmeniz gereken her şey",
@ -386,6 +386,32 @@
"ApplicationModuleExplanation2": "Modüler uygulamanız için modüller oluşturmak üzere bu seçeneği kullanabilirsiniz.",
"LeptonXLiteThemeInfo": " Modern ve şık bir Bootstrap UI teması. Üretime hazır bir UI temasına sahip olmak istiyorsanız idealdir. Bu en yeni temadır ve varsayılandır.",
"BasicThemeInfo": "Sade Bootstrap renkleri ve stilleri ile minimalist UI teması. Kendi UI temanızı oluşturacaksanız idealdir.",
"Details": "Detaylar"
"Details": "Detaylar",
"TestimonialText": "Referans yazısı",
"Position": "Ünvan",
"ExperienceYear": "Sektörel deneyim",
"FullName": "Ad soyad",
"CompanySize": "Şirket büyüklüğü",
"Image": "Profil resmi",
"TestimonialTitle": "Referanslarınızı paylaşın",
"TestimonialInfo": "Müşterilerimizin ne dediği önemlidir!",
"Country": "Ülke",
"TestimonialTextPlaceholder": "ABP'nin projenizi oluşturmanıza nasıl yardımcı olduğu hakkında kısa bir hikaye yazın.",
"PositionPlaceholder": "Şirketinizdeki pozisyonunuz",
"SelectExperienceYearPlaceholder": "Yazılım sektöründe kaç yıllık tecrübeye sahipsiniz?",
"FullNamePlaceholder": "Tam adınız",
"CompanyNamePlaceholder": "Şirketinizin ismi",
"SelectCompanySizePlaceholder": "Şirketinizin çalışan sayısı",
"ImagePlaceholder": "Profil resminiz",
"SelectCountryPlaceholder": "Ülkeniz",
"YouAreNotAuthorizedToWriteTestimonial": "Referans mektubu yazabilmek için giriş yapmalısınız.",
"UnAuthorizeTestimonialInfo": "Fikriniz bizim için önemli! Paylaşmak için giriş yapınız.",
"TheFileIsTooLargeForImage": "Profil resminiz 1 MB'tan fazla olamaz.",
"ThisExtensionIsNotAllowedForImage": "Bu dosya uzantısınız izin verilmiyor.",
"FileUploadError": "Dosya yükleme hatası",
"TestimonialSend": "Referansınızı paylaştığınız için teşekkürler!",
"Title": "Başlık",
"TitlePlaceholder": "Yazılım Geliştiricisi, CTO vb.",
"Characters": "karakter"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/vi.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework không chỉ là một framework mà còn là một hướng dẫn để phát triển/quản lý dự án vì nó cung cấp các khóa đào tạo về DDD, GenericRepository, DI, Microservice, moduleity. Ngay cả khi bạn không sử dụng framework, bạn vẫn có thể tự phát triển với docs.abp.io được chuẩn bị kỹ lưỡng và chuyên nghiệp. (OpenIddict, Redis, Quartz, v.v.) \n Bởi vì có nhiều thứ được xây dựng sẵn nên nó rút ngắn đáng kể thời gian phát triển dự án. (Chẳng hạn như trang đăng nhập, xử lý ngoại lệ, lọc dữ liệu, ghi nhật ký kiểm tra, bản địa hóa, bộ điều khiển api tự động, v.v.) \n Là một ví dụ từ ứng dụng của chúng tôi, tôi đã sử dụng Local Event Bus để kiểm soát hàng tồn kho. Vì vậy, tôi có thể quản lý việc di chuyển đơn hàng bằng cách viết trình xử lý hàng tồn kho. \n Thật tuyệt vời khi không lãng phí thời gian cho CreationTime, CreatorId. Chúng được điền tự động.",
"VideosLoginAndRegisterMessage": "Bạn phải đăng nhập để xem video. Bạn có thể tạo một tài khoản để xem nếu chưa có.",
"Filter": "Lọc",
"VideoCourses": "Khóa học video"
"VideoCourses": "Khóa học video",
"TestimonialText": "Lời chứng thực của bạn",
"Position": "Chức vụ",
"ExperienceYear": "Số năm kinh nghiệm",
"FullName": "Họ và tên",
"CompanySize": "Quy mô công ty",
"Image": "Hình ảnh cá nhân của bạn",
"TestimonialTitle": "Hãy nghe lời chứng thực của bạn",
"TestimonialInfo": "Những gì khách hàng của chúng tôi nói là quan trọng! ",
"Country": "Quốc gia",
"TestimonialTextPlaceholder": "Viết một câu chuyện ngắn gọn về cách ABP đã giúp bạn xây dựng và thực hiện dự án của mình. ",
"PositionPlaceholder": "Vị trí của bạn tại công ty của bạn.",
"SelectExperienceYearPlaceholder": "Bạn đã làm việc trong lĩnh vực phần mềm được bao nhiêu năm",
"FullNamePlaceholder": "Tên đầy đủ của bạn.",
"CompanyNamePlaceholder": "Tên công ty của bạn.",
"SelectCompanySizePlaceholder": "Số nhân viên",
"ImagePlaceholder": "Hình ảnh của bạn.",
"SelectCountryPlaceholder": "Quốc gia của bạn.",
"YouAreNotAuthorizedToWriteTestimonial": "Để có thể viết thư chứng thực, bạn phải đăng nhập.",
"UnAuthorizeTestimonialInfo": "Ý kiến của bạn rất quan trọng! ",
"TheFileIsTooLargeForImage": "Ảnh hồ sơ của bạn không thể lớn hơn 1 MB",
"ThisExtensionIsNotAllowedForImage": "Phần mở rộng này không được phép.",
"FileUploadError": "Lỗi tải tập tin lên",
"TestimonialSend": "Cảm ơn! ",
"Title": "Tiêu đề",
"TitlePlaceholder": "Nhà phát triển phần mềm, CTO, v.v.",
"Characters": "Ký tự"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework 不仅仅是一个框架,它还是项目开发/管理的指南,因为它提供了 DDD、GenericRepository、DI、Microservice、Modularity 培训。即使你不打算使用框架本身,你也可以通过 docs.abp.io 进行自我开发,它为你提供了精心准备的专业培训。(OpenIddict、Redis、Quartz 等)。\n因为很多东西都是预置的,所以大大缩短了项目开发时间。(如登录页面、异常处理、数据过滤-播种、审计日志、本地化、自动 api 控制器等)。\n以我们的应用程序为例,我将本地事件总线用于库存控制。因此,我可以通过编写库存处理程序来管理订单的变动。\n创建时间、CreatorId 不会浪费时间,它们会自动填入。它们会自动填充。",
"VideosLoginAndRegisterMessage": "您必须登录后才能观看视频。如果您还没有注册,可以创建一个账户进行观看。",
"Filter": "筛选",
"VideoCourses": "视频课程"
"VideoCourses": "视频课程",
"TestimonialText": "您的感言",
"Position": "位置",
"ExperienceYear": "多年经验",
"FullName": "全名",
"CompanySize": "公司规模",
"Image": "你的头像",
"TestimonialTitle": "让我们听听您的感言",
"TestimonialInfo": "客户的评价很重要!",
"Country": "国家",
"TestimonialTextPlaceholder": "写一个关于 ABP 如何帮助您构建和交付项目的简短故事。 ",
"PositionPlaceholder": "您在公司的职位。",
"SelectExperienceYearPlaceholder": "你从事软件工作多少年了",
"FullNamePlaceholder": "你的全名。",
"CompanyNamePlaceholder": "你的公司名称。",
"SelectCompanySizePlaceholder": "员工人数",
"ImagePlaceholder": "你的形象。",
"SelectCountryPlaceholder": "你的国家。",
"YouAreNotAuthorizedToWriteTestimonial": "为了能够撰写推荐信,您必须登录。",
"UnAuthorizeTestimonialInfo": "您的意见很重要,登录即可分享。",
"TheFileIsTooLargeForImage": "您的个人资料图片不能超过 1 MB",
"ThisExtensionIsNotAllowedForImage": "不允许此扩展。",
"FileUploadError": "文件上传错误",
"TestimonialSend": "谢谢你!",
"Title": "标题",
"TitlePlaceholder": "软件开发人员、CTO等",
"Characters": "字符"
}
}

28
abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hant.json

@ -440,6 +440,32 @@
"Index_Page_Testimonial_2": "ABP Framework不只是一個框架,它也是專案開發/管理的指南,因為它提供了DDD、GenericRepository、DI、Microservice、Modularity培訓。即使您不打算使用框架本身,您也可以使用經過充分專業準備的 docs.abp.io 進行開發。 (OpenIddict、Redis、Quartz 等) \n由於許多東西是預先建造的,因此它大大縮短了專案開發時間。 (例如登入頁面、異常處理、資料過濾播種、審核日誌記錄、本地化、自動 api 控制器等) \n作為我們應用程式的範例,我使用本地事件總線進行庫存控制。因此,我可以透過編寫庫存處理程序來管理訂單變更。 \n不浪費時間給CreationTime、CreatorId真是太好了。它們會自動填充。",
"VideosLoginAndRegisterMessage": "您必須登入才能觀看影片。如果您還沒有,您可以建立手錶帳戶。",
"Filter": "篩選",
"VideoCourses": "視訊課程"
"VideoCourses": "視訊課程",
"TestimonialText": "您的感言",
"Position": "位置",
"ExperienceYear": "多年经验",
"FullName": "全名",
"CompanySize": "公司规模",
"Image": "你的头像",
"TestimonialTitle": "让我们听听您的感言",
"TestimonialInfo": "客户的评价很重要!",
"Country": "国家",
"TestimonialTextPlaceholder": "写一个关于 ABP 如何帮助您构建和交付项目的简短故事。 ",
"PositionPlaceholder": "您在公司的职位。",
"SelectExperienceYearPlaceholder": "你从事软件工作多少年了",
"FullNamePlaceholder": "你的全名。",
"CompanyNamePlaceholder": "你的公司名称。",
"SelectCompanySizePlaceholder": "员工人数",
"ImagePlaceholder": "你的形象。",
"SelectCountryPlaceholder": "你的国家。",
"YouAreNotAuthorizedToWriteTestimonial": "为了能够撰写推荐信,您必须登录。",
"UnAuthorizeTestimonialInfo": "您的意见很重要,登录即可分享。",
"TheFileIsTooLargeForImage": "您的个人资料图片不能超过 1 MB",
"ThisExtensionIsNotAllowedForImage": "不允许此扩展。",
"FileUploadError": "文件上传错误",
"TestimonialSend": "谢谢你!",
"Title": "标题",
"TitlePlaceholder": "软件开发人员、CTO等",
"Characters": "字符"
}
}

1
docs/en/Audit-Logging.md

@ -46,6 +46,7 @@ Here, a list of the options you can configure:
* `ApplicationName`: If multiple applications are saving audit logs into a single database, set this property to your application name, so you can distinguish the logs of different applications. If you don't set, it will set from the `IApplicationInfoAccessor.ApplicationName` value, which is the entry assembly name by default.
* `IgnoredTypes`: A list of `Type`s to be ignored for audit logging. If this is an entity type, changes for this type of entities will not be saved. This list is also used while serializing the action parameters.
* `EntityHistorySelectors`: A list of selectors those are used to determine if an entity type is selected for saving the entity change. See the section below for details.
* `SaveEntityHistoryWhenNavigationChanges` (default: `true`): If you set to true, it will save entity changes to audit log when any navigation property changes.
* `Contributors`: A list of `AuditLogContributor` implementations. A contributor is a way of extending the audit log system. See the "Audit Log Contributors" section below.
* `AlwaysLogSelectors`: A list of selectors to save the audit logs for the matched criteria.

4
docs/en/Startup-Templates/Application.md

@ -197,7 +197,7 @@ In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an a
Test projects are prepared for integration testing;
* It is fully integrated into the ABP framework and all services in your application.
* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library.
* It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library.
* Authorization is disabled, so any application service can be easily used in tests.
You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all the initialization processes).
@ -329,7 +329,7 @@ You should add `routes` property in the `data` object to add a link on the menu
```
In the above example;
* If the user is not logged in, authGuard blocks access and redirects to the login page.
* PermissionGuard checks the user's permission with the `requiredPolicy` property of the `routes` object. If the user is not authorized to access the page, the 403 page appears.
* permissionGuard checks the user's permission with the `requiredPolicy` property of the `routes` object. If the user is not authorized to access the page, the 403 page appears.
* The `name` property of `routes` is the menu link label. A localization key can be defined.
* The `iconClass` property of the `routes` object is the menu link icon class.
* The `requiredPolicy` property of the `routes` object is the required policy key to access the page.

2
docs/en/Startup-Templates/Module.md

@ -110,7 +110,7 @@ In addition, `.HttpApi.Client.ConsoleTestApp` is a console application (not an a
Test projects are prepared for integration testing;
- It is fully integrated to ABP framework and all services in your application.
- It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library.
- It uses SQLite in-memory database for EF Core. For MongoDB, it uses the [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library.
- Authorization is disabled, so any application service can be easily used in tests.
You can still create unit tests for your classes which will be harder to write (because you will need to prepare mock/fake objects), but faster to run (because it only tests a single class and skips all initialization process).

2
docs/en/Testing.md

@ -431,7 +431,7 @@ ABP Provides a complete infrastructure to write integration tests. All the ABP i
#### The Database
The startup template is configured to use **in-memory SQLite** database for the EF Core (for MongoDB, it uses [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) library). So, all the configuration and queries are performed against a real database and you can even test database transactions.
The startup template is configured to use **in-memory SQLite** database for the EF Core (for MongoDB, it uses [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) library). So, all the configuration and queries are performed against a real database and you can even test database transactions.
Using in-memory SQLite database has two main advantages;

2
docs/en/Tutorials/Part-4.md

@ -64,7 +64,7 @@ Each project is used to test the related project. Test projects use the followin
{{else if DB=="Mongo"}}
> **[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)** library is used to mock the MongoDB database. A separate database instance is created and seeded (with the [data seed system](../Data-Seeding.md)) to prepare a fresh database for every test.
> **[EphemeralMongo](https://github.com/asimmon/ephemeral-mongo)** library is used to mock the MongoDB database. A separate database instance is created and seeded (with the [data seed system](../Data-Seeding.md)) to prepare a fresh database for every test.
{{end}}

2
docs/en/UI/Angular/Permission-Management.md

@ -56,7 +56,7 @@ As shown above you can remove elements from DOM with `abpPermission` structural
You can use `permissionGuard` if you want to control authenticated user's permission to access to the route during navigation.
* Import the PermissionGuard from @abp/ng.core.
* Import the permissionGuard from @abp/ng.core.
* Add `canActivate: [permissionGuard]` to your route object.
* Add `requiredPolicy` to the `data` property of your route in your routing module.

4
docs/en/UI/Blazor/Basic-Theme.md

@ -86,10 +86,10 @@ You can simply override the styles in the Global Styles file of your application
See the [Customization / Overriding Components](Customization-Overriding-Components.md) to learn how you can replace components, customize and extend the user interface.
### Overriding the Menu Item
Basic theme supports overriding a single menu item with a custom component. You can create a custom component and call `UseComponent` extension method of Basic Theme in the **MenuContributor**.
Basic theme supports overriding a single menu item with a custom component. You can create a custom component and call `UseComponent` extension method in the **MenuContributor**.
```csharp
using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Navigation;
using Volo.Abp.UI.Navigation;
//...

2
docs/pt-BR/Startup-Templates/Application.md

@ -192,7 +192,7 @@ Além disso, `.HttpApi.Client.ConsoleTestApp`é um aplicativo de console (não u
Projetos de teste são preparados para testes de integração;
- É totalmente integrado à estrutura ABP e a todos os serviços em sua aplicação.
- Ele usa o banco de dados SQLite na memória para o EF Core. Para o MongoDB, ele usa a biblioteca [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) .
- Ele usa o banco de dados SQLite na memória para o EF Core. Para o MongoDB, ele usa a biblioteca [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) .
- A autorização está desabilitada, portanto, qualquer serviço de aplicativo pode ser facilmente usado em testes.
Você ainda pode criar testes de unidade para suas classes, que serão mais difíceis de escrever (porque você precisará preparar objetos simulados / falsos), mas mais rápidos de executar (porque apenas testa uma única classe e ignora todo o processo de inicialização).

2
docs/pt-BR/Startup-Templates/Module.md

@ -110,7 +110,7 @@ Além disso, `.HttpApi.Client.ConsoleTestApp`é um aplicativo de console (não u
Projetos de teste são preparados para testes de integração;
- É totalmente integrado à estrutura ABP e a todos os serviços em sua aplicação.
- Ele usa o banco de dados SQLite na memória para o EF Core. Para o MongoDB, ele usa a biblioteca [Mongo2Go](https://github.com/Mongo2Go/Mongo2Go) .
- Ele usa o banco de dados SQLite na memória para o EF Core. Para o MongoDB, ele usa a biblioteca [EphemeralMongo](https://github.com/asimmon/ephemeral-mongo) .
- A autorização está desabilitada, portanto, qualquer serviço de aplicativo pode ser facilmente usado em testes.
Você ainda pode criar testes de unidade para suas classes, que serão mais difíceis de escrever (porque você precisará preparar objetos simulados / falsos), mas mais rápidos de executar (porque apenas testa uma única classe e ignora todo o processo de inicialização).

4
docs/zh-Hans/Startup-Templates/Application.md

@ -209,7 +209,7 @@ ABP有[动态 C# API 客户端](../API/Dynamic-CSharp-API-Clients.md)功能,所
测试项目是用于做集成测试的:
* 它完全集成到ABP框架和应用程序的所有服务.
* 如果数据库提供程序是EF Core,测试项目会使用SQLite内存数据库,如果是MongoDB,它使用[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)库.
* 如果数据库提供程序是EF Core,测试项目会使用SQLite内存数据库,如果是MongoDB,它使用[EphemeralMongo](https://github.com/asimmon/ephemeral-mongo)库.
* 授权被禁用,任何的应用服务都可以在测试中轻松调用.
你依然可以编写单元测试,只不过它很难写(因为你需要准备mock/fake对象),但它的运行速度更快(因为只测试单个类并跳过所有初始化过程).
@ -314,7 +314,7 @@ ABP 配置模块也已经导入到 `AppModule` 中, 以满足可延迟加载 ABP
}
```
在上面的例子中;
* 如果用户没有登录, AuthGuard 会阻塞访问并重定向到登录页面.
* 如果用户没有登录, authGuard 会阻塞访问并重定向到登录页面.
* permissionGuard 使用 `rotues` 对象的 `requiredPolicy` 属性检查用户的权限. 如果用户未被授权访问该页, 则显示403页.
* `routes``name` 属性是菜单链接标签. 可以定义本地化 key.
* `routes` 对象的 `iconClass` 属性是菜单链接图标类.

2
docs/zh-Hans/Startup-Templates/Module.md

@ -110,7 +110,7 @@ abp new Acme.IssueManagement -t module --no-ui
测试项目是用于做集成测试的:
* 它完全集成到ABP框架和应用程序的所有服务.
* 如果数据库提供程序是EF Core,测试项目会使用SQLite内存数据库,如果是MongoDB,它使用[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)库.
* 如果数据库提供程序是EF Core,测试项目会使用SQLite内存数据库,如果是MongoDB,它使用[EphemeralMongo](https://github.com/asimmon/ephemeral-mongo)库.
* 授权被禁用,任何的应用服务都可以在测试中轻松调用.
你依然可以编写单元测试,只不过它很难写(因为你需要准备mock/fake对象),但它的运行速度更快(因为只测试单个类并跳过所有初始化过程).

2
docs/zh-Hans/Testing.md

@ -431,7 +431,7 @@ ABP为编写集成测试提供了完整的基础设施. 所有ABP基础设施和
#### 数据库
启动模板使用EF Core配置**内存中的SQLite**数据库(对于MongoDB, 它使用[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)). 因此, 所有配置和查询都是针对真实数据库执行的, 你甚至可以测试数据库事务.
启动模板使用EF Core配置**内存中的SQLite**数据库(对于MongoDB, 它使用[EphemeralMongo](https://github.com/asimmon/ephemeral-mongo)). 因此, 所有配置和查询都是针对真实数据库执行的, 你甚至可以测试数据库事务.
使用内存中的SQLite数据库有两个主要优点:

114
docs/zh-Hans/Tutorials/Part-10.md

@ -622,79 +622,79 @@ using System.Threading.Tasks;
using Acme.BookStore.Authors;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Modularity;
using Volo.Abp.Validation;
using Xunit;
namespace Acme.BookStore.Books
{ {{if DB=="Mongo"}}
[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}}
public class BookAppService_Tests : BookStoreApplicationTestBase
namespace Acme.BookStore.Books;
public abstract class BookAppService_Tests<TStartupModule> : BookStoreApplicationTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private readonly IBookAppService _bookAppService;
private readonly IAuthorAppService _authorAppService;
protected BookAppService_Tests()
{
private readonly IBookAppService _bookAppService;
private readonly IAuthorAppService _authorAppService;
_bookAppService = GetRequiredService<IBookAppService>();
_authorAppService = GetRequiredService<IAuthorAppService>();
}
public BookAppService_Tests()
{
_bookAppService = GetRequiredService<IBookAppService>();
_authorAppService = GetRequiredService<IAuthorAppService>();
}
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "1984" &&
b.AuthorName == "George Orwell");
}
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
[Fact]
public async Task Should_Create_A_Valid_Book()
{
var authors = await _authorAppService.GetListAsync(new GetAuthorListDto());
var firstAuthor = authors.Items.First();
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "1984" &&
b.AuthorName == "George Orwell");
}
//Act
var result = await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
AuthorId = firstAuthor.Id,
Name = "New test book 42",
Price = 10,
PublishDate = System.DateTime.Now,
Type = BookType.ScienceFiction
}
);
[Fact]
public async Task Should_Create_A_Valid_Book()
{
var authors = await _authorAppService.GetListAsync(new GetAuthorListDto());
var firstAuthor = authors.Items.First();
//Assert
result.Id.ShouldNotBe(Guid.Empty);
result.Name.ShouldBe("New test book 42");
}
//Act
var result = await _bookAppService.CreateAsync(
[Fact]
public async Task Should_Not_Create_A_Book_Without_Name()
{
var exception = await Assert.ThrowsAsync<AbpValidationException>(async () =>
{
await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
AuthorId = firstAuthor.Id,
Name = "New test book 42",
Name = "",
Price = 10,
PublishDate = System.DateTime.Now,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
});
//Assert
result.Id.ShouldNotBe(Guid.Empty);
result.Name.ShouldBe("New test book 42");
}
[Fact]
public async Task Should_Not_Create_A_Book_Without_Name()
{
var exception = await Assert.ThrowsAsync<AbpValidationException>(async () =>
{
await _bookAppService.CreateAsync(
new CreateUpdateBookDto
{
Name = "",
Price = 10,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
});
exception.ValidationErrors
.ShouldContain(err => err.MemberNames.Any(m => m == "Name"));
}
exception.ValidationErrors
.ShouldContain(err => err.MemberNames.Any(m => m == "Name"));
}
}
```

78
docs/zh-Hans/Tutorials/Part-4.md

@ -67,7 +67,7 @@
{{else if DB=="Mongo"}}
> **[Mongo2Go](https://github.com/Mongo2Go/Mongo2Go)**库用于模拟MongoDB数据库. 创建一个单独的数据库实例并使用[数据种子系统](../Data-Seeding.md)初始化种子数据,为每个测试准备一个新的数据库.
> **[EphemeralMongo](https://github.com/asimmon/ephemeral-mongo)**库用于模拟MongoDB数据库. 创建一个单独的数据库实例并使用[数据种子系统](../Data-Seeding.md)初始化种子数据,为每个测试准备一个新的数据库.
{{end}}
@ -85,36 +85,70 @@ using System.Linq;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Modularity;
using Volo.Abp.Validation;
using Xunit;
namespace Acme.BookStore.Books
{ {{if DB=="Mongo"}}
[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}}
public class BookAppService_Tests : BookStoreApplicationTestBase
{
private readonly IBookAppService _bookAppService;
namespace Acme.BookStore.Books;
public BookAppService_Tests()
{
_bookAppService = GetRequiredService<IBookAppService>();
}
public abstract class BookAppService_Tests<TStartupModule> : BookStoreApplicationTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private readonly IBookAppService _bookAppService;
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
protected BookAppService_Tests()
{
_bookAppService = GetRequiredService<IBookAppService>();
}
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "1984");
}
[Fact]
public async Task Should_Get_List_Of_Books()
{
//Act
var result = await _bookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
//Assert
result.TotalCount.ShouldBeGreaterThan(0);
result.Items.ShouldContain(b => b.Name == "1984");
}
}
````
{{if DB == "EF"}}
添加 `BookAppService_Tests` 的实现类,命名为 `EfCoreBookAppService_Tests` ,并放置在 `EntityFrameworkCore\Applications\Books` 命名空间 (文件夹)下,在 `Acme.BookStore.EntityFrameworkCore.Tests` 项目中:
````csharp
using Acme.BookStore.Books;
using Xunit;
namespace Acme.BookStore.EntityFrameworkCore.Applications.Books;
[Collection(BookStoreTestConsts.CollectionDefinitionName)]
public class EfCoreBookAppService_Tests : BookAppService_Tests<BookStoreEntityFrameworkCoreTestModule>
{
}
````
{{end}}
{{if DB == "Mongo"}}
添加 `BookAppService_Tests` 的实现类,命名为`MongoDBBookAppService_Tests` ,并放置在 `MongoDb\Applications\Books` 命名空间 (文件夹)下,在 `Acme.BookStore.MongoDB.Tests` 项目中:
````csharp
using Acme.BookStore.MongoDB;
using Acme.BookStore.Books;
using Xunit;
namespace Acme.BookStore.MongoDb.Applications.Books;
[Collection(BookStoreTestConsts.CollectionDefinitionName)]
public class MongoDBBookAppService_Tests : BookAppService_Tests<BookStoreMongoDbTestModule>
{
}
````
{{end}}
* 测试方法 `Should_Get_List_Of_Books` 直接使用 `BookAppService.GetListAsync` 方法来获取用户列表,并执行检查.
* 我们可以安全地检查 "1984" 这本书的名称,因为我们知道这本书可以在数据库中找到,我们已将其添加到种子数据中.

139
docs/zh-Hans/Tutorials/Part-8.md

@ -497,77 +497,112 @@ namespace Acme.BookStore
using System;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Modularity;
using Xunit;
namespace Acme.BookStore.Authors
{ {{if DB=="Mongo"}}
[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}}
public class AuthorAppService_Tests : BookStoreApplicationTestBase
namespace Acme.BookStore.Authors;
public abstract class AuthorAppService_Tests<TStartupModule> : BookStoreApplicationTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private readonly IAuthorAppService _authorAppService;
protected AuthorAppService_Tests()
{
private readonly IAuthorAppService _authorAppService;
_authorAppService = GetRequiredService<IAuthorAppService>();
}
public AuthorAppService_Tests()
{
_authorAppService = GetRequiredService<IAuthorAppService>();
}
[Fact]
public async Task Should_Get_All_Authors_Without_Any_Filter()
{
var result = await _authorAppService.GetListAsync(new GetAuthorListDto());
[Fact]
public async Task Should_Get_All_Authors_Without_Any_Filter()
{
var result = await _authorAppService.GetListAsync(new GetAuthorListDto());
result.TotalCount.ShouldBeGreaterThanOrEqualTo(2);
result.Items.ShouldContain(author => author.Name == "George Orwell");
result.Items.ShouldContain(author => author.Name == "Douglas Adams");
}
result.TotalCount.ShouldBeGreaterThanOrEqualTo(2);
result.Items.ShouldContain(author => author.Name == "George Orwell");
result.Items.ShouldContain(author => author.Name == "Douglas Adams");
}
[Fact]
public async Task Should_Get_Filtered_Authors()
{
var result = await _authorAppService.GetListAsync(
new GetAuthorListDto {Filter = "George"});
[Fact]
public async Task Should_Get_Filtered_Authors()
{
var result = await _authorAppService.GetListAsync(
new GetAuthorListDto {Filter = "George"});
result.TotalCount.ShouldBeGreaterThanOrEqualTo(1);
result.Items.ShouldContain(author => author.Name == "George Orwell");
result.Items.ShouldNotContain(author => author.Name == "Douglas Adams");
}
result.TotalCount.ShouldBeGreaterThanOrEqualTo(1);
result.Items.ShouldContain(author => author.Name == "George Orwell");
result.Items.ShouldNotContain(author => author.Name == "Douglas Adams");
}
[Fact]
public async Task Should_Create_A_New_Author()
{
var authorDto = await _authorAppService.CreateAsync(
new CreateAuthorDto
{
Name = "Edward Bellamy",
BirthDate = new DateTime(1850, 05, 22),
ShortBio = "Edward Bellamy was an American author..."
}
);
authorDto.Id.ShouldNotBe(Guid.Empty);
authorDto.Name.ShouldBe("Edward Bellamy");
}
[Fact]
public async Task Should_Create_A_New_Author()
[Fact]
public async Task Should_Not_Allow_To_Create_Duplicate_Author()
{
await Assert.ThrowsAsync<AuthorAlreadyExistsException>(async () =>
{
var authorDto = await _authorAppService.CreateAsync(
await _authorAppService.CreateAsync(
new CreateAuthorDto
{
Name = "Edward Bellamy",
BirthDate = new DateTime(1850, 05, 22),
ShortBio = "Edward Bellamy was an American author..."
Name = "Douglas Adams",
BirthDate = DateTime.Now,
ShortBio = "..."
}
);
});
}
authorDto.Id.ShouldNotBe(Guid.Empty);
authorDto.Name.ShouldBe("Edward Bellamy");
}
//TODO: Test other methods...
}
````
[Fact]
public async Task Should_Not_Allow_To_Create_Duplicate_Author()
{
await Assert.ThrowsAsync<AuthorAlreadyExistsException>(async () =>
{
await _authorAppService.CreateAsync(
new CreateAuthorDto
{
Name = "Douglas Adams",
BirthDate = DateTime.Now,
ShortBio = "..."
}
);
});
}
{{if DB == "EF"}}
添加 `AuthorAppService_Tests` 的实现类,命名为 `EfCoreAuthorAppService_Tests` ,并放置在 `EntityFrameworkCore\Applications\Authors` 命名空间 (文件夹)下,在 `Acme.BookStore.EntityFrameworkCore.Tests` 项目中:
````csharp
using Acme.BookStore.Authors;
using Xunit;
namespace Acme.BookStore.EntityFrameworkCore.Applications.Authors;
[Collection(BookStoreTestConsts.CollectionDefinitionName)]
public class EfCoreAuthorAppService_Tests : AuthorAppService_Tests<BookStoreEntityFrameworkCoreTestModule>
{
//TODO: Test other methods...
}
}
````
{{end}}
{{if DB == "Mongo"}}
添加 `AuthorAppService_Tests` 的实现类,命名为 `MongoDBAuthorAppService_Tests` ,并放置在 `MongoDb\Applications\Authors` 命名空间 (文件夹)下,在 `Acme.BookStore.MongoDB.Tests` 项目中:
````csharp
using Acme.BookStore.MongoDB;
using Acme.BookStore.Authors;
using Xunit;
namespace Acme.BookStore.MongoDb.Applications.Authors;
[Collection(BookStoreTestConsts.CollectionDefinitionName)]
public class MongoDBAuthorAppService_Tests : AuthorAppService_Tests<BookStoreMongoDbTestModule>
{
}
````
{{end}}
完成应用服务方法的测试, 它们应该很容易理解.

46
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicformTagHelperService.cs

@ -22,11 +22,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicFormTagHelper>
{
private readonly HtmlEncoder _htmlEncoder;
private readonly IHtmlGenerator _htmlGenerator;
private readonly IServiceProvider _serviceProvider;
private readonly IStringLocalizer<AbpUiResource> _localizer;
private List<ModelExpression> _models = new();
protected HtmlEncoder HtmlEncoder { get; }
protected IHtmlGenerator HtmlGenerator { get; }
protected IServiceProvider _serviceProvider { get; }
protected IStringLocalizer<AbpUiResource> Localizer { get; }
protected List<ModelExpression> Models = new();
public AbpDynamicFormTagHelperService(
HtmlEncoder htmlEncoder,
@ -34,15 +34,15 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
IServiceProvider serviceProvider,
IStringLocalizer<AbpUiResource> localizer)
{
_htmlEncoder = htmlEncoder;
_htmlGenerator = htmlGenerator;
HtmlEncoder = htmlEncoder;
HtmlGenerator = htmlGenerator;
_serviceProvider = serviceProvider;
_localizer = localizer;
Localizer = localizer;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
_models = GetModels(context, output);
Models = GetModels(context, output);
var list = InitilizeFormGroupContentsContext(context, output);
NormalizeTagMode(context, output);
@ -64,7 +64,7 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
protected virtual async Task ConvertToMvcForm(TagHelperContext context, TagHelperOutput output)
{
var formTagHelper = new FormTagHelper(_htmlGenerator)
var formTagHelper = new FormTagHelper(HtmlGenerator)
{
Action = TagHelper.Action,
Controller = TagHelper.Controller,
@ -159,7 +159,7 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
protected virtual async Task ProcessFieldsAsync(TagHelperContext context, TagHelperOutput output)
{
foreach (var model in _models)
foreach (var model in Models)
{
if (IsSelectGroup(context, model))
{
@ -176,21 +176,21 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
}
}
private async Task ProcessDateGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model)
protected virtual async Task ProcessDateGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model)
{
var abpDateTagHelper = GetDateGroupTagHelper(context, output, model);
await abpDateTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
await abpDateTagHelper.RenderAsync(new TagHelperAttributeList(), context, HtmlEncoder, "div", TagMode.StartTagAndEndTag);
}
private AbpTagHelper GetDateGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
protected virtual AbpTagHelper GetDateGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
{
return IsDateRangeGroup(model.ModelExplorer)
? GetAbpDateRangeInputTagHelper(context, output, model)
: GetAbpDateInputTagHelper(model);
}
private AbpTagHelper GetAbpDateInputTagHelper(ModelExpression model)
protected virtual AbpTagHelper GetAbpDateInputTagHelper(ModelExpression model)
{
var abpDateInputTagHelper = _serviceProvider.GetRequiredService<AbpDatePickerTagHelper>();
abpDateInputTagHelper.AspFor = model;
@ -199,7 +199,7 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
return abpDateInputTagHelper;
}
private AbpTagHelper GetAbpDateRangeInputTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
protected virtual AbpTagHelper GetAbpDateRangeInputTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
{
var modelAttribute = model.ModelExplorer.GetAttribute<DateRangePickerAttribute>()!;
@ -223,13 +223,13 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
return abpDateRangeInputTagHelper;
}
private bool TryToGetOtherDateModel(ModelExpression model, string pickerId, out ModelExplorer? otherModel)
protected virtual bool TryToGetOtherDateModel(ModelExpression model, string pickerId, out ModelExplorer? otherModel)
{
otherModel = _models.Select(x => x.ModelExplorer).SingleOrDefault(x => x != model.ModelExplorer && x.GetAttribute<DateRangePickerAttribute>()?.PickerId == pickerId);
otherModel = Models.Select(x => x.ModelExplorer).SingleOrDefault(x => x != model.ModelExplorer && x.GetAttribute<DateRangePickerAttribute>()?.PickerId == pickerId);
return otherModel != null;
}
private static bool IsDateRangeGroup(ModelExplorer modelModelExplorer)
protected virtual bool IsDateRangeGroup(ModelExplorer modelModelExplorer)
{
return modelModelExplorer.GetAttribute<DateRangePickerAttribute>() != null;
}
@ -245,7 +245,7 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
{
var abpSelectTagHelper = GetSelectGroupTagHelper(context, output, model);
await abpSelectTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
await abpSelectTagHelper.RenderAsync(new TagHelperAttributeList(), context, HtmlEncoder, "div", TagMode.StartTagAndEndTag);
}
protected virtual AbpTagHelper GetSelectGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
@ -280,10 +280,10 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
{
var abpButtonTagHelper = _serviceProvider.GetRequiredService<AbpButtonTagHelper>();
var attributes = new TagHelperAttributeList { new TagHelperAttribute("type", "submit") };
abpButtonTagHelper.Text = _localizer["Submit"];
abpButtonTagHelper.Text = Localizer["Submit"];
abpButtonTagHelper.ButtonType = AbpButtonType.Primary;
return await abpButtonTagHelper.RenderAsync(attributes, context, _htmlEncoder, "button", TagMode.StartTagAndEndTag);
return await abpButtonTagHelper.RenderAsync(attributes, context, HtmlEncoder, "button", TagMode.StartTagAndEndTag);
}
protected virtual async Task ProcessInputGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model)
@ -293,7 +293,7 @@ public class AbpDynamicFormTagHelperService : AbpTagHelperService<AbpDynamicForm
abpInputTagHelper.ViewContext = TagHelper.ViewContext;
abpInputTagHelper.DisplayRequiredSymbol = TagHelper.RequiredSymbols ?? true;
await abpInputTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag);
await abpInputTagHelper.RenderAsync(new TagHelperAttributeList(), context, HtmlEncoder, "div", TagMode.StartTagAndEndTag);
}
protected virtual List<ModelExpression> GetModels(TagHelperContext context, TagHelperOutput output)

52
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerBaseTagHelperService.cs

@ -68,7 +68,6 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
protected readonly IAbpTagHelperLocalizer TagHelperLocalizer;
protected virtual string TagName { get; set; } = "abp-date-picker";
protected IStringLocalizer<AbpUiResource> L { get; }
protected InputTagHelper InputTagHelper { get; set; }
protected abstract TagHelperOutput TagHelperOutput { get; set; }
protected AbpDatePickerBaseTagHelperService(IJsonSerializer jsonSerializer, IHtmlGenerator generator,
@ -81,8 +80,6 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
ServiceProvider = serviceProvider;
L = l;
TagHelperLocalizer = tagHelperLocalizer;
InputTagHelper = new InputTagHelper(Generator) { InputTypeName = "text" };
}
protected virtual T? GetAttribute<T>() where T : Attribute
@ -95,19 +92,7 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
TagHelperOutput = new TagHelperOutput("input", GetInputAttributes(context, output), (_, _) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
InputTagHelper.ViewContext = TagHelper.ViewContext;
if (!TagHelper.Name.IsNullOrEmpty())
{
InputTagHelper.Name = TagHelper.Name;
}
if (!TagHelper.Value.IsNullOrEmpty())
{
InputTagHelper.Value = TagHelper.Value;
}
TagHelperOutput = TagHelperOutput = new TagHelperOutput("input", GetInputAttributes(context, output), (_, _) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
AddDisabledAttribute(TagHelperOutput);
AddAutoFocusAttribute(TagHelperOutput);
@ -131,7 +116,7 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
var labelContent = await GetLabelAsHtmlAsync(context, output, TagHelperOutput);
var infoContent = GetInfoAsHtml(context, output, TagHelperOutput);
var validationContent = await GetValidationAsHtmlAsync(context, output);
var validationContent = await GetValidationAsHtmlAsync(context, TagHelperOutput);
var inputGroup = new TagHelperOutput("div",
new TagHelperAttributeList(new[] { new TagHelperAttribute("class", "input-group") }),
@ -270,12 +255,12 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
if (options.MinDate != null)
{
attrList.Add("data-min-date", options.MinDate);
attrList.Add("data-min-date", options.MinDate?.ToString("O"));
}
if (options.MaxDate != null)
{
attrList.Add("data-max-date", options.MaxDate);
attrList.Add("data-max-date", options.MaxDate?.ToString("O"));
}
if (options.MaxSpan != null)
@ -754,16 +739,37 @@ public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelp
};
}
protected abstract Task<string> GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output);
protected virtual Task<string> GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output)
{
var @for = GetModelExpression();
if (@for == null)
{
return Task.FromResult(string.Empty);
}
return GetValidationAsHtmlByInputAsync(context, output, @for);
}
protected virtual async Task<string> GetValidationAsHtmlByInputAsync(TagHelperContext context,
TagHelperOutput output,
[NotNull]InputTagHelper inputTag)
[NotNull]ModelExpression @for)
{
var validationMessageTagHelper =
new ValidationMessageTagHelper(Generator) { For = inputTag.For, ViewContext = TagHelper.ViewContext };
new ValidationMessageTagHelper(Generator) { For = @for, ViewContext = TagHelper.ViewContext };
var attributeList = new TagHelperAttributeList { { "class", "text-danger col-auto" } };
var attributeList = new TagHelperAttributeList { { "class", "text-danger" } };
if(!output.Attributes.TryGetAttribute("name", out var nameAttribute) || nameAttribute == null || nameAttribute.Value == null)
{
if (nameAttribute != null)
{
output.Attributes.Remove(nameAttribute);
}
nameAttribute = new TagHelperAttribute("name", "date_" + Guid.NewGuid().ToString("N"));
output.Attributes.Add(nameAttribute);
}
attributeList.Add("data-valmsg-for", nameAttribute.Value);
return await validationMessageTagHelper.RenderAsync(attributeList, context, Encoder, "span",
TagMode.StartTagAndEndTag);

5
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDatePickerTagHelperService.cs

@ -77,11 +77,6 @@ public class AbpDatePickerTagHelperService : AbpDatePickerBaseTagHelperService<A
return TagHelper.AspFor;
}
protected async override Task<string> GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output)
{
return DateTagHelper != null ? await GetValidationAsHtmlByInputAsync(context, output, DateTagHelper) : string.Empty;
}
protected override string GetExtraInputHtml(TagHelperContext context, TagHelperOutput output)
{
return DateTagHelperOutput?.Render(Encoder)!;

19
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/DatePicker/AbpDateRangePickerTagHelperService.cs

@ -112,23 +112,6 @@ public class AbpDateRangePickerTagHelperService : AbpDatePickerBaseTagHelperServ
protected override ModelExpression? GetModelExpression()
{
return TagHelper.AspForStart;
}
protected async override Task<string> GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output)
{
var validationHtml = string.Empty;
if (StartDateTagHelper != null)
{
validationHtml += await GetValidationAsHtmlByInputAsync(context, output, StartDateTagHelper);
}
if (EndDateTagHelper != null)
{
validationHtml += await GetValidationAsHtmlByInputAsync(context, output, EndDateTagHelper);
}
return validationHtml;
return TagHelper.AspForStart ?? TagHelper.AspForEnd;
}
}

42
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/date-range-picker/date-range-picker-extensions.js

@ -205,7 +205,7 @@
var today = moment();
$dateRangePicker.setStartDate(today);
$dateRangePicker.setEndDate(today);
if(options.singleDatePicker && options.autoApply){
$dateRangePicker.clickApply();
}else{
@ -366,6 +366,14 @@
});
}
if (options.maxDate){
options.maxDate = convertToMoment(options.maxDate, options);
}
if (options.minDate){
options.minDate = convertToMoment(options.minDate, options);
}
if (typeof options.template !== 'string' && !(options.template instanceof $))
options.template =
'<div class="daterangepicker">' +
@ -433,13 +441,13 @@
return '';
}
function createInitialAbpDate(date, options) {
date = convertToMoment(date, options, undefined, options.isUtc);
if (options.isUtc) {
date = date.local();
}
return AbpDate(date, options);
}
@ -468,8 +476,9 @@
var singleOpenAndClearButton = options.singleOpenAndClearButton && $clearButton.length > 0 && $openButton.length > 0;
var startDate = createInitialAbpDate(options.startDate || options.date || (options.autoUpdateInput ? new Date() : undefined), options);
var oldStartDate = AbpDate(undefined, options);
var endDate = createInitialAbpDate(options.endDate || (options.autoUpdateInput ? new Date() : undefined), options);
var oldEndDate = AbpDate(undefined, options);
@ -544,6 +553,10 @@
triggerDateChange($input, startDate, isDateRangePickerTrigger);
}
}
if(isTrigger || isInputTrigger || isDateRangePickerTrigger){
triggerValidation();
}
}
function setDataDates(date, $selfInput, prefix){
@ -553,6 +566,25 @@
$input.data(prefix + 'date', date);
}
function triggerValidation() {
checkValidity($startDateInput);
checkValidity($endDateInput);
checkValidity($dateInput);
checkValidity($input);
}
function checkValidity($selfInput) {
if (!$selfInput) {
return;
}
if($selfInput.closest('form').length === 0) {
return;
}
$selfInput.valid();
}
function triggerDateChange($selfInput, value, isDateRangePickerTrigger) {
$selfInput.trigger('change');
if(isDateRangePickerTrigger !== false){
@ -583,7 +615,7 @@
}else{
picker.setStartDate(convertToMoment(startDate, options, options.inputDateFormat));
}
if(singleDatePicker){
picker.setEndDate(picker.startDate);
}else if(isEmptyDate(endDate, options)){

6
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs

@ -53,6 +53,12 @@ public class AbpAuditingOptions
public IEntityHistorySelectorList EntityHistorySelectors { get; }
/// <summary>
/// Default: true.
/// Save entity changes to audit log when any navigation property changes.
/// </summary>
public bool SaveEntityHistoryWhenNavigationChanges { get; set; } = true;
//TODO: Move this to asp.net core layer or convert it to a more dynamic strategy?
/// <summary>
/// Default: false.

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs

@ -1,6 +1,7 @@
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Commands.Internal;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.ServiceProxying;
using Volo.Abp.Cli.ServiceProxying.Angular;
@ -68,6 +69,7 @@ public class AbpCliCoreModule : AbpModule
options.Commands[CleanCommand.Name] = typeof(CleanCommand);
options.Commands[CliCommand.Name] = typeof(CliCommand);
options.Commands[ClearDownloadCacheCommand.Name] = typeof(ClearDownloadCacheCommand);
options.Commands[RecreateInitialMigrationCommand.Name] = typeof(RecreateInitialMigrationCommand);
options.DisabledModulesToAddToSolution.Add("Volo.Abp.LeptonXTheme.Pro");
options.DisabledModulesToAddToSolution.Add("Volo.Abp.LeptonXTheme.Lite");

89
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Internal/RecreateInitialMigrationCommand.cs

@ -0,0 +1,89 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Cli.Args;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands.Internal;
public class RecreateInitialMigrationCommand : IConsoleCommand, ITransientDependency
{
public const string Name = "recreate-initial-migration";
public ILogger<RecreateInitialMigrationCommand> Logger { get; set; }
protected CmdHelper CmdHelper { get; }
public RecreateInitialMigrationCommand(CmdHelper cmdHelper)
{
CmdHelper = cmdHelper;
Logger = NullLogger<RecreateInitialMigrationCommand>.Instance;
}
public virtual Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
var csprojFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj", SearchOption.AllDirectories)
.Where(x => x.Contains("templates") || x.Contains("test-app"))
.Where(x => File.ReadAllText(x).Contains("Microsoft.EntityFrameworkCore.Tools")).ToList();
var projectCounts = 0;
foreach (var csprojFile in csprojFiles)
{
var projectDir = Path.GetDirectoryName(csprojFile)!;
if (!Directory.Exists(Path.Combine(projectDir, "Migrations")))
{
continue;
}
Logger.LogInformation($"Recreating migrations for {csprojFile}");
if (Directory.Exists(Path.Combine(projectDir, "Migrations")))
{
Directory.Delete(Path.Combine(projectDir, "Migrations"), true);
}
var separateDbContext = false;
if (Directory.Exists(Path.Combine(projectDir, "TenantMigrations")))
{
Directory.Delete(Path.Combine(projectDir, "TenantMigrations"), true);
separateDbContext = true;
}
if (!separateDbContext)
{
CmdHelper.RunCmd($"dotnet ef migrations add Initial", workingDirectory: projectDir);
}
else
{
CmdHelper.RunCmd($"dotnet ef migrations add Initial --context MyProjectNameDbContext", workingDirectory: projectDir);
CmdHelper.RunCmd($"dotnet ef migrations add Initial --context MyProjectNameTenantDbContext --output-dir TenantMigrations", workingDirectory: projectDir);
}
if (Directory.Exists(Path.Combine(projectDir, "Logs")))
{
Directory.Delete(Path.Combine(projectDir, "Logs"), true);
}
projectCounts++;
}
Logger.LogInformation(projectCounts > 0
? $"Done! All {projectCounts} migrations recreated."
: "No project found to recreate migrations.");
return Task.CompletedTask;
}
public string GetUsageInfo()
{
return GetShortDescription();
}
public string GetShortDescription()
{
return "This is a internal command. Please run 'abp recreate-initial-migration' command in abp or volo root directory.";
}
}

35
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ChangeThemeStep.cs

@ -372,7 +372,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
return;
}
lines[lineIndex] = lines[lineIndex].Replace(lines[lineIndex], $"\t<ProjectReference Include=\"{projectReference}\" />");
lines[lineIndex] = lines[lineIndex].Replace(lines[lineIndex], $"\t\t<ProjectReference Include=\"{projectReference}\" />\n");
file.SetLines(lines);
}
@ -568,7 +568,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
private static void ChangeThemeToBasicForMvcProjects(ProjectBuildContext context, string defaultThemeName)
{
var projectNames = new[]
{
{
".Web", ".HttpApi.Host", ".AuthServer", ".Web.Public", ".Web.Public.Host",
"" //for app-nolayers-mvc
};
@ -608,45 +608,46 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
{
var projects = new Dictionary<string, string>
{
{"Blazor", "MyProjectNameBlazorModule"},
{"Blazor.Server.Tiered", "MyProjectNameBlazorModule"},
{"Blazor.Server", "MyProjectNameModule"},
{"Blazor.Server.Mongo", "MyProjectNameModule"}
{".Blazor", "MyProjectNameBlazorModule"},
{".Blazor.Server.Tiered", "MyProjectNameBlazorModule"},
{".Blazor.Server", "MyProjectNameModule"},
{"Blazor.Server.Mongo", "MyProjectNameModule"},
{"", ""} //for app-nolayers blazor-server
};
foreach (var project in projects)
{
ReplacePackageReferenceWithProjectReference(
context,
$"/MyCompanyName.MyProjectName.{project.Key}/MyCompanyName.MyProjectName.{project.Key}.csproj",
$"Volo.Abp.AspNetCore.Components.Server.{defaultThemeName}Theme",
@"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj"
$"/MyCompanyName.MyProjectName{project.Key}/MyCompanyName.MyProjectName{project.Key}.csproj",
$"Volo.Abp.AspNetCore.Components.Server.{defaultThemeName}",
@"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.Server.BasicTheme\Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj"
);
ReplacePackageReferenceWithProjectReference(
context,
$"/MyCompanyName.MyProjectName.{project.Key}/MyCompanyName.MyProjectName.{project.Key}.csproj",
$"/MyCompanyName.MyProjectName{project.Key}/MyCompanyName.MyProjectName{project.Key}.csproj",
$"Volo.Abp.AspNetCore.Mvc.UI.Theme.{defaultThemeName}",
@"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Components.Server.BasicTheme\Volo.Abp.AspNetCore.Components.Server.BasicTheme.csproj"
@"..\..\..\..\..\modules\basic-theme\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic\Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.csproj"
);
ReplaceAllKeywords(
context,
$"/MyCompanyName.MyProjectName.{project.Key}/Pages/_Host.cshtml",
$"/Pages/_Host.cshtml",
$"{defaultThemeName}Theme.Components",
Basic
);
ReplaceAllKeywords(
context,
$"/MyCompanyName.MyProjectName.{project.Key}/{project.Value}.cs",
$"/MyCompanyName.MyProjectName{project.Key}/{project.Value}.cs",
defaultThemeName,
Basic
Basic + "Theme"
);
ReplaceAllKeywords(
context,
$"/MyCompanyName.MyProjectName.{project.Key}/Pages/_Host.cshtml",
$"/Pages/_Host.cshtml",
defaultThemeName,
Basic
);
@ -682,7 +683,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
ReplaceAllKeywords(
context,
$"/MyCompanyName.MyProjectName.{projectName}/Pages/_Host.cshtml",
$"/Pages/_Host.cshtml",
LeptonX,
Lepton
);
@ -731,7 +732,7 @@ public class ChangeThemeStep : ProjectBuildPipelineStep
ReplaceAllKeywords(
context,
$"/MyCompanyName.MyProjectName.{projectName}/Pages/_Host.cshtml",
$"/Pages/_Host.cshtml",
LeptonX,
Lepton
);

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppNoLayersTemplateBase.cs

@ -346,6 +346,7 @@ public abstract class AppNoLayersTemplateBase : TemplateInfo
var blazorServerUiPackageName = isProTemplate ? "@volo/aspnetcore.components.server.leptonxtheme" : "@abp/aspnetcore.components.server.leptonxlitetheme";
var blazorServerPackageJsonFilePaths = new List<string>
{
"/MyCompanyName.MyProjectName/package.json",
"/MyCompanyName.MyProjectName.Blazor/package.json",
"/MyCompanyName.MyProjectName.Blazor.Server.Mongo/package.json"
};

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs

@ -594,10 +594,11 @@ public class SolutionModuleAdder : ITransientDependency
{
var args = new CommandLineArgs("new", module.Name);
args.Options.Add("t", newProTemplate ? ModuleProTemplate.TemplateName : ModuleTemplate.TemplateName);
args.Options.Add("v", version);
args.Options.Add("o", Path.Combine(modulesFolderInSolution, module.Name));
args.Options.Add("sib", true.ToString());
args.Options.Add(ProjectCreationCommandBase.Options.Template.Short, newProTemplate ? ModuleProTemplate.TemplateName : ModuleTemplate.TemplateName);
args.Options.Add(ProjectCreationCommandBase.Options.Version.Short, version);
args.Options.Add(ProjectCreationCommandBase.Options.OutputFolder.Short, Path.Combine(modulesFolderInSolution, module.Name));
args.Options.Add(ProjectCreationCommandBase.Options.SkipInstallingLibs.Short, true.ToString());
args.Options.Add(ProjectCreationCommandBase.Options.SkipBundling.Long, true.ToString());
await NewCommand.ExecuteAsync(args);
}

31
framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs

@ -85,7 +85,7 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency
case EntityState.Modified:
changeType = IsDeleted(entityEntry) ? EntityChangeType.Deleted : EntityChangeType.Updated;
break;
case EntityState.Unchanged:
case EntityState.Unchanged when HasNavigationPropertiesChanged(entityEntry):
changeType = EntityChangeType.Updated; // Navigation property changes.
break;
case EntityState.Detached:
@ -186,7 +186,7 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency
}
}
if (entityEntry.State == EntityState.Unchanged)
if (Options.SaveEntityHistoryWhenNavigationChanges && entityEntry.State == EntityState.Unchanged)
{
foreach (var navigation in entityEntry.Navigations)
{
@ -227,21 +227,6 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency
return false;
}
if (entityEntry.State == EntityState.Unchanged)
{
if (entityEntry.Navigations.Any(navigationEntry => navigationEntry.IsModified))
{
return true;
}
if (entityEntry.Navigations.Where(x => x is ReferenceEntry).Cast<ReferenceEntry>().Any(x => x.TargetEntry != null && x.TargetEntry.State == EntityState.Modified))
{
return true;
}
return false;
}
var entityType = entityEntry.Metadata.ClrType;
if (!EntityHelper.IsEntity(entityType) && !EntityHelper.IsValueObject(entityType))
@ -249,12 +234,20 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency
return false;
}
if (AuditingHelper.IsEntityHistoryEnabled(entityType))
var isEntityHistoryEnabled = AuditingHelper.IsEntityHistoryEnabled(entityType);
if (isEntityHistoryEnabled && HasNavigationPropertiesChanged(entityEntry))
{
return true;
}
return defaultValue;
return isEntityHistoryEnabled || defaultValue;
}
protected virtual bool HasNavigationPropertiesChanged(EntityEntry entityEntry)
{
return Options.SaveEntityHistoryWhenNavigationChanges && entityEntry.State == EntityState.Unchanged &&
(entityEntry.Navigations.Any(navigationEntry => navigationEntry.IsModified) ||
entityEntry.Navigations.Where(x => x is ReferenceEntry).Cast<ReferenceEntry>().Any(x => x.TargetEntry != null && x.TargetEntry.State == EntityState.Modified));
}
protected virtual bool ShouldSavePropertyHistory(PropertyEntry propertyEntry, bool defaultValue)

24
framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/ApplicationMenuExtensions.cs

@ -1,11 +1,13 @@
using System;
using JetBrains.Annotations;
using System.Linq;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.UI.Navigation;
public static class ApplicationMenuExtensions
{
public const string CustomDataComponentKey = "ApplicationMenu.CustomComponent";
[NotNull]
public static ApplicationMenuItem GetAdministration(
[NotNull] this ApplicationMenu applicationMenu)
@ -112,4 +114,24 @@ public static class ApplicationMenuExtensions
return menuWithGroups;
}
public static ApplicationMenuItem UseComponent<TComponent>(this ApplicationMenuItem applicationMenuItem)
{
return applicationMenuItem.UseComponent(typeof(TComponent));
}
public static ApplicationMenuItem UseComponent(this ApplicationMenuItem applicationMenuItem, Type componentType)
{
return applicationMenuItem.WithCustomData(CustomDataComponentKey, componentType);
}
public static Type? GetComponentTypeOrDefault(this ApplicationMenuItem applicationMenuItem)
{
if (applicationMenuItem.CustomData.TryGetValue(CustomDataComponentKey, out var value))
{
return value as Type;
}
return default;
}
}

255
framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NSubstitute;
@ -392,6 +391,7 @@ public class Auditing_Tests : AbpAuditingTestBase
x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithValueObject).FullName &&
x.EntityChanges[2].ChangeType == EntityChangeType.Deleted &&
x.EntityChanges[2].EntityTypeFullName == typeof(AppEntityWithValueObjectAddress).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
@ -421,7 +421,7 @@ public class Auditing_Tests : AbpAuditingTestBase
x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithValueObject).FullName &&
x.EntityChanges[1].PropertyChanges.Count == 1 &&
x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithValueObject.AppEntityWithValueObjectAddress)));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
@ -439,22 +439,16 @@ public class Auditing_Tests : AbpAuditingTestBase
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 2 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Updated &&
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 1 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Deleted &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithValueObjectAddress).FullName &&
x.EntityChanges[0].PropertyChanges.Count == 1 &&
x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithValueObjectAddress.Country) &&
x.EntityChanges[0].PropertyChanges[0].OriginalValue == "\"England\"" &&
x.EntityChanges[0].PropertyChanges[0].NewValue == "\"Germany\"" &&
x.EntityChanges[1].ChangeType == EntityChangeType.Updated &&
x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithValueObject).FullName));
x.EntityChanges[0].PropertyChanges.Count == 2 &&
x.EntityChanges[0].PropertyChanges.All(p => p.NewValue == null)));
#pragma warning restore 4014
}
[Fact]
public virtual async Task Should_Write_AuditLog_For_Navigations_Changes()
public virtual async Task Should_Write_AuditLog_For_Navigation_Changes()
{
var entityId = Guid.NewGuid();
var repository = ServiceProvider.GetRequiredService<IBasicRepository<AppEntityWithNavigations, Guid>>();
@ -484,6 +478,7 @@ public class Auditing_Tests : AbpAuditingTestBase
x.EntityChanges[0].PropertyChanges[0].NewValue == "\"test full name\"" &&
x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.FullName) &&
x.EntityChanges[0].PropertyChanges[0].PropertyTypeFullName == typeof(string).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
@ -513,6 +508,7 @@ public class Auditing_Tests : AbpAuditingTestBase
x.EntityChanges[1].PropertyChanges.Count == 1 &&
x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToOne) &&
x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
@ -545,7 +541,7 @@ public class Auditing_Tests : AbpAuditingTestBase
x.EntityChanges[1].PropertyChanges.Count == 1 &&
x.EntityChanges[1].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.OneToMany) &&
x.EntityChanges[1].PropertyChanges[0].PropertyTypeFullName == typeof(List<AppEntityWithNavigationChildOneToMany>).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
@ -604,3 +600,234 @@ public class Auditing_DisableLogActionInfo_Tests : Auditing_Tests
await AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.Actions.IsNullOrEmpty()));
}
}
public class Auditing_SaveEntityHistoryWhenNavigationChanges_Tests : AbpAuditingTestBase
{
protected IAuditingStore AuditingStore;
private IAuditingManager _auditingManager;
private IUnitOfWorkManager _unitOfWorkManager;
public Auditing_SaveEntityHistoryWhenNavigationChanges_Tests()
{
_auditingManager = GetRequiredService<IAuditingManager>();
_unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
}
protected override void AfterAddApplication(IServiceCollection services)
{
AuditingStore = Substitute.For<IAuditingStore>();
services.Replace(ServiceDescriptor.Singleton(AuditingStore));
services.Configure<AbpAuditingOptions>(options =>
{
options.SaveEntityHistoryWhenNavigationChanges = false;
});
}
[Fact]
public virtual async Task Should_Write_AuditLog_For_ValueObject_Entity()
{
var entityId = Guid.NewGuid();
var repository = ServiceProvider.GetRequiredService<IBasicRepository<AppEntityWithValueObject, Guid>>();
await repository.InsertAsync(new AppEntityWithValueObject(entityId, "test name", new AppEntityWithValueObjectAddress("USA")));
using (var scope = _auditingManager.BeginScope())
{
using (var uow = _unitOfWorkManager.Begin())
{
var entity = await repository.GetAsync(entityId);
entity.Name = "test name 2";
entity.AppEntityWithValueObjectAddress = new AppEntityWithValueObjectAddress("England");
await repository.UpdateAsync(entity);
await uow.CompleteAsync();
await scope.SaveAsync();
}
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 3 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Created &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithValueObjectAddress).FullName &&
x.EntityChanges[1].ChangeType == EntityChangeType.Updated &&
x.EntityChanges[1].EntityTypeFullName == typeof(AppEntityWithValueObject).FullName &&
x.EntityChanges[2].ChangeType == EntityChangeType.Deleted &&
x.EntityChanges[2].EntityTypeFullName == typeof(AppEntityWithValueObjectAddress).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
{
using (var uow = _unitOfWorkManager.Begin())
{
var entity = await repository.GetAsync(entityId);
entity.AppEntityWithValueObjectAddress.Country = "Germany";
await repository.UpdateAsync(entity);
await uow.CompleteAsync();
await scope.SaveAsync();
}
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 1 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Updated &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithValueObjectAddress).FullName &&
x.EntityChanges[0].PropertyChanges.Count == 1 &&
x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithValueObjectAddress.Country) &&
x.EntityChanges[0].PropertyChanges[0].OriginalValue == "\"England\"" &&
x.EntityChanges[0].PropertyChanges[0].NewValue == "\"Germany\""));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
{
using (var uow = _unitOfWorkManager.Begin())
{
var entity = await repository.GetAsync(entityId);
entity.AppEntityWithValueObjectAddress = null;
await repository.UpdateAsync(entity);
await uow.CompleteAsync();
await scope.SaveAsync();
}
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 1 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Deleted &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithValueObjectAddress).FullName &&
x.EntityChanges[0].PropertyChanges.Count == 2 &&
x.EntityChanges[0].PropertyChanges.All(p => p.NewValue == null)));
#pragma warning restore 4014
}
[Fact]
public virtual async Task Should_Not_Write_AuditLog_For_Navigation_Changes()
{
var entityId = Guid.NewGuid();
var repository = ServiceProvider.GetRequiredService<IBasicRepository<AppEntityWithNavigations, Guid>>();
await repository.InsertAsync(new AppEntityWithNavigations(entityId, "test name"));
using (var scope = _auditingManager.BeginScope())
{
using (var uow = _unitOfWorkManager.Begin())
{
var entity = await repository.GetAsync(entityId);
entity.FullName = "test full name";
await repository.UpdateAsync(entity);
await uow.CompleteAsync();
await scope.SaveAsync();
}
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 1 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Updated &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigations).FullName &&
x.EntityChanges[0].PropertyChanges.Count == 1 &&
x.EntityChanges[0].PropertyChanges[0].OriginalValue == "\"test name\"" &&
x.EntityChanges[0].PropertyChanges[0].NewValue == "\"test full name\"" &&
x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigations.FullName) &&
x.EntityChanges[0].PropertyChanges[0].PropertyTypeFullName == typeof(string).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
{
using (var uow = _unitOfWorkManager.Begin())
{
var entity = await repository.GetAsync(entityId);
entity.OneToOne = new AppEntityWithNavigationChildOneToOne
{
ChildName = "ChildName"
};
await repository.UpdateAsync(entity);
await uow.CompleteAsync();
await scope.SaveAsync();
}
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 1 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Created &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToOne).FullName &&
x.EntityChanges[0].PropertyChanges.Count == 1 &&
x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigationChildOneToOne.ChildName) &&
x.EntityChanges[0].PropertyChanges[0].PropertyTypeFullName == typeof(string).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
{
using (var uow = _unitOfWorkManager.Begin())
{
var entity = await repository.GetAsync(entityId);
entity.OneToMany = new List<AppEntityWithNavigationChildOneToMany>()
{
new AppEntityWithNavigationChildOneToMany
{
AppEntityWithNavigationId = entity.Id,
ChildName = "ChildName1"
}
};
await repository.UpdateAsync(entity);
await uow.CompleteAsync();
await scope.SaveAsync();
}
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 1 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Created &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigationChildOneToMany).FullName &&
x.EntityChanges[0].PropertyChanges.Count == 2 &&
x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigationChildOneToMany.AppEntityWithNavigationId) &&
x.EntityChanges[0].PropertyChanges[0].PropertyTypeFullName == typeof(Guid).FullName &&
x.EntityChanges[0].PropertyChanges[1].PropertyName == nameof(AppEntityWithNavigationChildOneToMany.ChildName) &&
x.EntityChanges[0].PropertyChanges[1].PropertyTypeFullName == typeof(string).FullName));
AuditingStore.ClearReceivedCalls();
#pragma warning restore 4014
using (var scope = _auditingManager.BeginScope())
{
using (var uow = _unitOfWorkManager.Begin())
{
var entity = await repository.GetAsync(entityId);
entity.ManyToMany = new List<AppEntityWithNavigationChildManyToMany>()
{
new AppEntityWithNavigationChildManyToMany
{
ChildName = "ChildName1"
}
};
await repository.UpdateAsync(entity);
await uow.CompleteAsync();
await scope.SaveAsync();
}
}
#pragma warning disable 4014
AuditingStore.Received().SaveAsync(Arg.Is<AuditLogInfo>(x => x.EntityChanges.Count == 1 &&
x.EntityChanges[0].ChangeType == EntityChangeType.Created &&
x.EntityChanges[0].EntityTypeFullName == typeof(AppEntityWithNavigationChildManyToMany).FullName &&
x.EntityChanges[0].PropertyChanges.Count == 1 &&
x.EntityChanges[0].PropertyChanges[0].PropertyName == nameof(AppEntityWithNavigationChildManyToMany.ChildName) &&
x.EntityChanges[0].PropertyChanges[0].PropertyTypeFullName == typeof(string).FullName));
#pragma warning restore 4014
}
}

2
latest-versions.json

@ -1,6 +1,6 @@
[
{
"version": "8.0.0",
"version": "8.0.1",
"releaseDate": "",
"type": "stable",
"message": ""

26
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Navigation/BasicThemeNavigationExtensions.cs

@ -1,26 +0,0 @@
using System;
using JetBrains.Annotations;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Navigation;
public static class BasicThemeNavigationExtensions
{
public const string CustomDataComponentKey = "BasicTheme.CustomComponent";
public static ApplicationMenuItem UseComponent(this ApplicationMenuItem applicationMenuItem, Type componentType)
{
return applicationMenuItem.WithCustomData(CustomDataComponentKey, componentType);
}
[CanBeNull]
public static Type GetComponentTypeOrDefault(this ApplicationMenuItem applicationMenuItem)
{
if (applicationMenuItem.CustomData.TryGetValue(CustomDataComponentKey, out object componentType))
{
return componentType as Type;
}
return default;
}
}

3
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor

@ -1,5 +1,4 @@
@using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Navigation;
@using Volo.Abp.UI.Navigation
@using Volo.Abp.UI.Navigation
@{
var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_");
var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass;

3
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor

@ -1,5 +1,4 @@
@using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Navigation;
@using Volo.Abp.UI.Navigation
@using Volo.Abp.UI.Navigation
@{
var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_");
var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass;

41
modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/Default.cshtml

@ -6,9 +6,15 @@
var cssClass = string.IsNullOrEmpty(menuItem.CssClass) ? string.Empty : menuItem.CssClass;
var disabled = menuItem.IsDisabled ? "disabled" : string.Empty;
var url = string.IsNullOrEmpty(menuItem.Url) ? "#" : Url.IsLocalUrl(menuItem.Url) ? Url.Content(menuItem.Url.EnsureStartsWith('~')) : menuItem.Url;
var customComponentType = menuItem.GetComponentTypeOrDefault();
if (menuItem.IsLeaf)
{
if (menuItem.Url != null)
if (customComponentType != null)
{
@(await Component.InvokeAsync(customComponentType))
}
else if (menuItem.Url != null)
{
<li class="nav-item @cssClass @disabled" @elementId>
<a class="nav-link" href="@url" target="@menuItem.Target">
@ -28,19 +34,26 @@
{
<li class="nav-item">
<div class="dropdown">
<a class="nav-link dropdown-toggle" href="#" id="Menu_@(menuItem.Name)" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@if (menuItem.Icon != null)
{
<i class="@menuItem.Icon"></i>
}
@menuItem.DisplayName
</a>
<div class="dropdown-menu border-0 shadow-sm" aria-labelledby="Menu_@(menuItem.Name)">
@foreach (var childMenuItem in menuItem.Items)
{
@await Html.PartialAsync("~/Themes/Basic/Components/Menu/_MenuItem.cshtml", childMenuItem)
}
</div>
@if (customComponentType != null)
{
@(await Component.InvokeAsync(customComponentType))
}
else
{
<a class="nav-link dropdown-toggle" href="#" id="Menu_@(menuItem.Name)" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@if (menuItem.Icon != null)
{
<i class="@menuItem.Icon"></i>
}
@menuItem.DisplayName
</a>
<div class="dropdown-menu border-0 shadow-sm" aria-labelledby="Menu_@(menuItem.Name)">
@foreach (var childMenuItem in menuItem.Items)
{
@await Html.PartialAsync("~/Themes/Basic/Components/Menu/_MenuItem.cshtml", childMenuItem)
}
</div>
}
</div>
</li>
}

45
modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic/Themes/Basic/Components/Menu/_MenuItem.cshtml

@ -5,10 +5,16 @@
var cssClass = string.IsNullOrEmpty(Model.CssClass) ? string.Empty : Model.CssClass;
var disabled = Model.IsDisabled ? "disabled" : string.Empty;
var url = string.IsNullOrEmpty(Model.Url) ? "#" : Url.IsLocalUrl(Model.Url) ? Url.Content(Model.Url.EnsureStartsWith('~')) : Model.Url;
var customComponentType = Model.GetComponentTypeOrDefault();
}
@if (Model.IsLeaf)
{
if (Model.Url != null)
if (customComponentType != null)
{
@(await Component.InvokeAsync(customComponentType))
}
else if (Model.Url != null)
{
<a class="dropdown-item @cssClass @disabled" href="@url" target="@Model.Target" @Html.Raw(elementId)>
@if (Model.Icon != null)
@ -25,20 +31,27 @@
else
{
<div class="dropdown-submenu">
<a role="button" class="btn dropdown-toggle" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<span class="lp-icon">
<i class="@(Model.Icon ?? "")"></i>
</span>
<span class="lp-text">
@Model.DisplayName
</span>
</a>
<div class="dropdown-menu border-0 shadow-sm">
@foreach (var childMenuItem in Model.Items)
{
@await Html.PartialAsync("~/Themes/Basic/Components/Menu/_MenuItem.cshtml", childMenuItem)
}
</div>
@if (customComponentType != null)
{
@(await Component.InvokeAsync(customComponentType))
}
else
{
<a role="button" class="btn dropdown-toggle" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<span class="lp-icon">
<i class="@(Model.Icon ?? "")"></i>
</span>
<span class="lp-text">
@Model.DisplayName
</span>
</a>
<div class="dropdown-menu border-0 shadow-sm">
@foreach (var childMenuItem in Model.Items)
{
@await Html.PartialAsync("~/Themes/Basic/Components/Menu/_MenuItem.cshtml", childMenuItem)
}
</div>
}
</div>
}

2352
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20230504122708_Initial.Designer.cs

File diff suppressed because it is too large

1334
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/20230504122708_Initial.cs

File diff suppressed because it is too large

2349
modules/cms-kit/host/Volo.CmsKit.Web.Unified/Migrations/UnifiedDbContextModelSnapshot.cs

File diff suppressed because it is too large

10
modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20231207053813_Initial.Designer.cs → modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20240108043816_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace OpenIddict.Demo.Server.Migrations
{
[DbContext(typeof(ServerDbContext))]
[Migration("20231207053813_Initial")]
[Migration("20240108043816_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1326,8 +1326,8 @@ namespace OpenIddict.Demo.Server.Migrations
.HasColumnType("uniqueidentifier");
b.Property<string>("DefaultValue")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("Description")
.HasMaxLength(512)
@ -1357,8 +1357,8 @@ namespace OpenIddict.Demo.Server.Migrations
.HasColumnType("nvarchar(128)");
b.Property<string>("Providers")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");

4
modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20231207053813_Initial.cs → modules/openiddict/app/OpenIddict.Demo.Server/Migrations/20240108043816_Initial.cs

@ -229,9 +229,9 @@ namespace OpenIddict.Demo.Server.Migrations
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
DefaultValue = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
DefaultValue = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
IsVisibleToClients = table.Column<bool>(type: "bit", nullable: false),
Providers = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Providers = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
IsInherited = table.Column<bool>(type: "bit", nullable: false),
IsEncrypted = table.Column<bool>(type: "bit", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true)

8
modules/openiddict/app/OpenIddict.Demo.Server/Migrations/ServerDbContextModelSnapshot.cs

@ -1323,8 +1323,8 @@ namespace OpenIddict.Demo.Server.Migrations
.HasColumnType("uniqueidentifier");
b.Property<string>("DefaultValue")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("Description")
.HasMaxLength(512)
@ -1354,8 +1354,8 @@ namespace OpenIddict.Demo.Server.Migrations
.HasColumnType("nvarchar(128)");
b.Property<string>("Providers")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");

5
modules/permission-management/src/Volo.Abp.PermissionManagement.Application/Volo/Abp/PermissionManagement/PermissionAppService.cs

@ -57,6 +57,11 @@ public class PermissionAppService : ApplicationService, IPermissionAppService
foreach (var permission in permissions)
{
if(permission.Parent != null && !neededCheckPermissions.Contains(permission.Parent))
{
continue;
}
if (await SimpleStateCheckerManager.IsEnabledAsync(permission))
{
neededCheckPermissions.Add(permission);

34
modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs

@ -17,7 +17,7 @@ public partial class PermissionManagementModal
[Inject] protected ICurrentApplicationConfigurationCacheResetService CurrentApplicationConfigurationCacheResetService { get; set; }
[Inject] protected IOptions<AbpLocalizationOptions> LocalizationOptions { get; set; }
protected Modal _modal;
protected string _providerName;
@ -71,7 +71,7 @@ public partial class PermissionManagementModal
}
}
}
protected Dictionary<string, int> _permissionDepths = new Dictionary<string, int>();
public PermissionManagementModal()
@ -137,7 +137,7 @@ public partial class PermissionManagementModal
{
try
{
var updateDto = new UpdatePermissionsDto
{
Permissions = _groups
@ -145,7 +145,7 @@ public partial class PermissionManagementModal
.Select(p => new UpdatePermissionDto { IsGranted = p.IsGranted, Name = p.Name })
.ToArray()
};
if (!updateDto.Permissions.Any(x => x.IsGranted))
{
if (!await Message.Confirm(L["SaveWithoutAnyPermissionsWarningMessage"].Value))
@ -182,7 +182,7 @@ public partial class PermissionManagementModal
}
}
}
protected virtual int GetPermissionDepthOrDefault(string name)
{
return _permissionDepths.GetValueOrDefault(name, 0);
@ -207,7 +207,7 @@ public partial class PermissionManagementModal
{
SetParentPermissionGrant(permissionGroup, permission);
}
else if (value == false)
else
{
var childPermissions = GetChildPermissions(permissionGroup, permission);
@ -229,7 +229,7 @@ public partial class PermissionManagementModal
SetPermissionGrant(parentPermission, true);
SetParentPermissionGrant(permissionGroup, parentPermission);
}
private void SetPermissionGrant(PermissionGrantInfoDto permission, bool value)
@ -260,7 +260,25 @@ public partial class PermissionManagementModal
protected List<PermissionGrantInfoDto> GetChildPermissions(PermissionGroupDto permissionGroup, PermissionGrantInfoDto permission)
{
return permissionGroup.Permissions.Where(x => x.Name.StartsWith(permission.Name)).ToList();
var childPermissions = new List<PermissionGrantInfoDto>();
GetChildPermissions(childPermissions, permissionGroup.Permissions, permission);
return childPermissions;
}
protected void GetChildPermissions(List<PermissionGrantInfoDto> allChildPermissions, List<PermissionGrantInfoDto> permissions, PermissionGrantInfoDto permission)
{
var childPermissions = permissions.Where(x => x.ParentName == permission.Name).ToList();
if (childPermissions.Count == 0)
{
return;
}
allChildPermissions.AddRange(childPermissions);
foreach (var childPermission in childPermissions)
{
GetChildPermissions(allChildPermissions, permissions, childPermission);
}
}
protected bool IsDisabledPermission(PermissionGrantInfoDto permissionGrantInfo)

16
modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs

@ -42,12 +42,24 @@ public class PermissionAppService_Tests : AbpPermissionManagementApplicationTest
permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission4");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyPermission5");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyPermission5.ChildPermission1");
using (_currentPrincipalAccessor.Change(new Claim(AbpClaimTypes.Role, "super-admin")))
{
(await _permissionAppService.GetAsync(UserPermissionValueProvider.ProviderName, PermissionTestDataBuilder.User1Id.ToString())).Groups.First().Permissions
.ShouldContain(x => x.Name == "MyPermission5");
var result = await _permissionAppService.GetAsync(UserPermissionValueProvider.ProviderName, PermissionTestDataBuilder.User1Id.ToString());
result.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission5");
result.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission5.ChildPermission1");
}
permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission6");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyPermission6.ChildDisabledPermission1");
permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission6.ChildPermission2");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyDisabledPermission1");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyDisabledPermission2");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyDisabledPermission2.ChildPermission1");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyDisabledPermission2.ChildPermission2");
permissionListResultDto.Groups.First().Permissions.ShouldNotContain(x => x.Name == "MyDisabledPermission2.ChildPermission2.ChildPermission1");
}
[Fact]

13
modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionDefinitionProvider.cs

@ -19,6 +19,17 @@ public class TestPermissionDefinitionProvider : PermissionDefinitionProvider
testGroup.AddPermission("MyPermission4", multiTenancySide: MultiTenancySides.Host).WithProviders(UserPermissionValueProvider.ProviderName);
testGroup.AddPermission("MyPermission5").StateCheckers.Add(new TestRequireRolePermissionStateProvider("super-admin"));
var myPermission5 = testGroup.AddPermission("MyPermission5");
myPermission5.StateCheckers.Add(new TestRequireRolePermissionStateProvider("super-admin"));
myPermission5.AddChild("MyPermission5.ChildPermission1");
var myPermission6 = testGroup.AddPermission("MyPermission6");
myPermission6.AddChild("MyPermission6.ChildDisabledPermission1", isEnabled: false);
myPermission6.AddChild("MyPermission6.ChildPermission2");
var myDisabledPermission2 = testGroup.AddPermission("MyDisabledPermission2", isEnabled: false);
myDisabledPermission2.AddChild("MyDisabledPermission2.ChildPermission1");
var myDisabledPermission2Child2 = myDisabledPermission2.AddChild("MyDisabledPermission2.ChildPermission2");
myDisabledPermission2Child2.AddChild("MyDisabledPermission2.ChildPermission2.ChildPermission1");
}
}

22
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/20230713030300_Initial.Designer.cs → modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/20240108025904_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.SettingManagement.DemoApp;
namespace Volo.Abp.SettingManagement.DemoApp.Migrations
{
[DbContext(typeof(DemoAppDbContext))]
[Migration("20230713030300_Initial")]
[Migration("20240108025904_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -22,7 +22,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("ProductVersion", "7.0.1")
.HasAnnotation("ProductVersion", "7.0.14")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
@ -35,6 +35,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -44,6 +45,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("nvarchar(256)");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -109,6 +111,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -117,6 +120,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -209,6 +213,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -221,6 +226,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("datetime2");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -270,6 +276,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -306,6 +313,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -590,6 +598,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -620,6 +629,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -835,8 +845,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("uniqueidentifier");
b.Property<string>("DefaultValue")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("Description")
.HasMaxLength(512)
@ -866,8 +876,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("nvarchar(128)");
b.Property<string>("Providers")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");

24
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/20230713030300_Initial.cs → modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/20240108025904_Initial.cs

@ -23,8 +23,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
RegexDescription = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Description = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ValueType = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true)
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
constraints: table =>
{
@ -56,8 +56,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
Code = table.Column<string>(type: "nvarchar(95)", maxLength: 95, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
@ -137,8 +137,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
IsStatic = table.Column<bool>(type: "bit", nullable: false),
IsPublic = table.Column<bool>(type: "bit", nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true)
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
constraints: table =>
{
@ -162,8 +162,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
ClientIpAddress = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
BrowserInfo = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true)
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
constraints: table =>
{
@ -178,9 +178,9 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
DefaultValue = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
DefaultValue = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
IsVisibleToClients = table.Column<bool>(type: "bit", nullable: false),
Providers = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Providers = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
IsInherited = table.Column<bool>(type: "bit", nullable: false),
IsEncrypted = table.Column<bool>(type: "bit", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true)
@ -247,8 +247,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
ShouldChangePasswordOnNextLogin = table.Column<bool>(type: "bit", nullable: false),
EntityVersion = table.Column<int>(type: "int", nullable: false),
LastPasswordChangeTime = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),

20
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/Migrations/DemoAppDbContextModelSnapshot.cs

@ -19,7 +19,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
.HasAnnotation("ProductVersion", "7.0.1")
.HasAnnotation("ProductVersion", "7.0.14")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
@ -32,6 +32,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -41,6 +42,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("nvarchar(256)");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -106,6 +108,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -114,6 +117,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -206,6 +210,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -218,6 +223,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("datetime2");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -267,6 +273,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -303,6 +310,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -587,6 +595,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.IsRequired()
.HasMaxLength(40)
.HasColumnType("nvarchar(40)")
.HasColumnName("ConcurrencyStamp");
@ -617,6 +626,7 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("int");
b.Property<string>("ExtraProperties")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("ExtraProperties");
@ -832,8 +842,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("uniqueidentifier");
b.Property<string>("DefaultValue")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("Description")
.HasMaxLength(512)
@ -863,8 +873,8 @@ namespace Volo.Abp.SettingManagement.DemoApp.Migrations
.HasColumnType("nvarchar(128)");
b.Property<string>("Providers")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");

4
modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/SettingDefinitionRecordConsts.cs

@ -8,7 +8,7 @@ public class SettingDefinitionRecordConsts
public static int MaxDescriptionLength { get; set; } = 512;
public static int MaxDefaultValueLength { get; set; } = 256;
public static int MaxDefaultValueLength { get; set; } = SettingConsts.MaxValueLengthValue;
public static int MaxProvidersLength { get; set; } = 128;
public static int MaxProvidersLength { get; set; } = 1024;
}

2
npm/packs/font-awesome/package.json

@ -11,7 +11,7 @@
},
"dependencies": {
"@abp/core": "~8.0.1",
"@fortawesome/fontawesome-free": "^5.15.4"
"@fortawesome/fontawesome-free": "^6.5.1"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431",
"homepage": "https://abp.io",

2
npm/publish-mvc.ps1

@ -25,7 +25,7 @@ if ($IsPrerelease) {
}
$commands = (
"npm run lerna -- version $Version --yes --no-commit-hooks --skip-git --force-publish",
"npm run lerna -- version $Version --yes --no-commit-hooks --no-git-tag-version --no-push --force-publish",
"yarn replace-with-tilde",
"cd scripts",
"yarn install",

10
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240108044306_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
{
[DbContext(typeof(MyProjectNameDbContext))]
[Migration("20231207053812_Initial")]
[Migration("20240108044306_Initial")]
partial class Initial
{
/// <inheritdoc />
@ -1589,8 +1589,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
.HasColumnType("uniqueidentifier");
b.Property<string>("DefaultValue")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
.HasMaxLength(2048)
.HasColumnType("nvarchar(2048)");
b.Property<string>("Description")
.HasMaxLength(512)
@ -1620,8 +1620,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
.HasColumnType("nvarchar(128)");
b.Property<string>("Providers")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
.HasMaxLength(1024)
.HasColumnType("nvarchar(1024)");
b.HasKey("Id");

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20231207053812_Initial.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240108044306_Initial.cs

@ -263,9 +263,9 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Description = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
DefaultValue = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
DefaultValue = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
IsVisibleToClients = table.Column<bool>(type: "bit", nullable: false),
Providers = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
Providers = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
IsInherited = table.Column<bool>(type: "bit", nullable: false),
IsEncrypted = table.Column<bool>(type: "bit", nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: true)

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

Loading…
Cancel
Save