Browse Source

Merge branch 'rel-4.0' of https://github.com/abpframework/abp into fix/6231

pull/6314/head
mehmet-erim 6 years ago
parent
commit
6d4a0ac7cb
  1. 14
      abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/es.json
  2. 199
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json
  3. 33
      abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/es.json
  4. 35
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/es.json
  5. 90
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json
  6. 189
      abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/es.json
  7. 18
      docs/en/CLI.md
  8. 2
      docs/en/Getting-Started-AspNetCore-Application.md
  9. 13
      docs/en/Getting-Started.md
  10. 4
      docs/en/Localization.md
  11. 2
      docs/en/Migration-Guides/Abp-4_0-Blazor.md
  12. 2
      docs/en/Migration-Guides/Abp-4_0.md
  13. 41
      docs/en/Tutorials/Part-10.md
  14. 5
      docs/en/Tutorials/Part-2.md
  15. 449
      docs/en/Tutorials/Part-3.md
  16. 4
      docs/en/Tutorials/Part-4.md
  17. 138
      docs/en/Tutorials/Part-5.md
  18. 17
      docs/en/Tutorials/Part-9.md
  19. BIN
      docs/en/Tutorials/images/blazor-bookstore-book-list.png
  20. BIN
      docs/en/Tutorials/images/blazor-delete-book-action.png
  21. BIN
      docs/en/Tutorials/images/blazor-edit-book-action-2.png
  22. 2
      docs/en/UI/Angular/Permission-Management.md
  23. 2
      docs/en/UI/AspNetCore/Branding.md
  24. 2
      docs/en/UI/AspNetCore/Customization-User-Interface.md
  25. 12
      docs/en/UI/AspNetCore/Navigation-Menu.md
  26. 57
      docs/en/UI/Blazor/Basic-Theme.md
  27. 37
      docs/en/UI/Blazor/Branding.md
  28. 85
      docs/en/UI/Blazor/Customization-Overriding-Components.md
  29. 37
      docs/en/UI/Blazor/Global-Scripts-Styles.md
  30. 77
      docs/en/UI/Blazor/Localization.md
  31. 130
      docs/en/UI/Blazor/Message.md
  32. 206
      docs/en/UI/Blazor/Navigation-Menu.md
  33. 102
      docs/en/UI/Blazor/Notification.md
  34. 126
      docs/en/UI/Blazor/Overall.md
  35. 62
      docs/en/UI/Blazor/Page-Alerts.md
  36. 62
      docs/en/UI/Blazor/Settings.md
  37. 206
      docs/en/UI/Blazor/Theming.md
  38. 74
      docs/en/UI/Blazor/Toolbars.md
  39. 16
      docs/en/docs-nav.json
  40. BIN
      docs/en/images/basic-theme-application-layout-blazor.png
  41. BIN
      docs/en/images/blazor-message-confirm.png
  42. BIN
      docs/en/images/blazor-message-error.png
  43. BIN
      docs/en/images/blazor-message-success.png
  44. BIN
      docs/en/images/blazor-notification-bell-component.png
  45. BIN
      docs/en/images/blazor-notification-success.png
  46. BIN
      docs/en/images/blazor-page-alert-example.png
  47. BIN
      docs/en/images/bookstore-branding-blazor.png
  48. BIN
      docs/en/images/bookstore-logo-blazor.png
  49. 3
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor
  50. 4
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor
  51. 3
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Alerts/AlertManager.cs
  52. 7
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Alerts/IAlertManager.cs
  53. 6
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs
  54. 11
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertList.cs
  55. 4
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertMessage.cs
  56. 10
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertType.cs
  57. 13
      framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/IAlertManager.cs
  58. 4
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs
  59. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  60. 15
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js
  61. 3
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs
  62. 2
      framework/src/Volo.Abp.BlazoriseUI/Components/AlertWrapper.cs
  63. 4
      framework/src/Volo.Abp.BlazoriseUI/Components/PageAlert.razor.cs
  64. 2
      framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/es.json
  65. 30
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/es.json
  66. 14
      framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextMySQLExtensions.cs
  67. 1
      framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs
  68. 1
      framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleExtensions.cs
  69. 12
      framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextPostgreSqlExtensions.cs
  70. 12
      framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqlServerExtensions.cs
  71. 12
      framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs
  72. 34
      framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/es.json
  73. 3
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs
  74. 20
      framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/es.json
  75. 7
      framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/es.json
  76. 18
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs
  77. 2
      framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/es.json
  78. 52
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json
  79. 52
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/es.json
  80. 31
      modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json
  81. 1
      modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/AbpAuditLoggingEfCoreQueryableExtensions.cs
  82. 6
      modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/es.json
  83. 58
      modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/es.json
  84. 22
      modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json
  85. 10
      modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/es.json
  86. 6
      modules/docs/app/VoloDocs.Web/Utils/GlobalExceptionHandlerMiddleware.cs
  87. 59
      modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/es.json
  88. 38
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json
  89. 10
      modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json
  90. 120
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json
  91. 1
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs
  92. 37
      modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/CreateModal.cshtml
  93. 37
      modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml
  94. 37
      modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml
  95. 37
      modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml
  96. 14
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/es.json
  97. 2
      modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/AbpIdentityServerEfCoreQueryableExtensions.cs
  98. 10
      modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json
  99. 7
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json
  100. 23
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/es.json

14
abp_io/AbpIoLocalization/AbpIoLocalization/Account/Localization/Resources/es.json

@ -0,0 +1,14 @@
{
"culture": "es",
"texts": {
"Account": "Cuenta de ABP - Iniciar sesión y registrarse | ABP.IO",
"Welcome": "Bienvenido",
"UseOneOfTheFollowingLinksToContinue": "Usa uno de los siguientes links para continuar",
"FrameworkHomePage": "Página de inicio del framework",
"FrameworkDocumentation": "Documentación del framework",
"OfficialBlog": "Blog Oficial",
"CommercialHomePage": "Página de inicio comercial",
"CommercialSupportWebSite": "Sitio web de soporte comercial",
"CommunityWebSite": "Sitio web comunidad ABP"
}
}

199
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/es.json

@ -0,0 +1,199 @@
{
"culture": "es",
"texts": {
"Permission:Organizations": "Organizaciones",
"Permission:Manage": "Gestionar organizaciones",
"Permission:DiscountRequests": "Solicitudes de descuento",
"Permission:DiscountManage": "Gestionar solicitudes de descuento",
"Permission:Disable": "Desactivar",
"Permission:Enable": "Activar",
"Permission:EnableSendEmail": "Activar enviar email",
"Permission:SendEmail": "Enviar email",
"Permission:NpmPackages": "Paquetes NPM",
"Permission:NugetPackages": "Paquetes Nuget",
"Permission:Maintenance": "Mantenimiento",
"Permission:Maintain": "Mantener",
"Permission:ClearCaches": "Borrar cachés",
"Permission:Modules": "Módulos",
"Permission:Packages": "Paquetes",
"Permission:Edit": "Editar",
"Permission:Delete": "Borrar",
"Permission:Create": "Crear",
"Permission:Accounting": "Contabilidad",
"Permission:Accounting:Quotation": "Cotización",
"Permission:Accounting:Invoice": "Factura",
"Menu:Organizations": "Organizaciones",
"Menu:Accounting": "Contabilidad",
"Menu:Packages": "Paquetes",
"Menu:DiscountRequests": "Solicitudes de descuento",
"NpmPackageDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?",
"NugetPackageDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?",
"ModuleDeletionWarningMessage": "Este NPM paquete será borrado. ¿Quieres confirmar?",
"Name": "Nombre",
"DisplayName": "Nombre para mostrar",
"ShortDescription": "Descripción corta",
"NameFilter": "Nombre",
"CreationTime": "Fecha de creación",
"IsPro": "Es pro",
"ShowOnModuleList": "Mostrar en la lista de módulos",
"EfCoreConfigureMethodName": "configurar nombre de método",
"IsProFilter": "Es pro",
"ApplicationType": "tipo de aplicación",
"Target": "Destino",
"TargetFilter": "Destino",
"ModuleClass": "Módulo de clase",
"NugetPackageTarget.DomainShared": "Dominio compartido",
"NugetPackageTarget.Domain": "Dominio",
"NugetPackageTarget.Application": "Aplicación",
"NugetPackageTarget.ApplicationContracts": "Contratos de aplicación",
"NugetPackageTarget.HttpApi": "Http Api",
"NugetPackageTarget.HttpApiClient": "Cliente Http Api",
"NugetPackageTarget.Web": "Web",
"NugetPackageTarget.EntityFrameworkCore": "Delete todo EntityFramework Core",
"NugetPackageTarget.MongoDB": "MongoDB",
"Edit": "Editar",
"Delete": "Borrar",
"Refresh": "Refrescar",
"NpmPackages": "Paquetes NPM",
"NugetPackages": "Paquetes Nuget",
"NpmPackageCount": "Número de paquetes NPM",
"NugetPackageCount": "Número de paquetes Nuget",
"Module": "Módulos",
"ModuleInfo": "Info de módulo",
"CreateANpmPackage": "Crear un paquete NPM",
"CreateAModule": "Crear un módulo",
"CreateANugetPackage": "Crear un paquete de Nuget",
"AddNew": "Añadir nuevo",
"PackageAlreadyExist{0}": "\"{0}\" paquete ya se encuentra añadido",
"ModuleAlreadyExist{0}": "\"{0}\" módulo ya se encuentra añadido.",
"ClearCache": "Borrar caché",
"SuccessfullyCleared": "Borrado satisfactoriamente",
"Menu:NpmPackages": "Paquetes de NPM",
"Menu:Modules": "Módulos",
"Menu:Maintenance": "Mantenimiento",
"Menu:NugetPackages": "Paquetes Nuget",
"CreateAnOrganization": "Crear una organización",
"Organizations": "Organizaciones",
"LongName": "Nombre largo",
"LicenseType": "Tipo de licencia",
"MissingLicenseTypeField": "El campo tipo de licencia es requerido!",
"LicenseStartTime": "Fecha de inicio de licencia",
"LicenseEndTime": "Fecha de caducidad de licencia",
"AllowedDeveloperCount": "Número de desarrolladores permitidos",
"UserNameOrEmailAddress": "Nombre de usuario o",
"AddOwner": "Añadir propietario",
"UserName": "Nombre de usuario",
"Email": "Email",
"Developers": "Desarrolladores",
"AddDeveloper": "Añadir desarrollador",
"Create": "Crear",
"UserNotFound": "Usuario no encontrado",
"{0}WillBeRemovedFromDevelopers": "{0} será eliminado de desarrolladores, ¿deseas continuar?",
"{0}WillBeRemovedFromOwners": "{0} será eliminado de propietarios, ¿deseas continuar?",
"Computers": "Ordenadores",
"UniqueComputerId": "Id única de ordenador",
"LastSeenDate": "Fecha de visto por última vez",
"{0}Computer{1}WillBeRemovedFromRecords": "El ordenador {0} ({1}) será eliminado de los registros",
"OrganizationDeletionWarningMessage": "La organización será eliminada",
"DeletingLastOwnerWarningMessage": "Una organización debe tener al menos un propietario!. Por lo tanto, tu no puedes eliminar este propietario",
"This{0}AlreadyExistInThisOrganization": "Este/a {0} ya existe en esta organización",
"AreYouSureYouWantToDeleteAllComputers": "Estás seguro tu quieres eliminar todos los ordenadores",
"DeleteAll": "Eliminar todo",
"DoYouWantToCreateNewUser": "¿Quieres crear un nuevo usuario?",
"MasterModules": "Módulos maestros",
"OrganizationName": "Nombre de organización",
"CreationDate": "Fecha de creación",
"LicenseStartDate": "Fecha de inicio de licencia",
"LicenseEndDate": "Fecha de caducidad de licencia",
"OrganizationNamePlaceholder": "Nombre de organización...",
"TotalQuestionCountPlaceholder": "Número total de preguntas...",
"RemainingQuestionCountPlaceholder": "Número de preguntas pendientes",
"LicenseTypePlaceholder": "Tipo de licencia...",
"CreationDatePlaceholder": "Fecha de creación...",
"LicenseStartDatePlaceholder": "Fecha de inicio de licencia...",
"LicenseEndDatePlaceholder": "Fecha de caducidad de licencia...",
"UsernameOrEmail": "Usuario o email",
"UsernameOrEmailPlaceholder": "Usuario o email...",
"Member": "Miembro",
"PurchaseOrderNo": "Número de orden de compra",
"QuotationDate": "",
"CompanyName": "",
"CompanyAddress": "",
"Price": "",
"DiscountText": "",
"DiscountQuantity": "",
"DiscountPrice": "",
"Quotation": "",
"ExtraText": "",
"ExtraAmount": "",
"DownloadQuotation": "",
"Invoice": "",
"TaxNumber": "",
"InvoiceNumber": "",
"InvoiceDate": "",
"InvoiceNote": "",
"Quantity": "",
"AddProduct": "",
"AddProductWarning": "",
"TotalPrice": "",
"Generate": "",
"MissingQuantityField": "",
"MissingPriceField": "",
"CodeUsageStatus": "",
"Country": "",
"DeveloperCount": "",
"RequestCode": "",
"WebSite": "",
"GithubUsername": "",
"PhoneNumber": "",
"ProjectDescription": "",
"Referrer": "",
"DiscountRequests": "",
"Copylink": "",
"Disable": "",
"Enable": "",
"EnableSendEmail": "",
"SendEmail": "",
"SuccessfullyDisabled": "",
"SuccessfullyEnabled": "",
"EmailSent": "",
"SuccessfullySent": "",
"SuccessfullyDeleted": "",
"DiscountRequestDeletionWarningMessage": "",
"BusinessType": "",
"TotalQuestionCount": "",
"RemainingQuestionCount": "",
"TotalQuestionMustBeGreaterWarningMessage": "",
"QuestionCountsMustBeGreaterThanZero": "",
"UnlimitedQuestionCount": "",
"Notes": "",
"Menu:Community": "",
"Menu:Articles": "",
"Wait": "",
"Approve": "",
"Reject": "",
"Details": "",
"Url": "",
"Title": "",
"ContentSource": "",
"Status": "",
"ReadArticle": "",
"ArticleHasBeenWaiting": "",
"ArticleHasBeenApproved": "",
"ArticleHasBeenRejected": "",
"Permission:Community": "",
"Permission:CommunityArticle": "",
"Link": "",
"Enum:ContentSource:0": "",
"Enum:ContentSource:1": "",
"Enum:Status:0": "",
"Enum:Status:1": "",
"Enum:Status:2": "",
"Summary": "",
"AuthorName": "",
"CoverImage": "",
"RemoveCacheConfirmationMessage": "",
"SuccessfullyRemoved": "",
"RemoveCache": ""
}
}

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

@ -0,0 +1,33 @@
{
"culture": "es",
"texts": {
"Volo.AbpIo.Domain:010004": "",
"Volo.AbpIo.Domain:010005": "",
"Volo.AbpIo.Domain:010006": "",
"Volo.AbpIo.Domain:010007": "",
"Volo.AbpIo.Domain:010008": "",
"Volo.AbpIo.Domain:010009": "",
"Volo.AbpIo.Domain:010010": "",
"Volo.AbpIo.Domain:010011": "",
"Volo.AbpIo.Domain:010012": "",
"Volo.AbpIo.Domain:020001": "",
"Volo.AbpIo.Domain:020002": "",
"Volo.AbpIo.Domain:020003": "",
"Volo.AbpIo.Domain:020004": "",
"WantToLearn?": "",
"ReadyToGetStarted?": "",
"JoinOurCommunity": "",
"GetStartedUpper": "",
"ForkMeOnGitHub": "",
"Features": "",
"GetStarted": "",
"Documents": "",
"Community": "",
"ContributionGuide": "",
"Blog": "",
"Commercial": "",
"MyAccount": "",
"SeeDocuments": "",
"Samples": ""
}
}

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

@ -0,0 +1,35 @@
{
"culture": "es",
"texts": {
"OrganizationManagement": "",
"OrganizationList": "",
"Volo.AbpIo.Commercial:010003": "",
"OrganizationNotFoundMessage": "",
"DeveloperCount": "",
"QuestionCount": "",
"Unlimited": "",
"Owners": "",
"AddMember": "",
"AddOwner": "",
"AddDeveloper": "",
"UserName": "",
"Name": "",
"EmailAddress": "",
"Developers": "",
"LicenseType": "Tipo de licencia",
"Manage": "",
"StartDate": "",
"EndDate": "",
"Modules": "Módulos",
"LicenseExtendMessage": "",
"LicenseUpgradeMessage": "",
"LicenseAddDeveloperMessage": "",
"Volo.AbpIo.Commercial:010004": "",
"MyOrganizations": "",
"ApiKey": "",
"UserNameNotFound": "",
"SuccessfullyAddedToNewsletter": "",
"MyProfile": "",
"EmailNotValid": ""
}
}

90
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/es.json

@ -0,0 +1,90 @@
{
"culture": "es",
"texts": {
"Permission:CommunityArticle": "",
"Permission:Edit": "",
"Waiting": "",
"Approved": "",
"Rejected": "",
"Wait": "",
"Approve": "",
"Reject": "",
"ReadArticle": "",
"Status": "",
"ContentSource": "",
"Details": "",
"Url": "",
"Title": "",
"CreationTime": "",
"Save": "Guardar",
"SameUrlAlreadyExist": "",
"UrlIsNotValid": "",
"UrlNotFound": "",
"UrlContentNotFound": "",
"Summary": "",
"MostRead": "",
"Latest": "",
"ContributeAbpCommunity": "",
"SubmitYourArticle": "",
"ContributionGuide": "",
"BugReport": "",
"SeeAllArticles": "",
"WelcomeToABPCommunity!": "",
"MyProfile": "",
"MyOrganizations": "",
"EmailNotValid": "",
"FeatureRequest": "",
"CreateArticleTitleInfo": "",
"CreateArticleUrlInfo": "",
"CreateArticleSummaryInfo": "",
"CreateArticleCoverInfo": "",
"ThisExtensionIsNotAllowed": "",
"TheFileIsTooLarge": "",
"GoToTheArticle": "",
"Contribute": "",
"OverallProgress": "",
"Done": "",
"Open": "",
"Closed": "",
"LatestQuestionOnThe": "",
"Stackoverflow": "",
"Votes": "",
"Answer": "",
"Views": "",
"Answered": "",
"WaitingForYourAnswer": "",
"Asked": "",
"AllQuestions": "",
"NextVersion": "",
"MilestoneErrorMessage": "",
"QuestionItemErrorMessage": "",
"Oops": "",
"CreateArticleSuccessMessage": "",
"ChooseCoverImage": "",
"CoverImage": "",
"ShareYourExperiencesWithTheABPFramework": "",
"Optional": "",
"UpdateUserWebSiteInfo": "",
"UpdateUserTwitterInfo": "",
"UpdateUserGithubInfo": "",
"UpdateUserLinkedinInfo": "",
"UpdateUserCompanyInfo": "",
"UpdateUserJobTitleInfo": "",
"UserName": "",
"Company": "",
"PersonalWebsite": "",
"RegistrationDate": "",
"Social": "",
"Biography": "",
"HasNoPublishedArticlesYet": "",
"Author": "",
"LatestGithubAnnouncements": "",
"SeeAllAnnouncements": "",
"LatestBlogPost": "",
"Edit": "",
"ProfileImageChange": "",
"BlogItemErrorMessage": "",
"PlannedReleaseDate": "",
"CommunityArticleRequestErrorMessage": ""
}
}

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

@ -0,0 +1,189 @@
{
"culture": "es",
"texts": {
"GetStarted": "",
"Create": "",
"NewProject": "",
"DirectDownload": "",
"ProjectName": "",
"ProjectType": "",
"DatabaseProvider": "",
"NTier": "",
"IncludeUserInterface": "",
"CreateNow": "",
"TheStartupProject": "",
"Tutorial": "",
"UsingCLI": "",
"SeeDetails": "",
"AbpShortDescription": "",
"SourceCodeUpper": "",
"LatestReleaseLogs": "",
"Infrastructure": "",
"Architecture": "",
"Modular": "",
"DontRepeatYourself": "",
"DeveloperFocused": "",
"FullStackApplicationInfrastructure": "",
"DomainDrivenDesign": "",
"DomainDrivenDesignExplanation": "",
"Authorization": "",
"AuthorizationExplanation": "",
"MultiTenancy": "",
"MultiTenancyExplanationShort": "",
"CrossCuttingConcerns": "",
"CrossCuttingConcernsExplanationShort": "",
"BuiltInBundlingMinification": "",
"BuiltInBundlingMinificationExplanation": "",
"VirtualFileSystem": "",
"VirtualFileSystemExplanation": "",
"Theming": "",
"ThemingExplanationShort": "",
"BootstrapTagHelpersDynamicForms": "",
"BootstrapTagHelpersDynamicFormsExplanation": "",
"HTTPAPIsDynamicProxies": "",
"HTTPAPIsDynamicProxiesExplanation": "",
"CompleteArchitectureInfo": "",
"DomainDrivenDesignBasedLayeringModelExplanation": "",
"DomainDrivenDesignBasedLayeringModelExplanationCont": "",
"MicroserviceCompatibleModelExplanation": "",
"MicroserviceCompatibleModelExplanationCont": "",
"ModularInfo": "",
"PreBuiltModulesThemes": "",
"PreBuiltModulesThemesExplanation": "",
"NuGetNPMPackages": "",
"NuGetNPMPackagesExplanation": "",
"ExtensibleReplaceable": "",
"ExtensibleReplaceableExplanation": "",
"CrossCuttingConcernsExplanation2": "",
"CrossCuttingConcernsExplanation3": "",
"AuthenticationAuthorization": "",
"ExceptionHandling": "",
"Validation": "",
"DatabaseConnection": "",
"TransactionManagement": "",
"AuditLogging": "",
"Caching": "",
"Multitenancy": "",
"DataFiltering": "",
"ConventionOverConfiguration": "",
"ConventionOverConfigurationExplanation": "",
"ConventionOverConfigurationExplanationList1": "",
"ConventionOverConfigurationExplanationList2": "",
"ConventionOverConfigurationExplanationList3": "",
"ConventionOverConfigurationExplanationList4": "",
"ConventionOverConfigurationExplanationList5": "",
"ConventionOverConfigurationExplanationList6": "",
"BaseClasses": "",
"BaseClassesExplanation": "",
"DeveloperFocusedExplanation": "",
"DeveloperFocusedExplanationCont": "",
"SeeAllFeatures": "",
"CLI_CommandLineInterface": "",
"CLI_CommandLineInterfaceExplanation": "",
"StartupTemplates": "",
"StartupTemplatesExplanation": "",
"BasedOnFamiliarTools": "",
"BasedOnFamiliarToolsExplanation": "",
"ORMIndependent": "",
"ORMIndependentExplanation": "",
"Features": "",
"ABPCLI": "",
"Modularity": "",
"BootstrapTagHelpers": "",
"DynamicForms": "",
"BundlingMinification": "",
"BackgroundJobs": "",
"BackgroundJobsExplanation": "",
"DDDInfrastructure": "",
"DomainDrivenDesignInfrastructure": "",
"AutoRESTAPIs": "",
"DynamicClientProxies": "",
"DistributedEventBus": "",
"DistributedEventBusWithRabbitMQIntegration": "",
"TestInfrastructure": "",
"AuditLoggingEntityHistories": "",
"ObjectToObjectMapping": "",
"ObjectToObjectMappingExplanation": "",
"EmailSMSAbstractions": "",
"EmailSMSAbstractionsWithTemplatingSupport": "",
"Localization": "",
"SettingManagement": "",
"ExtensionMethods": "",
"ExtensionMethodsHelpers": "",
"AspectOrientedProgramming": "",
"DependencyInjection": "",
"DependencyInjectionByConventions": "",
"ABPCLIExplanation": "",
"ModularityExplanation": "",
"MultiTenancyExplanation": "",
"MultiTenancyExplanation2": "",
"MultiTenancyExplanation3": "",
"MultiTenancyExplanation4": "",
"BootstrapTagHelpersExplanation": "",
"DynamicFormsExplanation": "",
"AuthenticationAuthorizationExplanation": "",
"CrossCuttingConcernsExplanation": "",
"DatabaseConnectionTransactionManagement": "",
"CorrelationIdTracking": "",
"BundlingMinificationExplanation": "",
"VirtualFileSystemnExplanation": "",
"ThemingExplanation": "",
"DomainDrivenDesignInfrastructureExplanation": "",
"Specification": "",
"Repository": "",
"DomainService": "",
"ValueObject": "",
"ApplicationService": "",
"DataTransferObject": "",
"AggregateRootEntity": "",
"AutoRESTAPIsExplanation": "",
"DynamicClientProxiesExplanation": "",
"DistributedEventBusWithRabbitMQIntegrationExplanation": "",
"TestInfrastructureExplanation": "",
"AuditLoggingEntityHistoriesExplanation": "",
"EmailSMSAbstractionsWithTemplatingSupportExplanation": "",
"LocalizationExplanation": "",
"SettingManagementExplanation": "",
"ExtensionMethodsHelpersExplanation": "",
"AspectOrientedProgrammingExplanation": "",
"DependencyInjectionByConventionsExplanation": "",
"DataFilteringExplanation": "",
"PublishEvents": "",
"HandleEvents": "",
"AndMore": "",
"Code": "",
"Result": "",
"SeeTheDocumentForMoreInformation": "",
"IndexPageHeroSection": "",
"UiFramework": "",
"EmailAddress": "",
"Mobile": "",
"ReactNative": "",
"Strong": "",
"Complete": "",
"BasedLayeringModel": "",
"Microservice": "",
"Compatible": "",
"MeeTTheABPCommunityInfo": "",
"JoinTheABPCommunityInfo": "",
"AllArticles": "",
"SubmitYourArticle": "",
"DynamicClientProxyDocument": "",
"EmailSMSAbstractionsDocument": "",
"CreateProjectWizard": "",
"TieredOption": "",
"SeparateIdentityServerOption": "",
"UseslatestPreVersion": "",
"ReadTheDocumentation": "",
"Documentation": "",
"GettingStartedTutorial": "",
"ApplicationDevelopmentTutorial": "",
"TheStartupTemplate": "",
"InstallABPCLIInfo": "",
"DifferentLevelOfNamespaces": "",
"ABPCLIExamplesInfo": "",
"SeeCliDocumentForMoreInformation": "",
"Optional": "",
"LocalFrameworkRef": ""
}
}

18
docs/en/CLI.md

@ -41,6 +41,7 @@ Here, the list of all available commands before explaining their details:
* **`login`**: Authenticates on your computer with your [abp.io](https://abp.io/) username and password.
* **`logout`**: Logouts from your computer if you've authenticated before.
* **`build`**: Builds a GIT repository and depending repositories or a single .NET solution.
* **`bundle`**: Generates script and style references for an ABP Blazor project.
### help
@ -400,3 +401,20 @@ abp build --build-name "prod" --dotnet-build-arguments "\"--no-dependencies\""
For more details, see [build command documentation](CLI-BuildCommand.md).
#### bundle
This command generates script and style references for an ABP Blazor project and updates the **index.html** file. It helps developers to manage dependencies required by ABP modules easily. In order ```bundle``` command to work, its **executing directory** or passed ```--working-directory``` parameter's directory must contain a Blazor project file(*.csproj).
Usage:
````bash
abp bundle [options]
````
#### Options
* ```--working-directory``` or ```-wd```: Specifies the working directory. This option is useful when executing directory doesn't contain a Blazor project file.
* ```--force``` or ```-f```: Forces to build project before generating references.
For more details about managing style and script references in Blazor apps, see [Managing Global Scripts & Styles](UI/Blazor/Global-Scripts-Styles.md)

2
docs/en/Getting-Started-AspNetCore-Application.md

@ -4,7 +4,7 @@ This tutorial explains how to start ABP from scratch with minimal dependencies.
## Create A New Project
1. Create a new AspNet Core Web Application from Visual Studio 2019 (16.4.0+):
1. Create a new AspNet Core Web Application from Visual Studio 2019 (16.8.0+):
![](images/create-new-aspnet-core-application-v2.png)

13
docs/en/Getting-Started.md

@ -22,15 +22,14 @@ First things first! Let's setup your development environment before creating the
The following tools should be installed on your development machine:
* [Visual Studio 2019](https://visualstudio.microsoft.com/vs/) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). <sup id="a-editor">[1](#f-editor)</sup>
* [.NET Core 3.1+](https://www.microsoft.com/net/download/dotnet-core/)
* [Visual Studio 2019](https://visualstudio.microsoft.com/vs/) (v16.8+) for Windows / [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/). <sup id="a-editor">[1](#f-editor)</sup>
* [.NET Core 5.0+](https://www.microsoft.com/net/download/dotnet-core/)
{{ if UI != "Blazor" }}
* [Node v12 or v14](https://nodejs.org/)
* [Yarn v1.20+ (not v2)](https://classic.yarnpkg.com/en/docs/install) <sup id="a-yarn">[2](#f-yarn)</sup> or npm v6+ (already installed with Node)
{{ end }}
{{ if Tiered == "Yes" }}
* [Redis](https://redis.io/) (the startup solution uses the Redis as the [distributed cache](Caching.md)).
{{ end }}
<sup id="f-editor"><b>1</b></sup> _You can use another editor instead of Visual Studio as long as it supports .NET Core and ASP.NET Core._ <sup>[↩](#a-editor)</sup>
@ -202,6 +201,8 @@ Right click to the `.DbMigrator` project and select **Set as StartUp Project**
{{ if Tiered == "Yes" }}
> Tiered solutions use Redis as the distributed cache. Ensure that it is installed and running in your local computer. If you are using a remote Redis Server, set the configuration in the `appsettings.json` files of the projects below.
1. Ensure that the `.IdentityServer` project is the startup project. Run this application that will open a **login** page in your browser.
> Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster.
@ -238,6 +239,8 @@ Ensure that the `.Web` project is the startup project. Run the application which
{{ if Tiered == "Yes" }}
> Tiered solutions use Redis as the distributed cache. Ensure that it is installed and running in your local computer. If you are using a remote Redis Server, set the configuration in the `appsettings.json` files of the projects below.
Ensure that the `.IdentityServer` project is the startup project. Run the application which will open a **login** page in your browser.
> Use Ctrl+F5 in Visual Studio (instead of F5) to run the application without debugging. If you don't have a debug purpose, this will be faster.

4
docs/en/Localization.md

@ -162,8 +162,8 @@ Getting the localized text is pretty standard.
Just inject the `IStringLocalizer<TResource>` service and use it like shown below:
````C#
public class MyService
````csharp
public class MyService : ITransientDependency
{
private readonly IStringLocalizer<TestResource> _localizer;

2
docs/en/Migration-Guides/Abp-4_0-Blazor.md

@ -85,4 +85,4 @@ If you've derived your pages from the `AbpCrudPageBase` class, then you may need
## Others
- Refactored namespaces for some Blazor components ([#6015](https://github.com/abpframework/abp/issues/6015)).
- Removed Async Suffix from IUiMessageService ([#6123](https://github.com/abpframework/abp/pull/6123)).
- Removed Async Suffix from IUiMessageService methods ([#6123](https://github.com/abpframework/abp/pull/6123)).

2
docs/en/Migration-Guides/Abp-4_0.md

@ -2,7 +2,7 @@
This document introduces the breaking changes done in the ABP Framework 4.0 and explains how to fix your 3.x based solutions while upgrading to the ABP Framework 4.0.
> See this blog post (TODO: LINK) to learn what's new with the ABP Framework 4.0. This document only focuses on the breaking changes.
> See [the blog post](https://blog.abp.io/abp/ABP.IO-Platform-v4.0-RC-Has-Been-Released-based-on-.NET-5.0) to learn what's new with the ABP Framework 4.0. This document only focuses on the breaking changes.
## Overall

41
docs/en/Tutorials/Part-10.md

@ -50,7 +50,7 @@ public Guid AuthorId { get; set; }
{{if DB=="EF"}}
> In this tutorial, we preferred to not add a **navigation property** to the `Author` entity from the `Book` class (like `public Author Author { get; set; }`). This is due to follow the DDD best practices (rule: refer to other aggregates only by id). However, you can add such a navigation property and configure it for the EF Core. In this way, you don't need to write join queries while getting books with their authors (just like we will done below) which makes your application code simpler.
> In this tutorial, we preferred to not add a **navigation property** to the `Author` entity from the `Book` class (like `public Author Author { get; set; }`). This is due to follow the DDD best practices (rule: refer to other aggregates only by id). However, you can add such a navigation property and configure it for the EF Core. In this way, you don't need to write join queries while getting books with their authors (like we will done below) which makes your application code simpler.
{{end}}
@ -362,7 +362,7 @@ namespace Acme.BookStore.Books
DeletePolicyName = BookStorePermissions.Books.Create;
}
public async override Task<BookDto> GetAsync(Guid id)
public override async Task<BookDto> GetAsync(Guid id)
{
await CheckGetPolicyAsync();
@ -384,8 +384,8 @@ namespace Acme.BookStore.Books
return bookDto;
}
public async override Task<PagedResultDto<BookDto>>
GetListAsync(PagedAndSortedResultRequestDto input)
public override async Task<PagedResultDto<BookDto>> GetListAsync(
PagedAndSortedResultRequestDto input)
{
await CheckGetListPolicyAsync();
@ -1082,36 +1082,37 @@ Add the following field to the `@code` section of the `Books.razor` file:
IReadOnlyList<AuthorLookupDto> authorList = Array.Empty<AuthorLookupDto>();
````
And fill it in the `OnInitializedAsync` method, by adding the following code to the end of the method:
Override the `OnInitializedAsync` method and adding the following code:
````csharp
authorList = (await AppService.GetAuthorLookupAsync()).Items;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
authorList = (await AppService.GetAuthorLookupAsync()).Items;
}
````
* It is essential to call the `base.OnInitializedAsync()` since `AbpCrudPageBase` has some initialization code to be executed.
The final `@code` block should be the following:
````csharp
@code
{
bool canCreateBook;
bool canEditBook;
bool canDeleteBook;
//ADDED A NEW FIELD
IReadOnlyList<AuthorLookupDto> authorList = Array.Empty<AuthorLookupDto>();
protected async override Task OnInitializedAsync()
public Books() // Constructor
{
await base.OnInitializedAsync();
canCreateBook = await
AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create);
canEditBook = await
AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Edit);
canDeleteBook = await
AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Delete);
CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete;
}
//GET AUTHORS
//GET AUTHORS ON INITIALIZATION
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
authorList = (await AppService.GetAuthorLookupAsync()).Items;
}
}

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

@ -590,7 +590,6 @@ Open the `Books.razor` and replace the content as the following:
````xml
@page "/books"
@using Volo.Abp.Application.Dtos
@using Volo.Abp.BlazoriseUI
@using Acme.BookStore.Books
@using Acme.BookStore.Localization
@using Microsoft.Extensions.Localization
@ -620,14 +619,14 @@ Open the `Books.razor` and replace the content as the following:
</DisplayTemplate>
</DataGridColumn>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.PublishDate)"
Field="@nameof(BookDto.PublishDate)"
Caption="@L["PublishDate"]">
<DisplayTemplate>
@context.PublishDate.ToShortDateString()
</DisplayTemplate>
</DataGridColumn>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.Price)"
Field="@nameof(BookDto.Price)"
Caption="@L["Price"]">
</DataGridColumn>
<DataGridColumn TItem="BookDto"

449
docs/en/Tutorials/Part-3.md

@ -1171,15 +1171,13 @@ Open the `Books.razor` and replace the `<CardHeader>` section with the following
````xml
<CardHeader>
<Row>
<Column ColumnSize="ColumnSize.Is6">
<Row Class="justify-content-between">
<Column ColumnSize="ColumnSize.IsAuto">
<h2>@L["Books"]</h2>
</Column>
<Column ColumnSize="ColumnSize.Is6">
<Paragraph Alignment="TextAlignment.Right">
<Button Color="Color.Primary"
Clicked="OpenCreateModalAsync">@L["NewBook"]</Button>
</Paragraph>
<Column ColumnSize="ColumnSize.IsAuto">
<Button Color="Color.Primary"
Clicked="OpenCreateModalAsync">@L["NewBook"]</Button>
</Column>
</Row>
</CardHeader>
@ -1196,48 +1194,67 @@ Now, we can add a modal that will be opened when we click to the button.
Open the `Books.razor` and add the following code to the end of the page:
````xml
<Modal @ref="CreateModal">
<Modal @ref="@CreateModal">
<ModalBackdrop />
<ModalContent IsCentered="true">
<ModalHeader>
<ModalTitle>@L["NewBook"]</ModalTitle>
<CloseButton Clicked="CloseCreateModalAsync" />
</ModalHeader>
<ModalBody>
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-text="NewEntity.Name" />
</Field>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@NewEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType)bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="NewEntity.PublishDate" />
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="NewEntity.Price" />
</Field>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Clicked="CreateEntityAsync">@L["Save"]</Button>
</ModalFooter>
<Form>
<ModalHeader>
<ModalTitle>@L["NewBook"]</ModalTitle>
<CloseButton Clicked="CloseCreateModalAsync"/>
</ModalHeader>
<ModalBody>
<Validations @ref="@CreateValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-Text="@NewEntity.Name">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@NewEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType) bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="NewEntity.PublishDate"/>
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="NewEntity.Price"/>
</Field>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Type="@ButtonType.Submit"
PreventDefaultOnSubmit="true"
Clicked="CreateEntityAsync">@L["Save"]</Button>
</ModalFooter>
</Form>
</ModalContent>
</Modal>
````
This code requires a service; Inject the `AbpBlazorMessageLocalizerHelper<T>` at the top of the file, just before the `@inherits...` line:
````csharp
@inject AbpBlazorMessageLocalizerHelper<BookStoreResource> LH
````
* The form implements validation and the `AbpBlazorMessageLocalizerHelper` is used to simply localize the validation messages.
* `CreateModal` object, `CloseCreateModalAsync` and `CreateEntityAsync` method are defined by the base class. See the [Blazorise documentation](https://blazorise.com/docs/) if you want to understand the `Modal` and the other components.
That's all. Run the application and try to add a new book:
@ -1250,78 +1267,81 @@ Editing a books is similar to the creating a new book.
### Actions Dropdown
Open the `Books.razor` and add the following `DataGridColumn` section inside the `DataGridColumns` as the first item:
Open the `Books.razor` and add the following `DataGridEntityActionsColumn` section inside the `DataGridColumns` as the first item:
````xml
<DataGridColumn Width="150px"
TItem="BookDto"
Field="@nameof(BookDto.Id)"
Sortable="false"
Caption="@L["Actions"]">
<DataGridEntityActionsColumn TItem="BookDto" @ref="@EntityActionsColumn">
<DisplayTemplate>
<Dropdown>
<DropdownToggle Color="Color.Primary">
@L["Actions"]
</DropdownToggle>
<DropdownMenu>
<DropdownItem Clicked="() => OpenEditModalAsync(context)">
@L["Edit"]
</DropdownItem>
</DropdownMenu>
</Dropdown>
<EntityActions TItem="BookDto" EntityActionsColumn="@EntityActionsColumn">
<EntityAction TItem="BookDto"
Text="@L["Edit"]"
Clicked="() => OpenEditModalAsync(context)" />
</EntityActions>
</DisplayTemplate>
</DataGridColumn>
</DataGridEntityActionsColumn>
````
* `OpenEditModalAsync` is defined in the base class which takes the entity (book) to edit.
This adds an "Actions" dropdown to all the books inside the `DataGrid` with an `Edit` action:
`DataGridEntityActionsColumn` component is used to show an "Actions" dropdown for each row in the `DataGrid`. `DataGridEntityActionsColumn` shows a **single button** instead of a dropdown if there is only one available action inside it:
![blazor-edit-book-action](images/blazor-edit-book-action.png)
![blazor-edit-book-action](images/blazor-edit-book-action-2.png)
### Edit Modal
We can now define a modal to edit the book. Add the following code to the end of the `Books.razor` page:
````xml
<Modal @ref="EditModal">
<Modal @ref="@EditModal">
<ModalBackdrop />
<ModalContent IsCentered="true">
<ModalHeader>
<ModalTitle>@EditingEntity.Name</ModalTitle>
<CloseButton Clicked="CloseEditModalAsync" />
</ModalHeader>
<ModalBody>
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.Name" />
</Field>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@EditingEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType)bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="EditingEntity.PublishDate" />
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="EditingEntity.Price" />
</Field>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Clicked="UpdateEntityAsync">@L["Save"]</Button>
</ModalFooter>
<Form>
<ModalHeader>
<ModalTitle>@EditingEntity.Name</ModalTitle>
<CloseButton Clicked="CloseEditModalAsync"/>
</ModalHeader>
<ModalBody>
<Validations @ref="@EditValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-Text="@EditingEntity.Name">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@EditingEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType) bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="EditingEntity.PublishDate"/>
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="EditingEntity.Price"/>
</Field>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Type="@ButtonType.Submit"
PreventDefaultOnSubmit="true"
Clicked="UpdateEntityAsync">@L["Save"]</Button>
</ModalFooter>
</Form>
</ModalContent>
</Modal>
````
@ -1356,17 +1376,26 @@ You can now run the application and try to edit a book.
![blazor-edit-book-modal](images/blazor-edit-book-modal.png)
> Tip: Try to leave the *Name* field empty and submit the form to show the validation error message.
## Deleting a Book
Open the `Books.razor` page and add the following `DropdownItem` under the "Edit" action inside the "Actions" `DropdownMenu`:
Open the `Books.razor` page and add the following `EntityAction` under the "Edit" action inside the `EntityActions`:
````xml
<DropdownItem Clicked="() => DeleteEntityAsync(context)">
@L["Delete"]
</DropdownItem>
<EntityAction TItem="BookDto"
Text="@L["Delete"]"
Clicked="() => DeleteEntityAsync(context)"
ConfirmationMessage="@() => GetDeleteConfirmationMessage(context)" />
````
* `DeleteEntityAsync` is defined in the base class.
* `DeleteEntityAsync` is defined in the base class that deletes the entity by performing a call to the server.
* `ConfirmationMessage` is a callback to show a confirmation message before executing the action.
* `GetDeleteConfirmationMessage` is defined in the base class. You can override this method (or pass another value to the `ConfirmationMessage` parameter) to customize the localization message.
The "Actions" button becomes a dropdown since it has two actions now:
![blazor-edit-book-action](images/blazor-delete-book-action.png)
Run the application and try to delete a book.
@ -1377,26 +1406,22 @@ Here the complete code to create the book management CRUD page, that has been de
````xml
@page "/books"
@using Volo.Abp.Application.Dtos
@using Volo.Abp.BlazoriseUI
@using Acme.BookStore.Books
@using Acme.BookStore.Localization
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<BookStoreResource> L
@inject AbpBlazorMessageLocalizerHelper<BookStoreResource> LH
@inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>
<Card>
<CardHeader>
<Row>
<Column ColumnSize="ColumnSize.Is6">
<Row Class="justify-content-between">
<Column ColumnSize="ColumnSize.IsAuto">
<h2>@L["Books"]</h2>
</Column>
<Column ColumnSize="ColumnSize.Is6">
<Paragraph Alignment="TextAlignment.Right">
<Column ColumnSize="ColumnSize.IsAuto">
<Button Color="Color.Primary"
Clicked="OpenCreateModalAsync">
@L["NewBook"]
</Button>
</Paragraph>
Clicked="OpenCreateModalAsync">@L["NewBook"]</Button>
</Column>
</Row>
</CardHeader>
@ -1408,27 +1433,19 @@ Here the complete code to create the book management CRUD page, that has been de
ShowPager="true"
PageSize="PageSize">
<DataGridColumns>
<DataGridColumn Width="150px"
TItem="BookDto"
Field="@nameof(BookDto.Id)"
Sortable="false"
Caption="@L["Actions"]">
<DataGridEntityActionsColumn TItem="BookDto" @ref="@EntityActionsColumn">
<DisplayTemplate>
<Dropdown>
<DropdownToggle Color="Color.Primary">
@L["Actions"]
</DropdownToggle>
<DropdownMenu>
<DropdownItem Clicked="() => OpenEditModalAsync(context)">
@L["Edit"]
</DropdownItem>
<DropdownItem Clicked="() => DeleteEntityAsync(context)">
@L["Delete"]
</DropdownItem>
</DropdownMenu>
</Dropdown>
<EntityActions TItem="BookDto" EntityActionsColumn="@EntityActionsColumn">
<EntityAction TItem="BookDto"
Text="@L["Edit"]"
Clicked="() => OpenEditModalAsync(context)" />
<EntityAction TItem="BookDto"
Text="@L["Delete"]"
Clicked="() => DeleteEntityAsync(context)"
ConfirmationMessage="()=>GetDeleteConfirmationMessage(context)" />
</EntityActions>
</DisplayTemplate>
</DataGridColumn>
</DataGridEntityActionsColumn>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.Name)"
Caption="@L["Name"]"></DataGridColumn>
@ -1436,7 +1453,7 @@ Here the complete code to create the book management CRUD page, that has been de
Field="@nameof(BookDto.Type)"
Caption="@L["Type"]">
<DisplayTemplate>
@L[$"Enum:BookType:{(int)context.Type}"]
@L[$"Enum:BookType:{(int) context.Type}"]
</DisplayTemplate>
</DataGridColumn>
<DataGridColumn TItem="BookDto"
@ -1462,85 +1479,109 @@ Here the complete code to create the book management CRUD page, that has been de
</CardBody>
</Card>
<Modal @ref="CreateModal">
<Modal @ref="@CreateModal">
<ModalBackdrop />
<ModalContent IsCentered="true">
<ModalHeader>
<ModalTitle>@L["NewBook"]</ModalTitle>
<CloseButton Clicked="CloseCreateModalAsync" />
</ModalHeader>
<ModalBody>
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-text="NewEntity.Name" />
</Field>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@NewEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType)bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="NewEntity.PublishDate" />
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="NewEntity.Price" />
</Field>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Clicked="CreateEntityAsync">@L["Save"]</Button>
</ModalFooter>
<Form>
<ModalHeader>
<ModalTitle>@L["NewBook"]</ModalTitle>
<CloseButton Clicked="CloseCreateModalAsync"/>
</ModalHeader>
<ModalBody>
<Validations @ref="@CreateValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-Text="@NewEntity.Name">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@NewEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType) bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="NewEntity.PublishDate"/>
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="NewEntity.Price"/>
</Field>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseCreateModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Type="@ButtonType.Submit"
PreventDefaultOnSubmit="true"
Clicked="CreateEntityAsync">@L["Save"]</Button>
</ModalFooter>
</Form>
</ModalContent>
</Modal>
<Modal @ref="EditModal">
<Modal @ref="@EditModal">
<ModalBackdrop />
<ModalContent IsCentered="true">
<ModalHeader>
<ModalTitle>@EditingEntity.Name</ModalTitle>
<CloseButton Clicked="CloseEditModalAsync" />
</ModalHeader>
<ModalBody>
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-text="EditingEntity.Name" />
</Field>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@EditingEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType)bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="EditingEntity.PublishDate" />
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="EditingEntity.Price" />
</Field>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Clicked="UpdateEntityAsync">@L["Save"]</Button>
</ModalFooter>
<Form>
<ModalHeader>
<ModalTitle>@EditingEntity.Name</ModalTitle>
<CloseButton Clicked="CloseEditModalAsync"/>
</ModalHeader>
<ModalBody>
<Validations @ref="@EditValidationsRef" Model="@NewEntity" ValidateOnLoad="false">
<Validation MessageLocalizer="@LH.Localize">
<Field>
<FieldLabel>@L["Name"]</FieldLabel>
<TextEdit @bind-Text="@EditingEntity.Name">
<Feedback>
<ValidationError/>
</Feedback>
</TextEdit>
</Field>
</Validation>
<Field>
<FieldLabel>@L["Type"]</FieldLabel>
<Select TValue="BookType" @bind-SelectedValue="@EditingEntity.Type">
@foreach (int bookTypeValue in Enum.GetValues(typeof(BookType)))
{
<SelectItem TValue="BookType" Value="@((BookType) bookTypeValue)">
@L[$"Enum:BookType:{bookTypeValue}"]
</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["PublishDate"]</FieldLabel>
<DateEdit TValue="DateTime" @bind-Date="EditingEntity.PublishDate"/>
</Field>
<Field>
<FieldLabel>@L["Price"]</FieldLabel>
<NumericEdit TValue="float" @bind-Value="EditingEntity.Price"/>
</Field>
</Validations>
</ModalBody>
<ModalFooter>
<Button Color="Color.Secondary"
Clicked="CloseEditModalAsync">@L["Cancel"]</Button>
<Button Color="Color.Primary"
Type="@ButtonType.Submit"
PreventDefaultOnSubmit="true"
Clicked="UpdateEntityAsync">@L["Save"]</Button>
</ModalFooter>
</Form>
</ModalContent>
</Modal>
````

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

@ -126,7 +126,7 @@ public async Task Should_Create_A_Valid_Book()
{
Name = "New test book 42",
Price = 10,
PublishDate = System.DateTime.Now,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);
@ -208,7 +208,7 @@ namespace Acme.BookStore.Books
{
Name = "New test book 42",
Price = 10,
PublishDate = System.DateTime.Now,
PublishDate = DateTime.Now,
Type = BookType.ScienceFiction
}
);

138
docs/en/Tutorials/Part-5.md

@ -70,7 +70,7 @@ namespace Acme.BookStore.Permissions
}
````
This is a hierarchical way of defining permission names. For example, "create book" permission name was defined as `BookStore.Books.Create`.
This is a hierarchical way of defining permission names. For example, "create book" permission name was defined as `BookStore.Books.Create`. ABP doesn't force you to a structure, but we find this way useful.
### Permission Definitions
@ -423,13 +423,13 @@ Open the `/src/app/book/book.component.html` file and replace the create button
````html
<!-- Add the abpPermission directive -->
<button abpPermission="BookStore.Books.Create" id="create" class="btn btn-primary" type="button" (click)="createBook()">
<button *abpPermission="'BookStore.Books.Create'" id="create" class="btn btn-primary" type="button" (click)="createBook()">
<i class="fa fa-plus mr-1"></i>
<span>{%{{{ '::NewBook' | abpLocalization }}}%}</span>
</button>
````
* Just added `abpPermission="BookStore.Books.Create"` that hides the button if the current user has no permission.
* Just added `*abpPermission="'BookStore.Books.Create'"` that hides the button if the current user has no permission.
### Hide the Edit and Delete Actions
@ -443,18 +443,18 @@ Open the `/src/app/book/book.component.html` file and replace the edit and delet
````html
<!-- Add the abpPermission directive -->
<button abpPermission="BookStore.Books.Edit" ngbDropdownItem (click)="editBook(row.id)">
<button *abpPermission="'BookStore.Books.Edit'" ngbDropdownItem (click)="editBook(row.id)">
{%{{{ '::Edit' | abpLocalization }}}%}
</button>
<!-- Add the abpPermission directive -->
<button abpPermission="BookStore.Books.Delete" ngbDropdownItem (click)="delete(row.id)">
<button *abpPermission="'BookStore.Books.Delete'" ngbDropdownItem (click)="delete(row.id)">
{%{{{ '::Delete' | abpLocalization }}}%}
</button>
````
* Added `abpPermission="BookStore.Books.Edit"` that hides the edit action if the current user has no editing permission.
* Added `abpPermission="BookStore.Books.Delete"` that hides the delete action if the current user has no delete permission.
* Added `*abpPermission="'BookStore.Books.Edit'"` that hides the edit action if the current user has no editing permission.
* Added `*abpPermission="'BookStore.Books.Delete'"` that hides the delete action if the current user has no delete permission.
{{else if UI == "Blazor"}}
@ -476,29 +476,29 @@ Adding this attribute prevents to enter this page if the current hasn't logged i
The book management page has a *New Book* button and *Edit* and *Delete* actions for each book. We should hide these buttons/actions if the current user has not granted for the related permissions.
#### Get the Permissions On Initialization
The base `AbpCrudPageBase` class already has the necessary functionality for these kind of operations.
#### Set the Policy (Permission) Names
Add the following code block to the end of the `Books.razor` file:
````csharp
@code
{
bool canCreateBook;
bool canEditBook;
bool canDeleteBook;
protected async override Task OnInitializedAsync()
public Books() // Constructor
{
await base.OnInitializedAsync();
canCreateBook =await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Create);
canEditBook = await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Edit);
canDeleteBook = await AuthorizationService.IsGrantedAsync(BookStorePermissions.Books.Delete);
CreatePolicyName = BookStorePermissions.Books.Create;
UpdatePolicyName = BookStorePermissions.Books.Edit;
DeletePolicyName = BookStorePermissions.Books.Delete;
}
}
````
We will use these `bool` fields to check the permissions. `AuthorizationService` comes from the base class as an injected property.
The base `AbpCrudPageBase` class automatically checks these permissions on the related operations. It also defines the given properties for us if we need to check them manually:
* `HasCreatePermission`: True, if the current user has permission to create the entity.
* `HasUpdatePermission`: True, if the current user has permission to edit/update the entity.
* `HasDeletePermission`: True, if the current user has permission to delete the entity.
> **Blazor Tip**: While adding the C# code into a `@code` block is fine for small code parts, it is suggested to use the code behind approach to develop a more maintainable code base when the code block becomes longer. We will use this approach for the authors part.
@ -507,32 +507,31 @@ We will use these `bool` fields to check the permissions. `AuthorizationService`
Wrap the *New Book* button by an `if` block as shown below:
````xml
@if (canCreateBook)
@if (HasCreatePermission)
{
<Button Color="Color.Primary"
Clicked="OpenCreateModalAsync">
@L["NewBook"]
</Button>
Clicked="OpenCreateModalAsync">@L["NewBook"]</Button>
}
````
#### Hide the Edit/Delete Actions
As similar to the *New Book* button, we can use `if` blocks to conditionally show/hide the *Edit* and *Delete* actions:
`EntityAction` component defines `RequiredPolicy` attribute (parameter) to conditionally show the action based on the user permissions.
Update the `EntityActions` section as shown below:
````xml
@if (canEditBook)
{
<DropdownItem Clicked="() => OpenEditModalAsync(context)">
@L["Edit"]
</DropdownItem>
}
@if (canDeleteBook)
{
<DropdownItem Clicked="() => DeleteEntityAsync(context)">
@L["Delete"]
</DropdownItem>
}
<EntityActions TItem="BookDto" EntityActionsColumn="@EntityActionsColumn">
<EntityAction TItem="BookDto"
Text="@L["Edit"]"
RequiredPolicy="@UpdatePolicyName"
Clicked="() => OpenEditModalAsync(context)" />
<EntityAction TItem="BookDto"
Text="@L["Delete"]"
RequiredPolicy="@DeletePolicyName"
Clicked="() => DeleteEntityAsync(context)"
ConfirmationMessage="()=>GetDeleteConfirmationMessage(context)" />
</EntityActions>
````
#### About the Permission Caching
@ -587,54 +586,39 @@ if (await context.IsGrantedAsync(BookStorePermissions.Books.Default))
}
````
You also need to add `async` keyword to the `ConfigureMenuAsync` method and re-arrange the return values. The final `BookStoreMenuContributor` class should be the following:
You also need to add `async` keyword to the `ConfigureMenuAsync` method and re-arrange the return value. The final `ConfigureMainMenuAsync` method should be the following:
````csharp
using System.Threading.Tasks;
using Acme.BookStore.Localization;
using Acme.BookStore.Permissions;
using Volo.Abp.UI.Navigation;
namespace Acme.BookStore.Blazor
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
{
public class BookStoreMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if(context.Menu.DisplayName != StandardMenus.Main)
{
return;
}
var l = context.GetLocalizer<BookStoreResource>();
var l = context.GetLocalizer<BookStoreResource>();
context.Menu.Items.Insert(
0,
new ApplicationMenuItem(
"BookStore.Home",
l["Menu:Home"],
"/",
icon: "fas fa-home"
)
);
context.Menu.Items.Insert(
0,
new ApplicationMenuItem(
"BookStore.Home",
l["Menu:Home"],
"/",
icon: "fas fa-home"
)
);
var bookStoreMenu = new ApplicationMenuItem(
"BooksStore",
l["Menu:BookStore"],
icon: "fa fa-book"
);
var bookStoreMenu = new ApplicationMenuItem(
"BooksStore",
l["Menu:BookStore"],
icon: "fa fa-book"
);
context.Menu.AddItem(bookStoreMenu);
context.Menu.AddItem(bookStoreMenu);
if (await context.IsGrantedAsync(BookStorePermissions.Books.Default))
{
bookStoreMenu.AddItem(new ApplicationMenuItem(
"BooksStore.Books",
l["Menu:Books"],
url: "/books"
));
}
}
//CHECK the PERMISSION
if (await context.IsGrantedAsync(BookStorePermissions.Books.Default))
{
bookStoreMenu.AddItem(new ApplicationMenuItem(
"BooksStore.Books",
l["Menu:Books"],
url: "/books"
));
}
}
````

17
docs/en/Tutorials/Part-9.md

@ -843,15 +843,8 @@ Create a new Razor Component Page, `/Pages/Authors.razor`, in the `Acme.BookStor
````xml
@page "/authors"
@using Acme.BookStore.Authors
@using Acme.BookStore.Localization
@using Microsoft.AspNetCore.Authorization
@using Microsoft.Extensions.Localization
@using Volo.Abp.ObjectMapping
@inherits BookStoreComponentBase
@inject IAuthorAppService AuthorAppService
@inject IStringLocalizer<BookStoreResource> L
@inject IAuthorizationService AuthorizationService
@inject IUiMessageService UiMessageService
@inject IObjectMapper ObjectMapper
<Card>
<CardHeader>
<Row>
@ -1038,7 +1031,7 @@ namespace Acme.BookStore.Blazor.Pages
EditingAuthor = new UpdateAuthorDto();
}
protected async override Task OnInitializedAsync()
protected override async Task OnInitializedAsync()
{
await SetPermissionsAsync();
await GetAuthorsAsync();
@ -1048,10 +1041,10 @@ namespace Acme.BookStore.Blazor.Pages
{
CanCreateAuthor = await AuthorizationService
.IsGrantedAsync(BookStorePermissions.Authors.Create);
CanEditAuthor = await AuthorizationService
.IsGrantedAsync(BookStorePermissions.Authors.Edit);
CanDeleteAuthor = await AuthorizationService
.IsGrantedAsync(BookStorePermissions.Authors.Delete);
}
@ -1105,7 +1098,7 @@ namespace Acme.BookStore.Blazor.Pages
private async Task DeleteAuthorAsync(AuthorDto author)
{
var confirmMessage = L["AuthorDeletionConfirmationMessage", author.Name];
if (!await UiMessageService.ConfirmAsync(confirmMessage))
if (!await Message.Confirm(confirmMessage))
{
return;
}

BIN
docs/en/Tutorials/images/blazor-bookstore-book-list.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 60 KiB

BIN
docs/en/Tutorials/images/blazor-delete-book-action.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
docs/en/Tutorials/images/blazor-edit-book-action-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

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

@ -54,8 +54,6 @@ You can use the `PermissionDirective` to manage visibility of a DOM Element acco
As shown above you can remove elements from DOM with `abpPermission` structural directive.
The directive can also be used as an attribute directive but we recommend to you to use it as a structural directive.
## Permission Guard
You can use `PermissionGuard` if you want to control authenticated user's permission to access to the route during navigation.

2
docs/en/UI/AspNetCore/Branding.md

@ -11,7 +11,7 @@ The screenshot below shows *MyProject* as the application name:
You can implement the `IBrandingProvider` interface or inherit from the `DefaultBrandingProvider` to set the application name:
````csharp
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components;
using Volo.Abp.Ui.Branding;
using Volo.Abp.DependencyInjection;
namespace MyProject.Web

2
docs/en/UI/AspNetCore/Customization-User-Interface.md

@ -1,6 +1,6 @@
# ASP.NET Core (MVC / Razor Pages) User Interface Customization Guide
This document explains how to override the user interface of a depended [application module](../../Modules/Index.md) for ASP.NET Core MVC / Razor Page applications.
This document explains how to override the user interface of a depended [application module](../../Modules/Index.md) or [theme](Theming.md) for ASP.NET Core MVC / Razor Page applications.
## Overriding a Page

12
docs/en/UI/AspNetCore/Navigation-Menu.md

@ -13,6 +13,8 @@ So, ABP Framework **provides a menu infrastructure** where;
In order to add menu items (or manipulate the existing items) you need to create a class implementing the `IMenuContributor` interface.
> The [application startup template](../../Startup-Templates/Application.md) already contains an implementation of the `IMenuContributor`. So, you can add items inside that class instead of creating a new one.
**Example: Add a *CRM* menu item with *Customers* and *Orders* sub menu items**
```csharp
@ -66,6 +68,16 @@ Configure<AbpNavigationOptions>(options =>
});
````
This example uses some localization keys as display names those should be defined in the localization file:
````json
"Menu:CRM": "CRM",
"Menu:Orders": "Orders",
"Menu:Customers": "Customers"
````
See the [localization document](../../Localization.md) to learn more about the localization.
When you run the application, you will see the menu items added to the main menu:
![nav-main-menu](../../images/nav-main-menu.png)

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

@ -0,0 +1,57 @@
# Blazor UI: Basic Theme
The Basic Theme is a theme implementation for the Blazor UI. It is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/). You can take the Basic Theme as the **base theme** and build your own theme or styling on top of it. See the *Customization* section.
> If you are looking for a professional, enterprise ready theme, you can check the [Lepton Theme](https://commercial.abp.io/themes), which is a part of the [ABP Commercial](https://commercial.abp.io/).
> See the [Theming document](Theming.md) to learn about themes.
## Installation
**This theme is already installed** when you create a new solution using the [startup templates](../../Startup-Templates/Index.md). If you need to manually install it, follow the steps below:
* Install the [Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) NuGet package to your web project.
* Add `AbpAspNetCoreComponentsWebAssemblyBasicThemeModule` into the `[DependsOn(...)]` attribute for your [module class](../../Module-Development-Basics.md) in the your Blazor UI project.
* Use `Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic.App` as the root component of your application in the `ConfigureServices` method of your module:
````csharp
var builder = context.Services.GetSingletonInstance<WebAssemblyHostBuilder>();
builder.RootComponents.Add<App>("#ApplicationContainer");
````
`#ApplicationContainer` is a selector (like `<div id="ApplicationContainer">Loading...</div>`) in the `index.html`.
## The Layout
![basic-theme-application-layout](../../images/basic-theme-application-layout.png)
Application Layout implements the following parts, in addition to the common parts mentioned above;
* [Branding](Branding.md) Area
* Main [Menu](Navigation-Menu.md)
* Main [Toolbar](Toolbars.md) with Language Selection & User Menu
* [Page Alerts](Page-Alerts.md)
## Customization
You have two options two customize this theme:
### Overriding Styles / Components
In this approach, you continue to use the the theme as NuGet and NPM packages and customize the parts you need to. There are several ways to customize it;
#### Override the Styles
You can simply override the styles in the Global Styles file of your application.
#### Override the Components
See the [Customization / Overriding Components](Customization-Overriding-Components.md) to learn how you can replace components, customize and extend the user interface.
### Copy & Customize
You can download the [source code](https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) of the Basic Theme, copy the project content into your solution, re-arrange the package/module dependencies (see the Installation section above to understand how it was installed to the project) and freely customize the theme based on your application requirements.
## See Also
* [Theming](Theming.md)

37
docs/en/UI/Blazor/Branding.md

@ -0,0 +1,37 @@
# Blazor UI: Branding
## IBrandingProvider
`IBrandingProvider` is a simple interface that is used to show the application name and logo on the layout.
The screenshot below shows *MyProject* as the application name:
![branding-nobrand](../../images/branding-nobrand.png)
You can implement the `IBrandingProvider` interface or inherit from the `DefaultBrandingProvider` to set the application name:
````csharp
using Volo.Abp.DependencyInjection;
using Volo.Abp.Ui.Branding;
namespace MyCompanyName.MyProjectName.Blazor
{
[Dependency(ReplaceServices = true)]
public class MyProjectNameBrandingProvider : DefaultBrandingProvider
{
public override string AppName => "Book Store";
}
}
````
The result will be like shown below:
![branding-appname](../../images/branding-appname.png)
`IBrandingProvider` has the following properties:
* `AppName`: The application name.
* `LogoUrl`: A URL to show the application logo.
* `LogoReverseUrl`: A URL to show the application logo on a reverse color theme (dark, for example).
> **Tip**: `IBrandingProvider` is used in every page refresh. For a multi-tenant application, you can return a tenant specific application name to customize it per tenant.

85
docs/en/UI/Blazor/Customization-Overriding-Components.md

@ -1,3 +1,86 @@
# Blazor UI: Customization / Overriding Components
TODO
This document explains how to override the user interface of a depended [application module](../../Modules/Index.md) or [theme](Theming.md) for Blazor applications.
## Overriding a Razor Component
The ABP Framework, pre-built themes and modules define some **re-usable razor components and pages**. These pages and components can be replaced by your application or module.
> Since pages are just the razor components, the same principle is valid for pages too.
### Example: Replacing the Branding Area
The screenshot below was taken from the [Basic Theme](Basic-Theme.md) comes with the application startup template.
![bookstore-brand-area-highlighted](../../images/bookstore-brand-area-highlighted.png)
The [Basic Theme](Basic-Theme.md) defines some razor components for the layout. For example, the highlighted area with the red rectangle above is called *Branding* component. You probably want to customize this component by adding your **own application logo**. Let's see how to do it.
First, create your logo and place under a folder in your web application. We used `wwwroot/bookstore-logo.png` path:
![bookstore-logo-blazor](../../images/bookstore-logo-blazor.png)
The next step is to create a razor component, like `MyBlazor.razor`, in your application:
![bookstore-logo-blazor](../../images/bookstore-branding-blazor.png)
The content of the `MyBlazor.razor` is shown below:
````html
@using Volo.Abp.DependencyInjection
@using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic
@inherits Branding
@attribute [ExposeServices(typeof(Branding))]
@attribute [Dependency(ReplaceServices = true)]
<a href="/">
<img src="bookstore-logo.png" width="250" height="60"/>
</a>
````
Let's explain the code:
* `@inherits Branding` line inherits the Branding component defined by the [Basic Theme](Basic-Theme.md) (in the `Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic` namespace).
* `@attribute [ExposeServices(typeof(Branding))]` registers this service (component) to [dependency injection](../../Dependency-Injection.md) for the `Branding` service (component).
* `@attribute [Dependency(ReplaceServices = true)]` replaces the `Branding` class (component) with this new `MyBranding` class (component).
* The rest of the code is related the content and styling of the component.
Now, you can run the application to see the result:
![bookstore-added-logo](D:/Github/abp/docs/en/images/bookstore-added-logo.png)
> Since the component inherits from the component it is replacing, you can use all the non-private fields/properties/methods of the base component in the derived component.
### Example: Replacing with the Code Behind File
If you prefer to use code-behind file for the C# code of your component, you can use the attributes in the C# side.
**MyBlazor.razor**
````html
@using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic
@inherits Branding
<a href="/">
<img src="bookstore-logo.png" width="250" height="60"/>
</a>
````
**MyBlazor.razor.cs**
````csharp
using Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme.Themes.Basic;
using Volo.Abp.DependencyInjection;
namespace MyProject.Blazor.Components
{
[ExposeServices(typeof(Branding))]
[Dependency(ReplaceServices = true)]
public partial class MyBranding
{
}
}
````
## Theming
The [Theming](Theming.md) system allows you to build your own theme. You can create your theme from scratch or get the [Basic Theme](Basic-Theme.md) and change however you like.

37
docs/en/UI/Blazor/Global-Scripts-Styles.md

@ -1,3 +1,38 @@
# Blazor UI: Managing Global Scripts & Styles
TODO
Some modules may require additional styles or scripts that need to be referenced in **index.html** file. It's not easy to find and update these types of references in Blazor apps. ABP offers a simple, powerful, and modular way to manage global style and scripts in Blazor apps.
To update script & style references without worrying about dependencies, ordering, etc in a project, you can use the [bundle command](../../CLI.md#bundle).
You can also add custom styles and scripts and let ABP manage them for you. In your Blazor project, you can create a class implementing `IBundleContributer` interface.
`IBundleContributer` interface contains two methods.
* `AddScripts(...)`
* `AddStyles(...)`
Both methods get `BundleContext` as a parameter. You can add scripts and styles to the `BundleContext` and run [bundle command](../../CLI.md#bundle). Bundle command detects custom styles and scripts with module dependencies and updates `index.html` file.
## Example Usage
```csharp
namespace MyProject.Blazor
{
public class MyProjectBundleContributer : IBundleContributer
{
public void AddScripts(BundleContext context)
{
context.Add("site.js");
}
public void AddStyles(BundleContext context)
{
context.Add("main.css");
context.Add("custom-styles.css");
}
}
}
```
> There is a BundleContributer class implementing `IBundleContributer` interface coming by default with the startup templates. So, most of the time, you don't need to add it manually.
> Bundle command adds style and script references individually. Bundling and minification support will be added to incoming releases.

77
docs/en/UI/Blazor/Localization.md

@ -1,3 +1,78 @@
# Blazor UI: Localization
Blazor applications can reuse the same `IStringLocalizer<T>` service that is explained in the [localization document](../../Localization.md). All the localization resources and texts available in the server side are usable in the Blazor application.
Blazor applications can reuse the same `IStringLocalizer<T>` service that is explained in the [localization document](../../Localization.md).
All the localization resources and texts available in the server side are usable in the Blazor application.
## IStringLocalizer
`IStringLocalizer<T>` (`T` is the localization resource class) can be injected in any service or component to use the localization service.
### Razor Components
Use `@inject IStringLocalizer<MyProjectNameResource>` to use the localization in a razor component.
**Example: Localization in a Razor Component**
````csharp
@page "/"
@using MyCompanyName.MyProjectName.Localization
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<MyProjectNameResource> L
<h1>
@L["LongWelcomeMessage"]
</h1>
````
> `L` is a name that we love and use as the name of a `IStringLocalizer` instance, while you can give any name.
#### The AbpComponentBase
`AbpComponentBase` is a useful base class that you can derive the components from. It has some useful properties/methods you typically need in a component.
The `AbpComponentBase` already defines a base `L` property (of type `IStringLocalizer`). It only requires to set the resource type (in the constructor of the derived class). If you created your application from the ABP's application startup template, then you should have a *YourProjectComponentBase* class in the Blazor project. Inherit components from this class to have the localizer pre-injected.
**Example: Derive from the base component class**
````csharp
@page "/"
@inherits MyProjectNameComponentBase
<h1>
@L["LongWelcomeMessage"]
</h1>
````
### Other Services
`IStringLocalizer<T>` can be injected into any service.
**Example**
````csharp
public class MyService : ITransientDependency
{
private readonly IStringLocalizer<TestResource> _localizer;
public MyService(IStringLocalizer<TestResource> localizer)
{
_localizer = localizer;
}
public void Foo()
{
var str = _localizer["HelloWorld"];
}
}
````
### Format Arguments
Format arguments can be passed after the localization key. If your message is `Hello {0}, welcome!`, then you can pass the `{0}` argument to the localizer like `_localizer["HelloMessage", "John"]`.
> Refer to the [Microsoft's localization documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization) for details about using the localization.
## See Also
* [Localization](../../Localization.md)

130
docs/en/UI/Blazor/Message.md

@ -1,3 +1,129 @@
# Blazor: UI Message Service
# Blazor UI: Message Service
TODO
UI message service is used to show nice-looking messages to the user as a blocking dialog.
## Quick Example
Simply [inject](../../Dependency-Injection.md) `IUiMessageService` to your page or component and call the `Success` method to show a success message.
```csharp
namespace MyProject.Blazor.Pages
{
public partial class Index
{
private readonly IUiMessageService _uiMessageService;
public Index(IUiMessageService uiMessageService)
{
_uiMessageService = uiMessageService;
}
public async Task SaveAsync()
{
await _uiMessageService.Success(
"Your changes have been successfully saved!",
"Congratulations");
}
}
}
```
It will show a dialog on the UI:
![blazor-message-success](../../images/blazor-message-success.png)
If you inherit your page or component from the `AbpComponentBase` class, you can use the `Message` property to access the `IUiMessageService` as a pre-injected property.
```csharp
namespace MyProject.Blazor.Pages
{
public partial class Index : AbpComponentBase
{
public async Task SaveAsync()
{
await Message.Success(
"Your changes have been successfully saved!",
"Congratulations");
}
}
}
```
> You typically use `@inherits AbpComponentBase` in the `.razor` file to inherit from the `AbpComponentBase`, instead of inheriting in the code behind file.
## Informative Messages
There are four types of informative message functions:
* `Info(...)`
* `Success(...)`
* `Warn(...)`
* `Error(...)`
All of these methods get three parameters:
* `message`: The message (`string`) to be shown.
* `title`: An optional (`string`) title.
* `options`: An optional (`Action`) to configure UI message options.
**Example: Show an error message**
````csharp
_uiMessageService.Error('Your credit card number is not valid!');
````
![blazor-message-success](../../images/blazor-message-error.png)
## Confirmation Message
`IUiMessageService.Confirm(...)` method can be used to get a confirmation from the user.
**Example**
Use the following code to get a confirmation result from the user:
```csharp
public async Task DeleteAsync()
{
var confirmed = await _uiMessageService.Confirm("Are you sure to delete the 'admin' role?");
if(confirmed)
{
//Delete the 'admin' role here.
}
}
```
The resulting UI will be like shown below:
![blazor-message-confirm](../../images/blazor-message-confirm.png)
If the user has clicked the `Yes` button, the `Confirm` method's return value will be `true`.
## Configuration
It is easy to change default message options if you like to it per message. Provide an `action` to the `options` parameter as shown below.
```csharp
await _uiMessageService.Success(
"Your changes have been successfully saved!",
"Congratulations",
(options) =>
{
options.MessageIcon = "msg-icon-new";
options.CenterMessage = false;
});
```
List of the options that you can change by providing the `action` parameter.
* `CenterMessage` : (Default: true) If true, the message dialogue will be centered on the screen.
* `ShowMessageIcon` : (Default: true) If true, the message dialogue will show the large icon for the current message type.
* `MessageIcon` : Overrides the build-in message icon.
* `OkButtonText` : Custom text for the OK button.
* `OkButtonIcon` : Custom icon for the OK button.
* `ConfirmButtonText` : Custom text for the Confirmation button.
* `ConfirmButtonIcon` : Custom icon for the Confirmation button.
* `CancelButtonText` : Custom text for the Cancel button.
* `CancelButtonIcon` : Custom icon for the Cancel button.
> "Confirm", "Cancel" and "Yes" texts are automatically localized based on the current language.

206
docs/en/UI/Blazor/Navigation-Menu.md

@ -1,3 +1,207 @@
# Blazor UI: Navigation / Menu
TODO
Every application has a main menu to allow users to navigate to pages/screens of the application. Some applications may contain more than one menu in different sections of the UI.
ABP Framework is a [modular](../../Module-Development-Basics.md) application development framework. **Every module may need to add items to the menu**.
So, ABP Framework **provides a menu infrastructure** where;
* The application or the modules can add items to a menu, without knowing how the menu is rendered.
* The [theme](Theming.md) properly renders the menu.
## Adding Menu Items
In order to add menu items (or manipulate the existing items) you need to create a class implementing the `IMenuContributor` interface.
> The [application startup template](../../Startup-Templates/Application.md) already contains an implementation of the `IMenuContributor`. So, you can add items inside that class instead of creating a new one.
**Example: Add a *CRM* menu item with *Customers* and *Orders* sub menu items**
```csharp
using System.Threading.Tasks;
using MyProject.Localization;
using Volo.Abp.UI.Navigation;
namespace MyProject.Web.Menus
{
public class MyProjectMenuContributor : IMenuContributor
{
public async Task ConfigureMenuAsync(MenuConfigurationContext context)
{
if (context.Menu.Name == StandardMenus.Main)
{
await ConfigureMainMenuAsync(context);
}
}
private async Task ConfigureMainMenuAsync(MenuConfigurationContext context)
{
var l = context.GetLocalizer<MyProjectResource>();
context.Menu.AddItem(
new ApplicationMenuItem("MyProject.Crm", l["Menu:CRM"])
.AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Customers",
displayName: l["Menu:Customers"],
url: "/crm/customers")
).AddItem(new ApplicationMenuItem(
name: "MyProject.Crm.Orders",
displayName: l["Menu:Orders"],
url: "/crm/orders")
)
);
}
}
}
```
* This example adds items only to the main menu (`StandardMenus.Main`: see the *Standard Menus* section below).
* It gets a `IStringLocalizer` from `context` to [localize](../../Localization.md) the display names of the menu items.
* Adds the Customers and Orders as children of the CRM menu.
Once you create a menu contributor, you need to add it to the `AbpNavigationOptions` in the `ConfigureServices` method of your module:
````csharp
Configure<AbpNavigationOptions>(options =>
{
options.MenuContributors.Add(new MyProjectMenuContributor());
});
````
This example uses some localization keys as display names those should be defined in the localization file:
````json
"Menu:CRM": "CRM",
"Menu:Orders": "Orders",
"Menu:Customers": "Customers"
````
See the [localization document](../../Localization.md) to learn more about the localization.
When you run the application, you will see the menu items added to the main menu:
![nav-main-menu](../../images/nav-main-menu.png)
> The menu is rendered by the current UI [theme](Theming.md). So, the look of the main menu can be completely different based on your theme.
Here, a few notes on the menu contributors;
* ABP Framework calls the `ConfigureMenuAsync` method **whenever need to render** the menu.
* Every menu item can have **children**. So, you can add menu items with **unlimited depth** (however, your UI theme may not support unlimited depth).
* Only leaf menu items have `url`s normally. When you click to a parent menu, its sub menu is opened or closed, you don't navigate the `url` of a parent menu item.
* If a menu item has no children and has no `url` defined, then it is not rendered on the UI. This simplifies to authorize the menu items: You only authorize the child items (see the next section). If none of the children are authorized, then the parent automatically disappears.
### Menu Item Properties
There are more options of a menu item (the constructor of the `ApplicationMenuItem` class). Here, the list of all available options;
* `name` (`string`, required): The **unique name** of the menu item.
* `displayName` (`string`, required): Display name/text of the menu item. You can [localize](../../Localization.md) this as shown before.
* `url` (`string`): The URL of the menu item.
* `icon` (`string`): An icon name. Free [Font Awesome](https://fontawesome.com/) icon classes are supported out of the box. Example: `fa fa-book`. You can use any CSS font icon class as long as you include the necessary CSS files to your application.
* `order` (`int`): The order of the menu item. Default value is `1000`. Items are sorted by the adding order unless you specify an order value.
* `customData` (`object`): A custom object that you can associate to the menu item and use it while rendering the menu item.
* `target` (`string`): Target of the menu item. Can be `null` (default), "\_*blank*", "\_*self*", "\_*parent*", "\_*top*" or a frame name for web applications.
* `elementId` (`string`): Can be used to render the element with a specific HTML `id` attribute.
* `cssClass` (`string`): Additional string classes for the menu item.
### Authorization
As seen above, a menu contributor contributes to the menu dynamically. So, you can perform any custom logic or get menu items from any source.
One use case is the [authorization](Authorization.md). You typically want to add menu items by checking a permission.
**Example: Check if the current user has a permission**
````csharp
if (await context.IsGrantedAsync("MyPermissionName"))
{
//...add menu items
}
````
> You can use `context.AuthorizationService` to directly access to the `IAuthorizationService`.
### Resolving Dependencies
`context.ServiceProvider` can be used to resolve any service dependency.
**Example: Get a service**
````csharp
var myService = context.ServiceProvider.GetRequiredService<IMyService>();
//...use the service
````
> You don't need to care about releasing/disposing services. ABP Framework handles it.
### The Administration Menu
There is a special menu item in the menu menu that is added by the ABP Framework: The *Administration* menu. It is typically used by the pre-built admin [application modules](../../Modules/Index.md):
![nav-main-menu-administration](../../images/nav-main-menu-administration.png)
If you want to add menu items under the *Administration* menu item, you can use the `context.Menu.GetAdministration()` extension method:
````csharp
context.Menu.GetAdministration().AddItem(...)
````
### Manipulating the Existing Menu Items
ABP Framework executes the menu contributors by the [module dependency order](../../Module-Development-Basics.md). So, you can manipulate the menu items that your application or module (directly or indirectly) depends on.
**Example: Set an icon for the `Users` menu item added by the [Identity Module](../../Modules/Identity.md)**
````csharp
var userMenu = context.Menu.FindMenuItem(IdentityMenuNames.Users);
userMenu.Icon = "fa fa-users";
````
> `context.Menu` gives you ability to access to all the menu items those have been added by the previous menu contributors.
## Standard Menus
A menu is a **named** component. An application may contain more than one menus with different, unique names. There are two pre-defined standard menus:
* `Main`: The main menu of the application. Contains links to the page of the application. Defined as a constant: `Volo.Abp.UI.Navigation.StandardMenus.Main`.
* `User`: User profile menu. Defined as a constant: `Volo.Abp.UI.Navigation.StandardMenus.User`.
The `Main` menu already covered above. The `User` menu is available when a user has logged in:
![user-menu](../../images/user-menu.png)
You can add items to the `User` menu by checking the `context.Menu.Name` as shown below:
```csharp
if (context.Menu.Name == StandardMenus.User)
{
//...add items
}
```
## IMenuManager
`IMenuManager` is generally used by the UI [theme](Theming.md) to render the menu items on the UI. So, **you generally don't need to directly use** the `IMenuManager`.
**Example: Get the Main Menu to render in a razor component**
```csharp
// Code behind file of a razor component
public partial class NavMenu
{
private readonly IMenuManager _menuManager;
public NavMenu(IMenuManager menuManager)
{
_menuManager = menuManager;
}
protected override async Task OnInitializedAsync()
{
var menu = await _menuManager.GetAsync(StandardMenus.Main);
//...
}
}
```

102
docs/en/UI/Blazor/Notification.md

@ -1,3 +1,103 @@
# Blazor UI: Notification Service
`IUiNotificationService` is used to show toastr style notifications on the user interface. The documentation is in progress...
`IUiNotificationService` is used to show toast style notifications on the user interface.
## Quick Example
Simply [inject](../../Dependency-Injection.md) `IUiNotificationService` to your page or component and call the `Success` method to show a success message.
```csharp
namespace MyProject.Blazor.Pages
{
public partial class Index
{
private readonly IUiNotificationService _uiNotificationService;
public Index(IUiNotificationService uiNotificationService)
{
_uiNotificationService = uiNotificationService;
}
public async Task DeleteAsync()
{
await _uiNotificationService.Success(
"The product 'Acme Atom Re-Arranger' has been successfully deleted."
);
}
}
}
```
![blazor-notification-sucess](../../images/blazor-notification-success.png)
If you inherit your page or component from the `AbpComponentBase` class, you can use the the `Notify` property to access the `IUiNotificationService` as a pre-injected property.
```csharp
namespace MyProject.Blazor.Pages
{
public partial class Index : AbpComponentBase
{
public async Task DeleteAsync()
{
await Notify.Success(
"The product 'Acme Atom Re-Arranger' has been successfully deleted."
);
}
}
}
```
> You typically use `@inherits AbpComponentBase` in the `.razor` file to inherit from the `AbpComponentBase`, instead of inheriting in the code behind file.
## Notification Types
There are four types of pre-defined notifications;
* `Info(...)`
* `Success(...)`
* `Warn(...)`
* `Error(...)`
All of the methods above gets the following parameters;
* `message`: The message (`string`) to be shown.
* `title`: An optional (`string`) title.
* `options`: An optional (`Action`) to configure notification options.
## Configuration
### Per Notification
It is easy to change default notification options if you like to customize it per notification. Provide an action to the `options` parameter as shown below:
```csharp
await UiNotificationService.Success(
"The product 'Acme Atom Re-Arranger' has been successfully deleted.",
options: (options) =>
{
options.OkButtonText =
LocalizableString.Create<MyProjectNameResource>("CustomOK");
});
```
### Available Options
Here, the list of all available options;
* `OkButtonText` : Custom text for the OK button.
* `OkButtonIcon` : Custom icon for the OK button
### Global Configuration
You can also configure global notification options to control the it in a single point. Configure the `UiNotificationOptions` [options class](../../Options.md) in the `ConfigureServices` of your [module](../../Module-Development-Basics.md):
````csharp
Configure<UiNotificationOptions>(options =>
{
options.OkButtonText = LocalizableString.Create<MyProjectNameResource>("CustomOK");
});
````
The same options are available here.
> *Per notification* configuration overrides the default values.

126
docs/en/UI/Blazor/Overall.md

@ -1,8 +1,126 @@
# Blazor UI: Overall
## Getting Started
## Introduction
You can follow the documents below to start with the ABP Framework and the Blazor UI:
[Blazor](https://docs.microsoft.com/en-us/aspnet/core/blazor/) is a framework for building interactive client-side web UI with .NET. It is promising for a .NET developer that you can create Single-Page Web Applications using C# and the Razor syntax.
* [Get started](https://docs.abp.io/en/abp/latest/Getting-Started?UI=Blazor) with the Blazor UI for the ABP Framework.
* [Web Application Development Tutorial](https://docs.abp.io/en/abp/latest/Tutorials/Part-1?UI=Blazor) with the Blazor UI.
ABP provides infrastructure and integrations that make your Blazor development even easier, comfortable and enjoyable.
This document provides an overview for the ABP Framework Blazor UI integration and highlights some major features.
### Getting Started
You can follow the documents below to start with the ABP Framework and the Blazor UI now:
* [Get started](../../Getting-Started.md) with the Blazor UI for the ABP Framework.
* [Web Application Development Tutorial](../../Tutorials/Part-1.md) with the Blazor UI.
## Modularity
[Modularity](../../Module-Development-Basics.md) is one of the key goals of the ABP Framework. It is not different for the UI; It is possible to develop modular applications and reusable application modules with isolated and reusable UI pages and components.
The [application startup template](../../Startup-Templates/Application.md) comes with some application modules pre-installed. These modules have their own UI pages embedded into their own NuGet packages. You don't see their code in your solution, but they work as expected on runtime.
## Dynamic C# Client Proxies
Dynamic C# Client Proxy system makes extremely easy to consume server side HTTP APIs from the UI. You just **inject** the [application service](../../Application-Services.md) **interface** and consume the remote APIs just like using local service method calls.
**Example: Get list of books from server and list on the UI**
````csharp
@page "/books"
@using Acme.BookStore.Books
@using Volo.Abp.Application.Dtos
@inject IBookAppService BookAppService
<ul>
@foreach (var book in Books)
{
<li>
@book.Name (by @book.AuthorName)
</li>
}
</ul>
@code {
private IReadOnlyList<BookDto> Books { get; set; } = new List<BookDto>();
protected override async Task OnInitializedAsync()
{
var result = await BookAppService.GetListAsync(
new PagedAndSortedResultRequestDto()
);
Books = result.Items;
}
}
````
* This razor component (page) uses `@inject IBookAppService BookAppService` to get a reference to the service proxy.
* It uses `BookAppService.GetListAsync` in the `OnInitializedAsync` and gets the list of the books, just like a regular C# method call.
* Finally, the page renders the books in a list on the UI.
ABP Framework handles all the low level details for you, including a proper HTTP call, JSON serialization, exception handling and authentication.
See the [Dynamic C# Client Proxies](../../API/Dynamic-CSharp-API-Clients.md) document for more.
## Theming System
ABP Framework provides a complete [Theming](Theming.md) system with the following goals:
* Reusable [application modules](../../Modules/Index.md) are developed **theme-independent**, so they can work with any UI theme.
* UI theme is **decided by the final application**.
* The theme is distributed as NuGet package, so it is **easily upgradable**.
* The final application can **customize** the selected theme.
### Current Themes
Currently, two themes are **officially provided**:
* The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**.
* The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license.
### Base Libraries
There are a set of standard libraries that comes pre-installed and supported by all the themes:
* [Twitter Bootstrap](https://getbootstrap.com/) as the fundamental HTML/CSS framework.
* [Blazorise](https://github.com/stsrki/Blazorise) as a component library that supports the Bootstrap and adds extra components like Data Grid and Tree.
* [FontAwesome](https://fontawesome.com/) as the fundamental CSS font library.
* [Flag Icon](https://github.com/lipis/flag-icon-css) as a library to show flags of countries.
These libraries are selected as the base libraries and available to the applications and modules.
> Bootstrap's JavaScript part is not used since the Blazorise library already provides the necessary functionalities to the Bootstrap components in a native way.
### The Layout
The themes provide the layout. So, you have a responsive layout with the standard features already implemented. The screenshot below has taken from the layout of the [Basic Theme](Basic-Theme.md):
![basic-theme-application-layout](D:/Github/abp/docs/en/images/basic-theme-application-layout.png)
See the [Theming](Theming.md) document for more layout options and other details.
### Layout Parts
A typical layout consists of multiple parts. The [Theming](Theming.md) system provides [menus](Navigation-Menu.md), [toolbars](Toolbars.md), [page alerts](Page-Alerts.md) and more to dynamically control the layout by your application and the modules you are using.
## Global Styles & Scripts / Bundling & Minification
ABP provides a standard way to manage the global script and style dependencies of an application. This is an essential feature for modularity since some modules may have such dependencies and they can declare dependencies in that way.
See the [Managing Global Scripts & Styles](Global-Scripts-Styles.md) document.
## Services
ABP provides useful services that you can consume in your applications. Some of them are;
* [IUiMessageService](Message.md) is used to show modal messages to the user.
* [IUiNotificationService](Notification.md) is used to show toast-style notifications.
* [IAlertManager](Page-Alerts.md) is used to show in-page alerts.
* [ISettingProvider](Settings.md) is used to access to the current setting values.
* `ICurrentUser` and `ICurrentTenant` is used to get information about the current user and the tenant.
## Customization
While the theme and some modules come as NuGet packages, you can still override and customize them on need. See the [Customization / Overriding Components](Customization-Overriding-Components.md) document.

62
docs/en/UI/Blazor/Page-Alerts.md

@ -0,0 +1,62 @@
# Blazor UI: Page Alerts
It is common to show error, warning or information alerts to inform the user. An example *Service Interruption* alert is shown below:
![blazor-page-alert-example](../../images/blazor-page-alert-example.png)
## Quick Example
Simply [inject](../../Dependency-Injection.md) `IAlertManager` to your page or component and call the `Alerts.Warning` method to show a success message.
```csharp
namespace MyProject.Blazor.Pages
{
public partial class Index
{
private readonly IAlertManager _alertManager;
public Index(IAlertManager alertManager)
{
this._alertManager = alertManager;
}
protected override void OnInitialized()
{
_alertManager.Alerts.Warning(
"We will have a service interruption between 02:00 AM and 04:00 AM at October 23, 2023!",
"Service Interruption");
base.OnInitialized();
}
}
}
```
If you inherit your page or component from the `AbpComponentBase` class, you can use the `Alerts` property to add alerts.
```csharp
namespace MyProject.Blazor.Pages
{
public partial class Index : AbpComponentBase
{
protected override void OnInitialized()
{
Alerts.Warning(
"We will have a service interruption between 02:00 AM and 04:00 AM at October 23, 2023!",
"Service Interruption");
base.OnInitialized();
}
}
}
```
> You typically use `@inherits AbpComponentBase` in the `.razor` file to inherit from the `AbpComponentBase`, instead of inheriting in the code behind file.
### Alert Types
`Warning` is used to show a warning alert. Other common methods are `Info`, `Danger` and `Success`.
Beside the standard methods, you can use the `Alerts.Add` method by passing an `AlertType` `enum` with one of these values: `Default`, `Primary`, `Secondary`, `Success`, `Danger`, `Warning`, `Info`, `Light`, `Dark`.
### Dismissible
All alert methods gets an optional `dismissible` parameter. Default value is `true` which makes the alert box dismissible. Set it to `false` to create a sticky alert box.

62
docs/en/UI/Blazor/Settings.md

@ -1,3 +1,63 @@
# Blazor UI: Settings
Blazor applications can reuse the same `ISettingProvider` service that is explained in the [settings document](../../Settings.md).
Blazor applications can reuse the same `ISettingProvider` service that is explained in the [settings document](../../Settings.md).
## ISettingProvider
`ISettingProvider` is used to get the value of a setting or get the values of all the settings.
**Example usages in a simple service**
````csharp
public class MyService : ITransientDependency
{
private readonly ISettingProvider _settingProvider;
//Inject ISettingProvider in the constructor
public MyService(ISettingProvider settingProvider)
{
_settingProvider = settingProvider;
}
public async Task FooAsync()
{
//Get a value as string.
string setting1 = await _settingProvider.GetOrNullAsync("MySettingName");
//Get a bool value and fallback to the default value (false) if not set.
bool setting2 = await _settingProvider.GetAsync<bool>("MyBoolSettingName");
//Get a bool value and fallback to the provided default value (true) if not set.
bool setting3 = await _settingProvider.GetAsync<bool>(
"MyBoolSettingName", defaultValue: true);
//Get a bool value with the IsTrueAsync shortcut extension method
bool setting4 = await _settingProvider.IsTrueAsync("MyBoolSettingName");
//Get an int value or the default value (0) if not set
int setting5 = (await _settingProvider.GetAsync<int>("MyIntegerSettingName"));
//Get an int value or null if not provided
int? setting6 = (await _settingProvider
.GetOrNullAsync("MyIntegerSettingName"))?.To<int>();
}
}
````
**Example usage in a Razor Component**
````csharp
@page "/"
@using Volo.Abp.Settings
@inject ISettingProvider SettingProvider
@code {
protected override async Task OnInitializedAsync()
{
bool settingValue = await SettingProvider.GetAsync<bool>("MyBoolSettingName");
}
}
````
## See Also
* [Settings](../../Settings.md)

206
docs/en/UI/Blazor/Theming.md

@ -1,3 +1,207 @@
# Blazor UI: Theming
TODO
## Introduction
ABP Framework provides a complete **UI Theming** system with the following goals:
* Reusable [application modules](../../Modules/Index.md) are developed **theme-independent**, so they can work with any UI theme.
* UI theme is **decided by the final application**.
* The theme is distributed via a NuGet package, so it is **easily upgradable**.
* The final application can **customize** the selected theme.
In order to accomplish these goals, ABP Framework;
* Determines a set of **base libraries** used and adapted by all the themes. So, module and application developers can depend on and use these libraries without depending on a particular theme.
* Provides a system that consists of layout parts (like [navigation menus](Navigation-Menu.md) and [toolbars](Toolbars.md)) that is implemented by all the themes. So, the modules and the application to contribute to the layout to compose a consistent application UI.
### Current Themes
Currently, two themes are **officially provided**:
* The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**.
* The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license.
## Overall
### The Base Libraries
All the themes must depend on the [Volo.Abp.AspNetCore.Components.WebAssembly.Theming](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Components.WebAssembly.Theming) NuGet package, so they are indirectly depending on the following libraries:
* [Twitter Bootstrap](https://getbootstrap.com/) as the fundamental HTML/CSS framework.
* [Blazorise](https://github.com/stsrki/Blazorise) as a component library that supports the Bootstrap and adds extra components like Data Grid and Tree.
* [FontAwesome](https://fontawesome.com/) as the fundamental CSS font library.
* [Flag Icon](https://github.com/lipis/flag-icon-css) as a library to show flags of countries.
These libraries are selected as the base libraries and available to the applications and modules.
> Bootstrap's JavaScript part is not used since the Blazorise library already provides the necessary functionalities to the Bootstrap components in a native way.
### The Layout
All themes must define a layout for the application. The following image shows the user management page in the [Basic Theme](Basic-Theme.md) application layout:
![basic-theme-application-layout-blazor](../../images/basic-theme-application-layout-blazor.png)
And the same page is shown below with the [Lepton Theme](https://commercial.abp.io/themes) application layout:
![lepton-theme-application-layout](../../images/lepton-theme-application-layout.png)
As you can see, the page is the same, but the look is completely different in the themes above.
The application layout typically includes the following parts;
* A [main menu](Navigation-Menu.md)
* Main [Toolbar](Toolbars.md) with the following components;
* User menu
* Language switch dropdown
* [Page alerts](Page-Alerts.md)
* The page content (aka `@Body`)
## Implementing a Theme
A theme is simply a Razor Class Library.
### The Easy Way
The easiest way to create a new theme is to copy the [Basic Theme Source Code](https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme) and customize it. Once you get a copy of the theme in your solution, remove the `Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic` NuGet package and reference to the local project.
### Global Styles / Scripts
A theme generally needs to add a global style to the page. ABP provides a system to manage the [Global Styles and Scripts](Global-Scripts-Styles.md). A theme can implement the `IBundleContributer` to add global style or script files to the page.
**Example: Adding a style to the page**
````csharp
using Volo.Abp.Bundling;
namespace MyTheme
{
public class MyThemeBundleContributer : IBundleContributer
{
public void AddScripts(BundleContext context)
{
}
public void AddStyles(BundleContext context)
{
context.Add("_content/MyTheme/styles.css");
}
}
}
````
`styles.css` file should be added into the `wwwroot` folder of the theme project for this example. When you use the `abp bundle` command, this class is automatically discovered and executed to add the style to the page.
See the [Global Styles and Scripts](Global-Scripts-Styles.md) document for more.
### Layout Parts
A typical Layout consists of several parts. The theme should include the necessary parts in each layout.
**Example: The Basic Theme has the following parts for the Application Layout**
![basic-theme-application-layout-parts](../../images/basic-theme-application-layout-parts.png)
The application code and the modules can only show contents in the Page Content part. If they need to change the other parts (to add a menu item, to add a toolbar item, to change the application name in the branding area...) they should use the ABP Framework APIs.
The following sections explain the fundamental parts pre-defined by the ABP Framework and can be implemented by the themes.
> It is a good practice to split the layout into components/partials, so the final application can override them partially for customization purpose.
#### Branding
`IBrandingProvider` service should be used to get the name and the logo URL of the application to render in the Branding part.
The [Application Startup Template](../../Startup-Templates/Application.md) has an implementation of this interface to set the values by the application developer.
#### Main Menu
`IMenuManager` service is used to get the main menu items and render on the layout.
**Example: Get the Main Menu to render in a razor component**
```csharp
// Code behind file of a razor component
public partial class NavMenu
{
private readonly IMenuManager _menuManager;
public NavMenu(IMenuManager menuManager)
{
_menuManager = menuManager;
}
protected override async Task OnInitializedAsync()
{
var menu = await _menuManager.GetAsync(StandardMenus.Main);
//...
}
}
```
See the [Navigation / Menus](Navigation-Menu.md) document to learn more about the navigation system.
#### Main Toolbar
`IToolbarManager` service is used to get the Main Toolbar items and render on the layout. Each item of this toolbar is a Razor Component, so it may include any type of UI elements. Inject the `IToolbarManager` and use the `GetAsync` to get the toolbar items:
````csharp
var toolbar = await _toolbarManager.GetAsync(StandardToolbars.Main);
````
> See the [Toolbars](Toolbars.md) document to learn more on the toolbar system.
The theme has a responsibility to add two pre-defined items to the main toolbar: Language Selection and User Menu. To do that, create a class implementing the `IToolbarContributor` interface and add it to the `AbpToolbarOptions` as shown below:
```csharp
Configure<AbpToolbarOptions>(options =>
{
options.Contributors.Add(new BasicThemeMainTopToolbarContributor());
});
```
##### Language Selection
Language Selection toolbar item is generally a dropdown that is used to switch between languages. `ILanguageProvider` is used to get the list of available languages and `CultureInfo.CurrentUICulture` is used to learn the current language.
Local Storage is used to get and set the current language with the `Abp.SelectedLanguage` key.
**Example: Get the currently selected language**
````csharp
var selectedLanguageName = await JsRuntime.InvokeAsync<string>(
"localStorage.getItem",
"Abp.SelectedLanguage"
);
````
**Example: Set the selected language**
````csharp
await JsRuntime.InvokeVoidAsync(
"localStorage.setItem",
"Abp.SelectedLanguage",
"en-US"
);
````
The theme should reload the page after changing the language:
````csharp
await JsRuntime.InvokeVoidAsync("location.reload");
````
##### User Menu
User menu includes links related to the user account. `IMenuManager` is used just like the Main Menu, but this time with `StandardMenus.User` parameter like shown below:
````csharp
var menu = await _menuManager.GetAsync(StandardMenus.User);
````
[ICurrentUser](../../CurrentUser.md) and [ICurrentTenant](../../Multi-Tenancy.md) services can be used to obtain the current user and tenant names.
#### Page Alerts
`IAlertManager` service is used to get the current page alerts to render on the layout. See the [Page Alerts](Page-Alerts.md) document to learn more.

74
docs/en/UI/Blazor/Toolbars.md

@ -1,3 +1,75 @@
# Blazor UI: Toolbars
TODO
The Toolbar system is used to define **toolbars** on the user interface. Modules (or your application) can add **items** to a toolbar, then the [theme](Theming.md) renders the toolbar on the **layout**.
There is only one **standard toolbar** named "Main" (defined as a constant: `StandardToolbars.Main`). The [Basic Theme](Basic-Theme) renders the main toolbar as shown below:
![bookstore-toolbar-highlighted](../../images/bookstore-toolbar-highlighted.png)
In the screenshot above, there are two items added to the main toolbar: Language switch component & user menu. You can add your own items here.
## Example: Add a Notification Icon
In this example, we will add a **notification (bell) icon** to the left of the language switch item. A item in the toolbar should be a **Razor Component**. So, first, create a new razor component in your project (the location of the component doesn't matter):
![bookstore-notification-view-component](../../images/blazor-notification-bell-component.png)
The content of the `Notification.razor` is shown below:
````html
@inherits Volo.Abp.AspNetCore.Components.AbpComponentBase
<div style="color: white; margin: 8px;">
<i class="far fa-bell" @onclick="ShowNotifications"></i>
</div>
@code {
private async Task ShowNotifications()
{
await Message.Info("TODO: Show notifications");
}
}
````
This sample simply shows a message. In real life, you probably want to call an HTTP API to get notifications and show on the UI.
Now, we can create a class implementing the `IToolbarContributor` interface:
````csharp
using System.Threading.Tasks;
using MyCompanyName.MyProjectName.Blazor.Components;
using Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Toolbars;
namespace MyCompanyName.MyProjectName.Blazor
{
public class MyToolbarContributor : IToolbarContributor
{
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
{
if (context.Toolbar.Name == StandardToolbars.Main)
{
context.Toolbar.Items.Insert(0, new ToolbarItem(typeof(Notification)));
}
return Task.CompletedTask;
}
}
}
````
This class adds the `NotificationViewComponent` as the first item in the `Main` toolbar.
Finally, you need to add this contributor to the `AbpToolbarOptions`, in the `ConfigureServices` of your [module](../../Module-Development-Basics.md):
````csharp
Configure<AbpToolbarOptions>(options =>
{
options.Contributors.Add(new MyToolbarContributor());
});
````
That's all, you will see the notification icon on the toolbar when you run the application:
![bookstore-notification-icon-on-toolbar](../../images/bookstore-notification-icon-on-toolbar.png)
## IToolbarManager
`IToolbarManager` is used to render the toolbar. It returns the toolbar items by a toolbar name. This is generally used by the [themes](Theming.md) to render the toolbar on the layout.

16
docs/en/docs-nav.json

@ -588,12 +588,26 @@
},
{
"text": "Theming",
"path": "UI/Blazor/Theming.md"
"path": "UI/Blazor/Theming.md",
"items": [
{
"text": "The Basic Theme",
"path": "UI/Blazor/Basic-Theme.md"
}
]
},
{
"text": "Toolbars",
"path": "UI/Blazor/Toolbars.md"
},
{
"text": "Page Alerts",
"path": "UI/Blazor/Page-Alerts.md"
},
{
"text": "Branding",
"path": "UI/Blazor/Branding.md"
},
{
"text": "Customization / Overriding Components",
"path": "UI/Blazor/Customization-Overriding-Components.md"

BIN
docs/en/images/basic-theme-application-layout-blazor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
docs/en/images/blazor-message-confirm.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/images/blazor-message-error.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
docs/en/images/blazor-message-success.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
docs/en/images/blazor-notification-bell-component.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
docs/en/images/blazor-notification-success.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
docs/en/images/blazor-page-alert-example.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/en/images/bookstore-branding-blazor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/en/images/bookstore-logo-blazor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

3
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/Branding.razor

@ -0,0 +1,3 @@
@using Volo.Abp.Ui.Branding
@inject IBrandingProvider BrandingProvider
<a class="navbar-brand" href="/">@BrandingProvider.AppName</a>

4
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/MainLayout.razor

@ -1,9 +1,7 @@
@inherits LayoutComponentBase
@using Volo.Abp.Ui.Branding
@inject IBrandingProvider BrandingProvider
<nav class="navbar navbar-expand-md navbar-dark bg-dark shadow-sm flex-column flex-md-row mb-4" id="main-navbar" style="min-height: 4rem;">
<div class="container">
<a class="navbar-brand" href="/">@BrandingProvider.AppName</a>
<Branding />
<button @onclick="ToggleCollapse" class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#main-navbar-collapse" aria-controls="main-navbar-collapse"
aria-expanded="false" aria-label="Toggle navigation">

3
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Alerts/AlertManager.cs

@ -1,4 +1,5 @@
using Volo.Abp.DependencyInjection;
using Volo.Abp.AspNetCore.Components.Alerts;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Alerts
{

7
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Alerts/IAlertManager.cs

@ -1,7 +0,0 @@
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Alerts
{
public interface IAlertManager
{
AlertList Alerts { get; }
}
}

6
framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/AbpComponentBase.cs

@ -5,6 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.Components.Alerts;
using Volo.Abp.AspNetCore.Components.Messages;
using Volo.Abp.AspNetCore.Components.Notifications;
using Volo.Abp.Localization;
@ -61,6 +62,11 @@ namespace Volo.Abp.AspNetCore.Components
protected IUiNotificationService Notify => LazyGetNonScopedRequiredService(ref _notify);
private IUiNotificationService _notify;
protected IAlertManager AlertManager => LazyGetNonScopedRequiredService(ref _alertManager);
private IAlertManager _alertManager;
protected AlertList Alerts => AlertManager.Alerts;
protected IObjectMapper ObjectMapper
{
get

11
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Alerts/AlertList.cs → framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertList.cs

@ -1,6 +1,11 @@
using System.Collections.ObjectModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Alerts
namespace Volo.Abp.AspNetCore.Components.Alerts
{
public class AlertList : ObservableCollection<AlertMessage>
{
@ -29,4 +34,4 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.Alerts
Add(new AlertMessage(AlertType.Success, text, title, dismissible));
}
}
}
}

4
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Alerts/AlertMessage.cs → framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertMessage.cs

@ -1,6 +1,6 @@
using JetBrains.Annotations;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Alerts
namespace Volo.Abp.AspNetCore.Components.Alerts
{
public class AlertMessage
{
@ -27,4 +27,4 @@ namespace Volo.Abp.AspNetCore.Components.WebAssembly.Alerts
Dismissible = dismissible;
}
}
}
}

10
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/Alerts/AlertType.cs → framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/AlertType.cs

@ -1,4 +1,10 @@
namespace Volo.Abp.AspNetCore.Components.WebAssembly.Alerts
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Alerts
{
public enum AlertType
{
@ -12,4 +18,4 @@
Light,
Dark
}
}
}

13
framework/src/Volo.Abp.AspNetCore.Components/Volo/Abp/AspNetCore/Components/Alerts/IAlertManager.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Components.Alerts
{
public interface IAlertManager
{
AlertList Alerts { get; }
}
}

4
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs

@ -31,6 +31,10 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
public string AutocompleteFilterParamName { get; set; }
public string AutocompleteSelectedItemName { get; set; }
public string AutocompleteSelectedItemValue { get; set; }
public AbpSelectTagHelper(AbpSelectTagHelperService tagHelperService)
: base(tagHelperService)
{

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Diagnostics;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
@ -85,6 +86,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
selectTagHelper.Items = GetSelectItems(context, output);
}
else
{
selectTagHelper.Items = new SelectListItem[]
{
new SelectListItem(TagHelper.AutocompleteSelectedItemName,TagHelper.AutocompleteSelectedItemValue,true)
};
}
var selectTagHelperOutput = await selectTagHelper.ProcessAndGetOutputAsync(GetInputAttributes(context, output), context, "select", TagMode.StartTagAndEndTag);
@ -107,6 +115,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
output.Attributes.Add("data-autocomplete-display-property", TagHelper.AutocompleteDisplayPropertyName);
output.Attributes.Add("data-autocomplete-value-property", TagHelper.AutocompleteValuePropertyName);
output.Attributes.Add("data-autocomplete-filter-param-name", TagHelper.AutocompleteFilterParamName);
output.Attributes.Add("data-autocomplete-selected-item-name", TagHelper.AutocompleteSelectedItemName);
output.Attributes.Add("data-autocomplete-selected-item-value", TagHelper.AutocompleteSelectedItemValue);
}
}

15
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/dom-event-handlers.js

@ -80,6 +80,18 @@
var displayValue = $(this).data("autocompleteValueProperty");
var itemsPropertyName = $(this).data("autocompleteItemsProperty");
var filterParamName = $(this).data("autocompleteFilterParamName");
var selectedText = $(this).data("autocompleteSelectedItemName");
var name = $(this).attr("name");
var selectedTextInputName = name.substring(0, name.length - 1) + "_Text]";
var selectedTextInput = $('<input>', {
type: 'hidden',
id: selectedTextInputName,
name: selectedTextInputName,
});
if (selectedText != "") {
selectedTextInput.val(selectedText);
}
selectedTextInput.insertAfter($select);
$select.select2({
ajax: {
url: url,
@ -109,6 +121,9 @@
},
width: '100%'
});
$select.on('select2:select', function (e) {
selectedTextInput.val(e.params.data.text);
});
});
}
}

3
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ApplicationConfigurations/ObjectExtending/CachedObjectExtensionsDtoService.cs

@ -140,8 +140,7 @@ namespace Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending
},
OnTable = new ExtensionPropertyUiTableDto
{
IsVisible = propertyConfig.UI.OnTable.IsVisible &&
propertyConfig.UI.Lookup.Url.IsNullOrEmpty()
IsVisible = propertyConfig.UI.OnTable.IsVisible
},
Lookup = new ExtensionPropertyUiLookupDto
{

2
framework/src/Volo.Abp.BlazoriseUI/Components/AlertWrapper.cs

@ -1,4 +1,4 @@
using Volo.Abp.AspNetCore.Components.WebAssembly.Alerts;
using Volo.Abp.AspNetCore.Components.Alerts;
namespace Volo.Abp.BlazoriseUI.Components
{

4
framework/src/Volo.Abp.BlazoriseUI/Components/PageAlert.razor.cs

@ -5,7 +5,7 @@ using System.Linq;
using Blazorise;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Volo.Abp.AspNetCore.Components.WebAssembly.Alerts;
using Volo.Abp.AspNetCore.Components.Alerts;
namespace Volo.Abp.BlazoriseUI.Components
{
@ -47,7 +47,7 @@ namespace Volo.Abp.BlazoriseUI.Components
{
Alerts.Add(new AlertWrapper
{
AlertMessage = (AspNetCore.Components.WebAssembly.Alerts.AlertMessage)item,
AlertMessage = (AspNetCore.Components.Alerts.AlertMessage)item,
IsVisible = true
});
}

2
framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/es.json

@ -1,6 +1,6 @@
{
"culture": "es",
"texts": {
"MaxResultCountExceededExceptionMessage": "{0} no puede tener más de {1}! Incremente {2}.{3} en el lado del servidor para obtener más resultados."
"MaxResultCountExceededExceptionMessage": "{0} no puede ser más de {1}! Aumente {2}. {3} en el lado del servidor para permitir más resultados."
}
}

30
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/es.json

@ -1,25 +1,25 @@
{
"culture": "es",
"texts": {
"DisplayName:Abp.Mailing.DefaultFromAddress": "Dirección de envío",
"DisplayName:Abp.Mailing.DefaultFromDisplayName": "Nombre de envío",
"DisplayName:Abp.Mailing.DefaultFromAddress": "Por defecto desde dirección",
"DisplayName:Abp.Mailing.DefaultFromDisplayName": "Por defecto desde nombre a mostrar",
"DisplayName:Abp.Mailing.Smtp.Host": "Host",
"DisplayName:Abp.Mailing.Smtp.Port": "Puerto",
"DisplayName:Abp.Mailing.Smtp.UserName": "Nombre de usuario",
"DisplayName:Abp.Mailing.Smtp.Password": "Contraseña",
"DisplayName:Abp.Mailing.Smtp.Password": "Contraseña",
"DisplayName:Abp.Mailing.Smtp.Domain": "Dominio",
"DisplayName:Abp.Mailing.Smtp.EnableSsl": "Habilitar SSL",
"DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Usar las credenciales por defecto",
"Description:Abp.Mailing.DefaultFromAddress": "La dirección de envío por defecto",
"Description:Abp.Mailing.DefaultFromDisplayName": "El nombre de envío por defecto",
"Description:Abp.Mailing.Smtp.Host": "El nombre o dirección del host para transacciones SMTP.",
"Description:Abp.Mailing.Smtp.Port": "El puerto usado para transacciones SMTP.",
"Description:Abp.Mailing.Smtp.UserName": "Nombre de usuario asociado a las credenciales.",
"Description:Abp.Mailing.Smtp.Password": "La contraseña del ususario asociado a las credenciales.",
"Description:Abp.Mailing.Smtp.Domain": "El dominio o equipo que valida las credenciales.",
"Description:Abp.Mailing.Smtp.EnableSsl": "Si SmtpClient usa Secure Sockets Layer (SSL) para encriptar la conección.",
"Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Si las credenciales por defecto se envían con los request.",
"TextTemplate:StandardEmailTemplates.Layout": "Plantilla de email por defecto",
"TextTemplate:StandardEmailTemplates.Message": "Plantilla de mensaje simple para emails"
"DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Usar credenciales por defecto",
"Description:Abp.Mailing.DefaultFromAddress": "Por defecto desde dirección",
"Description:Abp.Mailing.DefaultFromDisplayName": "Por defecto desde nombre a mostrar",
"Description:Abp.Mailing.Smtp.Host": "El nombre o dirección IP del host usado para transacciones SMTP.",
"Description:Abp.Mailing.Smtp.Port": "El puerto usado por transacciones SMTP.",
"Description:Abp.Mailing.Smtp.UserName": "Nombre de usuario asociado con los credenciales.",
"Description:Abp.Mailing.Smtp.Password": "La contraseña para el nombre de usuario asociado con los credenciales.",
"Description:Abp.Mailing.Smtp.Domain": "El dominio o nombre de equipo que verifica los credenciales.",
"Description:Abp.Mailing.Smtp.EnableSsl": "Cuando el cliente SMTP usa Secure Sockets Layer (SSL) para encriptar la conexión.",
"Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Cuando los credenciales por defecto son enviados con las peticiones.",
"TextTemplate:StandardEmailTemplates.Layout": "Plantilla de Email por defecto",
"TextTemplate:StandardEmailTemplates.Message": "Simple plantilla de mensaje para emails"
}
}

14
framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextMySQLExtensions.cs

@ -14,11 +14,21 @@ namespace Volo.Abp.EntityFrameworkCore
{
if (context.ExistingConnection != null)
{
return context.DbContextOptions.UseMySql(context.ExistingConnection, ServerVersion.AutoDetect(context.ConnectionString), mySQLOptionsAction);
return context.DbContextOptions.UseMySql(context.ExistingConnection,
ServerVersion.AutoDetect(context.ConnectionString), optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
mySQLOptionsAction?.Invoke(optionsBuilder);
});
}
else
{
return context.DbContextOptions.UseMySql(context.ConnectionString, ServerVersion.AutoDetect(context.ConnectionString), mySQLOptionsAction);
return context.DbContextOptions.UseMySql(context.ConnectionString,
ServerVersion.AutoDetect(context.ConnectionString), optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
mySQLOptionsAction?.Invoke(optionsBuilder);
});
}
}
}

1
framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleDevartExtensions.cs

@ -13,6 +13,7 @@
// [CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null,
// bool useExistingConnectionIfAvailable = false)
// {
// TODO: UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
// if (useExistingConnectionIfAvailable && context.ExistingConnection != null)
// {
// return context.DbContextOptions.UseOracle(context.ExistingConnection, oracleOptionsAction);

1
framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextOracleExtensions.cs

@ -12,6 +12,7 @@
// [NotNull] this AbpDbContextConfigurationContext context,
// [CanBeNull] Action<OracleDbContextOptionsBuilder> oracleOptionsAction = null)
// {
// TODO: UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
// if (context.ExistingConnection != null)
// {
// return context.DbContextOptions.UseOracle(context.ExistingConnection, oracleOptionsAction);

12
framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextPostgreSqlExtensions.cs

@ -22,11 +22,19 @@ namespace Volo.Abp.EntityFrameworkCore
{
if (context.ExistingConnection != null)
{
return context.DbContextOptions.UseNpgsql(context.ExistingConnection, postgreSqlOptionsAction);
return context.DbContextOptions.UseNpgsql(context.ExistingConnection, optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
postgreSqlOptionsAction?.Invoke(optionsBuilder);
});
}
else
{
return context.DbContextOptions.UseNpgsql(context.ConnectionString, postgreSqlOptionsAction);
return context.DbContextOptions.UseNpgsql(context.ConnectionString, optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
postgreSqlOptionsAction?.Invoke(optionsBuilder);
});
}
}
}

12
framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqlServerExtensions.cs

@ -14,11 +14,19 @@ namespace Volo.Abp.EntityFrameworkCore
{
if (context.ExistingConnection != null)
{
return context.DbContextOptions.UseSqlServer(context.ExistingConnection, sqlServerOptionsAction);
return context.DbContextOptions.UseSqlServer(context.ExistingConnection, optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
sqlServerOptionsAction?.Invoke(optionsBuilder);
});
}
else
{
return context.DbContextOptions.UseSqlServer(context.ConnectionString, sqlServerOptionsAction);
return context.DbContextOptions.UseSqlServer(context.ConnectionString, optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
sqlServerOptionsAction?.Invoke(optionsBuilder);
});
}
}
}

12
framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/AbpDbContextConfigurationContextSqliteExtensions.cs

@ -14,11 +14,19 @@ namespace Volo.Abp.EntityFrameworkCore
{
if (context.ExistingConnection != null)
{
return context.DbContextOptions.UseSqlite(context.ExistingConnection, sqliteOptionsAction);
return context.DbContextOptions.UseSqlite(context.ExistingConnection, optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
sqliteOptionsAction?.Invoke(optionsBuilder);
});
}
else
{
return context.DbContextOptions.UseSqlite(context.ConnectionString, sqliteOptionsAction);
return context.DbContextOptions.UseSqlite(context.ConnectionString, optionsBuilder =>
{
optionsBuilder.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
sqliteOptionsAction?.Invoke(optionsBuilder);
});
}
}
}

34
framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/es.json

@ -1,23 +1,25 @@
{
"culture": "es",
"texts": {
"InternalServerErrorMessage": "Ocurrió un error interno en su pedido!",
"ValidationErrorMessage": "Su pedido no es válido!",
"ValidationNarrativeErrorMessageTitle": "Los siguientes errores se encontraton durante la validación.",
"DefaultErrorMessage": "Ocurrió un error!",
"DefaultErrorMessageDetail": "El servidor no envió el detalle del error.",
"DefaultErrorMessage401": "Usted no ha iniciado sessión!",
"DefaultErrorMessage401Detail": "Debe iniciar sessión para ejecutar esta operación.",
"DefaultErrorMessage403": "Usted no está autorizado!",
"DefaultErrorMessage403Detail": "Usted no puede hacer esta operación!",
"DefaultErrorMessage404": "No se encontró el recurso!",
"DefaultErrorMessage404Detail": "El recurso solicitado no se encontró en el servidor!",
"EntityNotFoundErrorMessage": "No hay una entidad {0} con el id = {1}!",
"InternalServerErrorMessage": "Un error interno ocurrido durante tu Solicitud!",
"ValidationErrorMessage": "Tu Solicitud no es valida.",
"ValidationNarrativeErrorMessageTitle": "Los siguientes errores fueron detectados durante la validación.",
"DefaultErrorMessage": "Un error ha ocurrido!",
"DefaultErrorMessageDetail": "Detalles del error no enviado por el servidor.",
"DefaultErrorMessage401": "Tu no estás autenticado!",
"DefaultErrorMessage401Detail": "Tu deberías iniciar sesión para realizar esta operación.",
"DefaultErrorMessage403": "Tu no estás autorizado!",
"DefaultErrorMessage403Detail": "No tienes permitido realizar esta operación!",
"DefaultErrorMessage404": "Recurso no encontrado!",
"DefaultErrorMessage404Detail": "El recurso solitiado podría no encontrarse en el servidor!",
"EntityNotFoundErrorMessage": "No hay una entidad {0} con id = {1}!",
"Error": "Error",
"UnhandledException": "Excepción no controlada!",
"UnhandledException": "Excepción no manejada!",
"401Message": "No autorizado",
"403Message": "Prohibido",
"404Message": "La página no existe",
"500Message": "Error interno del servidor"
"404Message": "Página no encuentrada",
"500Message": "Error interno de servidor",
"403MessageDetail": "Tu no estás autorizado para realizar esta operación!",
"404MessageDetail": "Disculpa, no hay nada en esta dirección."
}
}
}

3
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ActionApiDescriptionModel.cs

@ -31,12 +31,11 @@ namespace Volo.Abp.Http.Modeling
}
public static ActionApiDescriptionModel Create([NotNull] string uniqueName, [NotNull] MethodInfo method, [NotNull] string url, [NotNull] string httpMethod, [NotNull] IList<string> supportedVersions)
public static ActionApiDescriptionModel Create([NotNull] string uniqueName, [NotNull] MethodInfo method, [NotNull] string url, [CanBeNull] string httpMethod, [NotNull] IList<string> supportedVersions)
{
Check.NotNull(uniqueName, nameof(uniqueName));
Check.NotNull(method, nameof(method));
Check.NotNull(url, nameof(url));
Check.NotNull(httpMethod, nameof(httpMethod));
Check.NotNull(supportedVersions, nameof(supportedVersions));
return new ActionApiDescriptionModel

20
framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/es.json

@ -1,19 +1,15 @@
{
"culture": "es",
"texts": {
"DisplayName:Abp.Ldap.ServerHost": "Server host",
"Description:Abp.Ldap.ServerHost": "Servidor host",
"DisplayName:Abp.Ldap.ServerPort": "Server port",
"Description:Abp.Ldap.ServerPort": "Puerto del servidor host",
"DisplayName:Abp.Ldap.BaseDc": "Base domain component",
"DisplayName:Abp.Ldap.ServerHost": "Host del servidor",
"Description:Abp.Ldap.ServerHost": "Host del servidor",
"DisplayName:Abp.Ldap.ServerPort": "Puerto del servidor",
"Description:Abp.Ldap.ServerPort": "Puerto del servidor",
"DisplayName:Abp.Ldap.BaseDc": "Dominio base",
"Description:Abp.Ldap.BaseDc": "Dominio base",
"DisplayName:Abp.Ldap.UserName": "Username",
"DisplayName:Abp.Ldap.UserName": "Nombre de usuario",
"Description:Abp.Ldap.UserName": "Nombre de usuario",
"DisplayName:Abp.Ldap.Password": "Password",
"Description:Abp.Ldap.Password": "Contraseña"
"DisplayName:Abp.Ldap.Password": "Contraseña",
"Description:Abp.Ldap.Password": "Contraseña"
}
}

7
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/es.json

@ -0,0 +1,7 @@
{
"culture": "es",
"texts": {
"DisplayName:Abp.Localization.DefaultLanguage": "Idioma predeterminado.",
"Description:Abp.Localization.DefaultLanguage": "El idioma predeterminado de la aplicación"
}
}

18
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/EntityExtensionConfiguration.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using JetBrains.Annotations;
using Volo.Abp.Localization;
namespace Volo.Abp.ObjectExtending.Modularity
{
@ -47,14 +48,29 @@ namespace Volo.Abp.ObjectExtending.Modularity
propertyName,
() => new ExtensionPropertyConfiguration(this, propertyType, propertyName)
);
configureAction?.Invoke(propertyInfo);
NormalizeProperty(propertyInfo);
if (!propertyInfo.UI.Lookup.Url.IsNullOrEmpty())
{
AddLookupTextProperty(propertyInfo);
propertyInfo.UI.OnTable.IsVisible = false;
propertyInfo.Api.OnGet.IsAvailable = false;
}
return this;
}
private void AddLookupTextProperty(ExtensionPropertyConfiguration propertyInfo)
{
var lookupTextPropertyName = $"{propertyInfo.Name}_Text";
var lookupTextPropertyInfo = Properties.GetOrAdd(
lookupTextPropertyName,
() => new ExtensionPropertyConfiguration(this, typeof(string), lookupTextPropertyName)
);
lookupTextPropertyInfo.DisplayName = propertyInfo.DisplayName ?? new FixedLocalizableString(propertyInfo.Name);
}
[NotNull]
public virtual ImmutableList<ExtensionPropertyConfiguration> GetProperties()
{

2
framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/es.json

@ -2,6 +2,6 @@
"culture": "es",
"texts": {
"DisplayName:Abp.Timing.Timezone": "Zona horaria",
"Description:Abp.Timing.Timezone": "Zona horaria de la Aplicacion"
"Description:Abp.Timing.Timezone": "Zona horaria de aplicación"
}
}

52
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json

@ -1,52 +1,52 @@
{
"culture": "es",
"texts": {
"Languages": "Lenguajes",
"AreYouSure": "¿Está seguro?",
"Languages": "Idiomas",
"AreYouSure": "¿Estas seguro?",
"Cancel": "Cancelar",
"Clear": "Limpiar",
"Yes": "Si",
"Yes": "Sí",
"No": "No",
"Ok": "Aceptar",
"Ok": "Ok",
"Close": "Cerrar",
"Save": "Guardar",
"SavingWithThreeDot": "Guardando...",
"Actions": "Acciones",
"Delete": "Eliminar",
"Actions": "Actiones",
"Delete": "Borrar",
"Edit": "Editar",
"Refresh": "Refrescar",
"Language": "Lenguaje",
"Refresh": "Actualizar",
"Language": "Idioma",
"LoadMore": "Cargar más",
"ProcessingWithThreeDot": "Procesando...",
"LoadingWithThreeDot": "Cargando...",
"LoadingWithThreeDot": "Cargardo...",
"Welcome": "Bienvenido",
"Login": "Iniciar session",
"Login": "Iniciar Sesión",
"Register": "Registrarse",
"Logout": "Cerrar sessión",
"Logout": "Cerrar sesión",
"Submit": "Enviar",
"Back": "Atrás",
"Back": "Volver",
"PagerSearch": "Buscar",
"PagerNext": "Siguiente",
"PagerPrevious": "Anterior",
"PagerFirst": "Primero",
"PagerLast": "Último",
"PagerInfo": "Mostrando desde _START_ hasta _END_ total _TOTAL_",
"PagerInfo{0}{1}{2}": "Mostrando desde {0} hasta {1} total {2}",
"PagerInfoEmpty": "Mostrando desde 0 hasta 0 de 0 registros",
"PagerInfoFiltered": "(filtrado de un total de _MAX_ registros)",
"NoDataAvailableInDatatable": "No hay datos",
"Total": "total",
"Selected": "seleccionado",
"PagerShowMenuEntries": "Mostrar _MENU_ registros",
"PagerInfo": "Mostrando de la _START a la _END_ de _TOTAL_ entradas",
"PagerInfo{0}{1}{2}": "Mostrando de la {0} a la {1} de {2} entradas",
"PagerInfoEmpty": "Mostrando de la 0 a la 0 de 0 entradas",
"PagerInfoFiltered": "(filtrado desde _MAX_ entradas totales)",
"NoDataAvailableInDatatable": "No hay datos disponibles",
"Total": "Total",
"Selected": "Seleccionado",
"PagerShowMenuEntries": "Mostrar _MENU_ entradas",
"DatatableActionDropdownDefaultText": "Acciones",
"ChangePassword": "Cambiar contraseña",
"PersonalInfo": "My perfil",
"AreYouSureYouWantToCancelEditingWarningMessage": "Tiene cambios sin guardar.",
"PersonalInfo": "Mi perfil",
"AreYouSureYouWantToCancelEditingWarningMessage": "Tu tienes cambios sin guardar",
"GoHomePage": "Ir a la página principal",
"GoBack": "Atras",
"GoBack": "Volver atrás",
"Search": "Buscar",
"ItemWillBeDeletedMessageWithFormat": "Se eliminarán {0}!",
"ItemWillBeDeletedMessage": "Este itém será eliminado!",
"ManageYourAccount": "Administre su cuenta"
"ItemWillBeDeletedMessageWithFormat": "{0} serán borrados!",
"ItemWillBeDeletedMessage": "Este elemento será borrado",
"ManageYourAccount": "Gestiona tu cuenta"
}
}

52
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/es.json

@ -1,34 +1,34 @@
{
"culture": "es",
"texts": {
"'{0}' and '{1}' do not match.": "'{0} \" y \"{1} \" no coinciden.",
"The {0} field is not a valid credit card number.": "{0} no es un número de tarjeta de crédito.",
"{0} is not valid.": "{0} no es válido.",
"The {0} field is not a valid e-mail address.": "{0} no es una dirección de correo electrónico válida.",
"The {0} field only accepts files with the following extensions: {1}": "{0} campo sólo acepta archivos con las siguientes extensiones: {1}",
"The field {0} must be a string or array type with a maximum length of '{1}'.": "El campo {0} debe ser una cadena o un array con una longitud máxima de '{1}'.",
"The field {0} must be a string or array type with a minimum length of '{1}'.": "El campo {0} debe ser una cadena o un array con una longitud mínima de '{1}'.",
"The {0} field is not a valid phone number.": "{0} no es un número de teléfono válido.",
"The field {0} must be between {1} and {2}.": "El campo {0} debe ser entre {1} y {2}.",
"'{0}' and '{1}' do not match.": "'{0}' y '{1}' no coinciden.",
"The {0} field is not a valid credit card number.": "El campo {0} no es un número de tarjeta de crédito valido.",
"{0} is not valid.": "{0} no es valido.",
"The {0} field is not a valid e-mail address.": "El campo {0} no es una dirección de e-mail valida.",
"The {0} field only accepts files with the following extensions: {1}": "El campo {0} sólo acepta ficheros con la siguientes extensiones: {1}",
"The field {0} must be a string or array type with a maximum length of '{1}'.": "El campo {0} debe ser de tipo cadena o lista con una longitud máxima de '{1}'.",
"The field {0} must be a string or array type with a minimum length of '{1}'.": "El campo {0} debe ser de tipo cadena o lista con una longitud máxima de '{1}'.",
"The {0} field is not a valid phone number.": "El campo no tiene un número de teléfono valido.",
"The field {0} must be between {1} and {2}.": "El campo {0} debe estar entre {1} y {2}.",
"The field {0} must match the regular expression '{1}'.": "El campo {0} no coincide con el formato solicitado.",
"The {0} field is required.": "El {0} campo es obligatorio.",
"The {0} field is required.": "El campo {0} es requerido.",
"The field {0} must be a string with a maximum length of {1}.": "El campo {0} debe ser una cadena con una longitud máxima de {1}.",
"The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "El campo {0} debe ser una cadena con una longitud mínima de {2} y una longitud máxima de {1}.",
"The {0} field is not a valid fully-qualified http, https, or ftp URL.": "El campo {0} no es una dirección URL válida http, https o ftp.",
"The field {0} is invalid.": "El campo {0} no es válido.",
"ThisFieldIsNotAValidCreditCardNumber.": "Este campo no es un número de tarjeta de crédito.",
"ThisFieldIsNotValid.": "Este campo no es válido.",
"ThisFieldIsNotAValidEmailAddress.": "Este campo no es una dirección de correo electrónico válida.",
"ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Este campo sólo acepta archivos con las siguientes extensiones: {0}",
"ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}": "Este campo debe ser una cadena o un array con una longitud máxima de '{0}'.",
"ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Este campo debe ser una cadena o un array con una longitud mínima de '{0}'.",
"ThisFieldIsNotAValidPhoneNumber.": "Este campo no es un número de teléfono válido.",
"ThisFieldMustBeBetween{0}And{1}": "Este campo debe tener un valor entre {0} y {1}.",
"The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "El campo {0} debe ser una cadena con una longitud mínima de {2} y máxima de {1}.",
"The {0} field is not a valid fully-qualified http, https, or ftp URL.": "El campo {0} no es una URL (http, https o ftp) valida.",
"The field {0} is invalid.": "El campo {0} no es valido.",
"ThisFieldIsNotAValidCreditCardNumber.": "El campo no es un número de tarjeta de crédito valido.",
"ThisFieldIsNotValid.": "Este campo no es valido.",
"ThisFieldIsNotAValidEmailAddress.": "Este campo no es una dirección de e-mail valida.",
"ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Este campo sólo acepta ficheros con las siguientes extensiones: {0}",
"ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}": "Este campo debe ser una cadena o lista con una longitud máxima de {1}.",
"ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Este campo debe ser una cadena o lista con una longitud mínima de {1}.",
"ThisFieldIsNotAValidPhoneNumber.": "Este campo no es un número de teléfono valido.",
"ThisFieldMustBeBetween{0}And{1}": "Este campo debe estar entre {0} y {1}.",
"ThisFieldMustMatchTheRegularExpression{0}": "Este campo debe coincidir con la expresión regular '{0}'.",
"ThisFieldIsRequired.": "Este campo es obligatorio.",
"ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Este campo debe ser una cadena de caracteres con una longitud máxima de {0}.",
"ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Este campo debe ser una cadena de caracteres con una longitud mínima de {1} y una longitud máxima de {0}.",
"ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Este campo no es una dirección URL válida http, https o ftp.",
"ThisFieldIsInvalid.": "Este campo no es válido."
"ThisFieldIsRequired.": "Este campo es requerido",
"ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Este campo debe ser una cadena con una longitud máxima de {1}.",
"ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Este campo debe ser una cadena con una longitud mínima de {2} y máxima de {1}.",
"ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "El campo {0} no es una URL (http, https o ftp) valida.",
"ThisFieldIsInvalid.": "Este en un campo no valido."
}
}

31
modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/es.json

@ -11,12 +11,12 @@
"InvalidUserNameOrPassword": "El nombre de usuario o la contraseña no son válidos",
"LoginIsNotAllowed": "No está permitido el inicio de sesión! Usted tendrá que confirmar su correo electrónico o número de teléfono.",
"SelfRegistrationDisabledMessage": "El autoregistro de usuario está deshabilitado para esta aplicación. Póngase en contacto con el administrador de la aplicación para registrar un nuevo usuario.",
"LocalLoginDisabledMessage": "No está habilitado el login local para esta aplicación.",
"LocalLoginDisabledMessage": "Inicio de sesión local ha sido deshabilitado para esta aplicación",
"Login": "Iniciar sesión",
"Cancel": "Cancelar",
"Register": "Registrarse",
"AreYouANewUser": "¿Usted es un usuario nuevo?",
"AlreadyRegistered": "¿Está registrado en esta aplicación?",
"AreYouANewUser": "¿Eres un nuevo usuario?",
"AlreadyRegistered": "¿Ya registrado?",
"InvalidLoginRequest": "Solicitud de inicio de sesión no válido",
"ThereAreNoLoginSchemesConfiguredForThisClient": "No hay ningún esquema de inicio de sesión configurado para este cliente.",
"LogInUsingYourProviderAccount": "Inicia sesión con tu cuenta de {0} ",
@ -37,9 +37,26 @@
"NewPasswordConfirmFailed": "Por favor, confirme la nueva contraseña.",
"Manage": "Administrar",
"ManageYourProfile": "Gestionar su perfil",
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Habilitar el registro de usuario",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Si está habilitado los usuarios pueden crear una cuenta mediante el registro automático.",
"DisplayName:Abp.Account.EnableLocalLogin": "Habilitar cuenta local",
"Description:Abp.Account.EnableLocalLogin": "Indica que el servidor permite iniciar sessión con una cuenta local."
"DisplayName:Abp.Account.IsSelfRegistrationEnabled": "¿Está el auto-registro habilitado?",
"Description:Abp.Account.IsSelfRegistrationEnabled": "Cuando un usuario puede registrar la cuenta por él/ ella mismo/a",
"DisplayName:Abp.Account.EnableLocalLogin": "Autenticado con una cuenta local",
"Description:Abp.Account.EnableLocalLogin": "Indica si el servidor permitirá a los usuarios autenticarse con una cuenta local.",
"LoggedOutTitle": "Sesión cerrada",
"LoggedOutText": "La sesión ha sido cerrada y serás redireccionado en breve.",
"ReturnToText": "Haz click aquí para redirigirte a {0}",
"OrLoginWith": "O inicia sesión con;",
"ForgotPassword": "¿Olvidaste la contraseña?",
"SendPasswordResetLink_Information": "Un link para resetear la contraseña será enviado a tu e-mail. Si no recibes el e-mail en unos minutos, por favor re-intenta.",
"PasswordResetMailSentMessage": "Un e-mail para recuperar la cuenta ha sido enviado a tu e-mail. Si no recibes el e-mail en unos minutos, por favor re-intentalo.",
"ResetPassword": "Resetear contraseña",
"ConfirmPassword": "Confirmar la contraseña",
"ResetPassword_Information": "Por favor, introduce tu nueva contraseña.",
"YourPasswordIsSuccessfullyReset": "Tu contraseña ha sido reseteada satisfactoriamente.",
"GoToTheApplication": "Ir a la aplicación",
"BackToLogin": "Volver al inicio de sesión",
"ProfileTab:Password": "Cambiar contraseña",
"ProfileTab:PersonalInfo": "Información personal",
"ReturnToApplication": "Volver a la aplicación",
"Volo.Account:InvalidEmailAddress": "No se puede encontrar la dirección de e-mail solicitada: {0}"
}
}

1
modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/AbpAuditLoggingEfCoreQueryableExtensions.cs

@ -15,7 +15,6 @@ namespace Volo.Abp.AuditLogging
}
return queryable
.AsSplitQuery()
.Include(x => x.Actions)
.Include(x => x.EntityChanges).ThenInclude(ec=>ec.PropertyChanges);
}

6
modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/es.json

@ -0,0 +1,6 @@
{
"culture": "es",
"texts": {
"ManageYourProfile": "Administra tu perfil"
}
}

58
modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/es.json

@ -0,0 +1,58 @@
{
"culture": "es",
"texts": {
"Menu:Blogs": "Blogs",
"Menu:BlogManagement": "Blogging",
"Permission:Management": "Gestión",
"Permission:Edit": "Editar",
"Permission:Create": "Crear",
"Permission:Delete": "Borrar",
"Permission:Blogging": "Blog",
"Permission:Blogs": "Blogs",
"Permission:Posts": "Entradas",
"Permission:Tags": "Etiquetas",
"Permission:Comments": "Comentarios",
"Title": "Título",
"Delete": "Borrar",
"Reply": "Respondere",
"ReplyTo": "Responder a {0}",
"ContinueReading": "Continuar leyendo",
"DaysAgo": "Hace {0} días",
"YearsAgo": "Hace {0} años",
"MonthsAgo": "Hace {0} meses",
"WeeksAgo": "Hace {0} semanas",
"MinutesAgo": "Hacer {0} minutos",
"SecondsAgo": "Hace {0} segundos",
"HoursAgo": "Hace {0} horas",
"Now": "Ahora",
"Content": "Contenido",
"SeeAll": "Ver todo",
"PopularTags": "Etiquetas populares",
"WiewsWithCount": "{0} visualizaciones",
"LastPosts": "Última entrada",
"LeaveComment": "Deja un comentario",
"TagsInThisArticle": "Etiquetas en este artículo",
"Posts": "Entradas",
"Edit": "Editar",
"BLOG": "BLOG",
"CommentDeletionWarningMessage": "El comentario será borrado",
"PostDeletionWarningMessage": "La entrada será borrada.",
"BlogDeletionWarningMessage": "El blog será borrado.",
"AreYouSure": "¿Estás seguro?",
"CommentWithCount": "{0} comentarios",
"Comment": "Comentario",
"ShareOnTwitter": "Comparte en Twitter",
"CoverImage": "Imágen de portada",
"CreateANewPost": "Crear una nueva entrada",
"CreateANewBlog": "Crear un nuevo blog",
"WhatIsNew": "Novedades",
"Name": "Nombre",
"ShortName": "Nombre corto",
"CreationTime": "Fecha de creación",
"Description": "Descripción",
"Blogs": "Blogs",
"Tags": "Etiquetas",
"ShareOn": "Compartir en",
"TitleLengthWarning": "Manten el tamaño del título por debajo de 60 caracteres para ser amigable al SEO"
}
}

22
modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/es.json

@ -0,0 +1,22 @@
{
"culture": "es",
"texts": {
"PickYourReaction": "Recoge tu reación",
"YourComment": "Tu comentario",
"YourReply": "Tu respuesta",
"Comments": "Comentarios",
"Send": "Enviar",
"Delete": "Borrar",
"Reply": "Responder",
"Update": "Actualizar",
"Edit": "Editar",
"LoginToAddComment": "Inicia sesión para añadir comentarios",
"LoginToReply": "Inicia sesión para responder",
"MessageDeletionConfirmationMessage": "Este comentario será completamente borrado.",
"CommentAuthorizationExceptionMessage": "Esos comentarios no están permitidos mostrarlos al público.",
"Undo": "Deshacer",
"RatingUndoMessage": "Tu puntuación sera removida.",
"LoginToRate": "Inicia sesión para puntuar",
"Star": "Valoración"
}
}

10
modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/es.json

@ -0,0 +1,10 @@
{
"culture": "es",
"texts": {
"DocsTitle": "VoloDocs",
"WelcomeVoloDocs": "Bienvenidos a VoloDocs",
"NoProjectWarning": "No hay proyectos definidos todavía!",
"CreateYourFirstProject": "Click aquí para comenzar to primer proyecto",
"NoProject": "No proyecto!"
}
}

6
modules/docs/app/VoloDocs.Web/Utils/GlobalExceptionHandlerMiddleware.cs

@ -11,9 +11,9 @@ namespace VoloDocs.Web.Utils
public class GlobalExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<AbpUnitOfWorkMiddleware> _logger;
private readonly ILogger<GlobalExceptionHandlerMiddleware> _logger;
public GlobalExceptionHandlerMiddleware(RequestDelegate next, ILogger<AbpUnitOfWorkMiddleware> logger)
public GlobalExceptionHandlerMiddleware(RequestDelegate next, ILogger<GlobalExceptionHandlerMiddleware> logger)
{
_logger = logger;
_next = next;
@ -42,4 +42,4 @@ namespace VoloDocs.Web.Utils
}
}
}
}
}

59
modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/es.json

@ -0,0 +1,59 @@
{
"culture": "es",
"texts": {
"Permission:DocumentManagement": "Gestión de documentos",
"Permission:Projects": "Proyectos",
"Permission:Edit": "Editar",
"Permission:Delete": "Borrar",
"Permission:Create": "Crear",
"Permission:Documents": "Documentos",
"Menu:Documents": "Documentos",
"Menu:DocumentManagement": "Documentos",
"Menu:ProjectManagement": "Proyectos",
"CreateANewProject": "Crear nuevo proyecto",
"Edit": "Editar",
"Create": "Crear",
"Pull": "Extraer",
"Projects": "Proyectos",
"Name": "Nombre",
"ShortName": "ShortName",
"DocumentStoreType": "DocumentStoreType",
"Format": "Formato",
"ShortNameInfoText": "Será usado para crear una URL única",
"DisplayName:Name": "Nombre",
"DisplayName:ShortName": "Nombre corto",
"DisplayName:Format": "Formato",
"DisplayName:DefaultDocumentName": "Nombre del documento predeterminado",
"DisplayName:NavigationDocumentName": "Nombre del documento de navegación",
"DisplayName:MinimumVersion": "Versión mínima",
"DisplayName:MainWebsiteUrl": "URL principal del sitio web",
"DisplayName:LatestVersionBranchName": "Nombre de la rama de la última versión ",
"DisplayName:GitHubRootUrl": "URL raíz de GitHub",
"DisplayName:GitHubAccessToken": "Token de acceso a GitHub",
"DisplayName:GitHubUserAgent": "Usuario agente de GitHub",
"DisplayName:GithubVersionProviderSource": "Versión del proveedor de Github",
"DisplayName:VersionBranchPrefix": "Prefijo de la rama de la versión",
"DisplayName:All": "Extraer tódo",
"DisplayName:LanguageCode": "Código de idioma",
"DisplayName:Version": "Versión",
"Documents": "Documentos",
"RemoveFromCache": "Borrado de caché",
"Reindex": "Reindexado",
"ReindexCompleted": "Reindexado completado",
"RemovedFromCache": "Borrar la caché",
"RemoveFromCacheConfirmation": "¿Estás seguro que quieres borrar este elemento de la caché?",
"ReIndexDocumentConfirmation": "¿Estás seguro que quieres reindexar este elemento?",
"DeleteFromDatabase": "Eliminado de la base de datos",
"Deleted": "Eliminado",
"Search": "Buscar",
"StartDate": "Fecha de inicio",
"EndDate": "Fecha de fin",
"CreationTime": "Fecha de creación",
"LastUpdateTime": "Última actualización",
"LastSignificantUpdateTime": "Última actualización significativa",
"Version": "Versión",
"LanguageCode": "Código de idioma",
"FileName": "Nombre de fichero",
"LastCachedTime": "Última actualización de caché"
}
}

38
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/es.json

@ -2,18 +2,38 @@
"culture": "es",
"texts": {
"Documents": "Documentos",
"BackToWebsite": "Regresar al sitio",
"BackToWebsite": "Volver al sitio web",
"Contributors": "Contribuidores",
"ShareOn": "Compartilhar no",
"Version": "Versão",
"ShareOn": "Compartir en",
"Version": "Versión",
"Edit": "Editar",
"Delete": "Excluir",
"LastEditTime": "Última edición",
"Delete": "Borrar",
"ClearCache": "Borrar caché",
"ClearCacheConfirmationMessage": "Estas seguro que quieres borrar todas las cachés para el proyecto",
"ReIndexAllProjects": "Reindexar todos los proyectos",
"ReIndexProject": "Reindexar proyecto",
"ReIndexProjectConfirmationMessage": "¿Estás seguro que quieres reindexar el proyecto \"{0}\"?",
"SuccessfullyReIndexProject": "La reidexación para el proyecto \"{0}\" se completo correctamente",
"ReIndexAllProjectConfirmationMessage": "¿Estás seguro que quieres reindexar todos los proyectos?",
"SuccessfullyReIndexAllProject": "La reidexación para todos los proyectos se completo correctamente",
"InThisDocument": "En este documento",
"GoToTop": "Subir",
"GoToTop": "Ir hacia arriba",
"Projects": "Proyecto(s)",
"NoProjectWarning": "Não há projetos ainda!",
"DocumentNotFound": "Ups! O documento solicitado não foi encontrado!",
"NavigationDocumentNotFound": "Esta versão não possui um documento de navegação!",
"DocumentNotFoundInSelectedLanguage": "Documento no idioma desejado não foi encontrado. Documento no idioma padrão é mostrado."
"NoProjectWarning": "No hay proyectos todavía!",
"DocumentNotFound": "Oops, El documento solicitado no fue encontrado!",
"ProjectNotFound": "Oops, El proyecto solicitado no fue encontrado!",
"NavigationDocumentNotFound": "Esta versión no tiene un documento de navegación!",
"DocumentNotFoundInSelectedLanguage": "documento en el idioma que solicitaste no encontrado. El documento será mostrado en el idioma por defecto.",
"FilterTopics": "Filtrar temas ",
"FullSearch": "Buscar en documentos",
"Volo.Docs.Domain:010001": "Búsqueda elástica no habilida",
"MultipleVersionDocumentInfo": "Este documento tiene múltiple versiones. Selecciona las opciones que más te interesan.",
"New": "Nuevo",
"Upd": "Upd",
"NewExplanation": "Creado en las últimas dos semanas.",
"UpdatedExplanation": "Actualizo en las dos últimas semanas",
"Volo.Docs.Domain:010002": "ShortName {ShortName} ya existe.",
"Preview": "Previsualizar"
}
}

10
modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/es.json

@ -0,0 +1,10 @@
{
"culture": "es",
"texts": {
"Features": "Características",
"NoFeatureFoundMessage": "No hay ninguna característica disponible.",
"Permission:FeatureManagement": "Gestión de características",
"Permission:FeatureManagement.ManageHostFeatures": "Gestionar características del Host",
"Volo.Abp.FeatureManagement:InvalidFeatureValue": "{0} valor de característica no es valido!"
}
}

120
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/es.json

@ -0,0 +1,120 @@
{
"culture": "es",
"texts": {
"Menu:IdentityManagement": "Gestión de identidades",
"Users": "Usuarios",
"NewUser": "Nuevo Usuario",
"UserName": "Nombre de usuario",
"EmailAddress": "Dirección e-mail",
"PhoneNumber": "Número de teléfono",
"UserInformations": "Información de usuario",
"DisplayName:IsDefault": "Predeterminado",
"DisplayName:IsStatic": "Estático",
"DisplayName:IsPublic": "Público",
"Roles": "Roles",
"Password": "Contraseña",
"PersonalInfo": "Mi perfil",
"PersonalSettings": "Configuración personal",
"UserDeletionConfirmationMessage": "El usuario '{0}' será eliminado. ¿Quieres continuar?",
"RoleDeletionConfirmationMessage": "El role '{0}' será eliminado. ¿Quieres continuar? ",
"DisplayName:RoleName": "Nombre de Role",
"DisplayName:UserName": "Nombre de usuario",
"DisplayName:Name": "Nombre",
"DisplayName:Surname": "Apellido",
"DisplayName:Password": "Contraseña",
"DisplayName:Email": "Dirección de e-mail",
"DisplayName:PhoneNumber": "Número de teléfono",
"DisplayName:TwoFactorEnabled": "Autenticación en dos pasos",
"DisplayName:LockoutEnabled": "Bloquear la cuenta después de intentos de inicio de sesión fallidos",
"NewRole": "Nuevo role",
"RoleName": "Nombre de role",
"CreationTime": "Fecha de creación",
"Permissions": "Permisos",
"DisplayName:CurrentPassword": "Contraseña actual",
"DisplayName:NewPassword": "Nueva contraseña",
"DisplayName:NewPasswordConfirm": "Confirmar nueva contraseña",
"PasswordChangedMessage": "Tu contraseña ha sido cambiada satisfactoriamente.",
"PersonalSettingsSavedMessage": "Tu configuración personal ha sido guardada satisfactoriamente.",
"Volo.Abp.Identity:DefaultError": "Error desconocido.",
"Volo.Abp.Identity:ConcurrencyFailure": "Fallo de concurrencia optimista",
"Volo.Abp.Identity:DuplicateEmail": "E-mail '{0}' está en uso.",
"Volo.Abp.Identity:DuplicateRoleName": "Nombre de role '{0}' está en uso.",
"Volo.Abp.Identity:DuplicateUserName": "Nombre de usuario '{0}' está en uso.",
"Volo.Abp.Identity:InvalidEmail": "E-mail '{0}' no es válido.",
"Volo.Abp.Identity:InvalidPasswordHasherCompatibilityMode": "El PasswordHasherCompatibilityMode proporcionado no es válido.",
"Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "La cuenta iterativa debe ser una entero positivo.",
"Volo.Abp.Identity:InvalidRoleName": "El nombre de role '{0}' no es válido.",
"Volo.Abp.Identity:InvalidToken": "token no válido",
"Volo.Abp.Identity:InvalidUserName": "Nombre de usuario '{0}' no es válido. Sólo puede contener letras o dígitos",
"Volo.Abp.Identity:LoginAlreadyAssociated": "Usuario con este inicio de sesión en uso.",
"Volo.Abp.Identity:PasswordMismatch": "Contraseña incorrecta.",
"Volo.Abp.Identity:PasswordRequiresDigit": "Contraseñas deben tener al menos un dígito ('0'-'9').",
"Volo.Abp.Identity:PasswordRequiresLower": "Contraseñas deben tener al menos un caráctere en minúscula ('a'-'z').",
"Volo.Abp.Identity:PasswordRequiresNonAlphanumeric": "Contraseñas deben tener al menos un carácter no alfanumérico",
"Volo.Abp.Identity:PasswordRequiresUpper": "Contraseñas deben tener al menos un carácter en mayúsculas ('A'-'Z').",
"Volo.Abp.Identity:PasswordTooShort": "Contraseñas deben tener al menos {0} caracteres",
"Volo.Abp.Identity:RoleNotFound": "El role {0} no existe.",
"Volo.Abp.Identity:UserAlreadyHasPassword": "El usuario tiene la contraseña establecida",
"Volo.Abp.Identity:UserAlreadyInRole": "El usuario ya tiene asignado el rol '{0}'´.",
"Volo.Abp.Identity:UserLockedOut": "El usuario está bloqueado.",
"Volo.Abp.Identity:UserLockoutNotEnabled": "El bloqueo no está habilitado para este usuario.",
"Volo.Abp.Identity:UserNameNotFound": "El usuario {0} no existe.",
"Volo.Abp.Identity:UserNotInRole": "El usuario no tiene asignado el rol '{0}'.",
"Volo.Abp.Identity:PasswordConfirmationFailed": "La contraseña no coincide con la confirmación.",
"Volo.Abp.Identity:010001": "Tu no puedes borrar tu propia cuenta!",
"Volo.Abp.Identity:010002": "No puedes establecer más de {MaxUserMembershipCount} unidades organizativas para un usuario!",
"Volo.Abp.Identity:010003": "No puedes cambiar la contraseña de un usuario que inicio sesión desde un servicio externo!",
"Volo.Abp.Identity:010004": "Hay una unidad organizativa con nombre {0}. Dos unidades con el mismo nombre no pueden ser creadas en el mismo nivel.",
"Volo.Abp.Identity:010005": "Roles estáticos no pueden ser renombrados.",
"Volo.Abp.Identity:010006": "Roles estáticos no pueden ser borrados.",
"Volo.Abp.Identity:010007": "No puedes cambiar tu configuración de autentificación de dos pasos.",
"Volo.Abp.Identity:010008": "No está permitido cambiar la configuración de autenticación de dos pasos.",
"Identity.OrganizationUnit.MaxUserMembershipCount": "Número máximo de unidades organizativas por usuario",
"Permission:IdentityManagement": "Gestión de identidades",
"Permission:RoleManagement": "Gestión de roles",
"Permission:Create": "Crear",
"Permission:Edit": "Editar",
"Permission:Delete": "Borrar",
"Permission:ChangePermissions": "Cambiar permisos",
"Permission:UserManagement": "Gestión de usuarios",
"Permission:UserLookup": "Busqueda de usuario",
"Feature:IdentityGroup": "Identidad",
"Feature:TwoFactor": "Autenticatión de dos pasos",
"Feature:TwoFactorDescription": "Establecer autenticación de dos pasos. Valores opcionales: Opcional, Deshabilitado, Obligatorio",
"Feature:TwoFactor.Optional": "Opcional",
"Feature:TwoFactor.Disabled": "Deshabilitado",
"Feature:TwoFactor.Forced": "Obligatorio",
"DisplayName:Abp.Identity.Password.RequiredLength": "Longitud requerida",
"DisplayName:Abp.Identity.Password.RequiredUniqueChars": "Caracteres únicos requeridos",
"DisplayName:Abp.Identity.Password.RequireNonAlphanumeric": "Caracteres no alfanuméricos requeridos",
"DisplayName:Abp.Identity.Password.RequireLowercase": "Carácter en minúsculas requerido",
"DisplayName:Abp.Identity.Password.RequireUppercase": "Carácter en mayúsculas requerido",
"DisplayName:Abp.Identity.Password.RequireDigit": "Dígito requerido",
"DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Habilitado para nuevos usuarios",
"DisplayName:Abp.Identity.Lockout.LockoutDuration": "Duración del bloqueo (segundos)",
"DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Número máximo de accesos fallidos",
"DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Confirmación de e-mail requerida",
"DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permitir usuarios confirmar su número de teléfono",
"DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Requerir confirmación de número de teléfono",
"DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Permitir a los usuarios cambiar su nombre de usuario.",
"DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Permitir usuarios cambiar sus direcciones de e-mail",
"Description:Abp.Identity.Password.RequiredLength": "La mínima longitud de una contraseña debe ser.",
"Description:Abp.Identity.Password.RequiredUniqueChars": "El mínimo número de caracteres unicos que una contraseña debe contener.",
"Description:Abp.Identity.Password.RequireNonAlphanumeric": "Si las contraseñas deben contener un no alfanumérico carácter.",
"Description:Abp.Identity.Password.RequireLowercase": "Si las contraseñas deben contener un carácter en minúscula.",
"Description:Abp.Identity.Password.RequireUppercase": "Si las contreseñas deben contener un carácter en mayúscula",
"Description:Abp.Identity.Password.RequireDigit": "Si las contraseñas deben contener un dígito",
"Description:Abp.Identity.Lockout.AllowedForNewUsers": "Si un nuevo usuario puede ser bloqueado.",
"Description:Abp.Identity.Lockout.LockoutDuration": "La duración del bloqueo de un usuario cuando el bloqueo ocurre.",
"Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "El número de accessos fallidos permitidos antes de que un usuario sea bloqueado, el bloqueo de usuario debe estar habilitado.",
"Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Si la confirmación de dirección de e-mail es requerida para iniciar sesión.",
"Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Si el número de teléfono puede ser confirmado por el usuario. ",
"Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Sí un número de teléfono confirmado es requerido para iniciar sesión.",
"Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Si el nombre de usuario puede ser actualizado por el usuario.",
"Description:Abp.Identity.User.IsEmailUpdateEnabled": "Si el e-mail puede ser actualizado por el usuario.",
"DisplayName:Abp.Identity.TwoFactorBehaviour": "Autenticación de dos pasos",
"Description:Abp.Identity.TwoFactorBehaviour": "Autenticación de dos pasos",
"DisplayName:Abp.Identity.UsersCanChange": "Permitir a los usuario cambiar su autenticación de dos pasos.",
"Description:Abp.Identity.UsersCanChange": "Permitir a los usuario cambiar su autenticación de dos pasos."
}
}

1
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityEfCoreQueryableExtensions.cs

@ -13,7 +13,6 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
}
return queryable
.AsSplitQuery()
.Include(x => x.Roles)
.Include(x => x.Logins)
.Include(x => x.Claims)

37
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/CreateModal.cshtml

@ -24,23 +24,28 @@
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<CreateModalModel.RoleInfoModel>())
{
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
if (!propertyInfo.Name.EndsWith("_Text"))
{
<abp-select asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.Role.ExtraProperties[propertyInfo.Name])" />
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
{
<abp-select asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-selected-item-name="@Model.Role.ExtraProperties[propertyInfo.Name+"_Text"]"
autocomplete-selected-item-value="@Model.Role.ExtraProperties[propertyInfo.Name]"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.Role.ExtraProperties[propertyInfo.Name])" />
}
}
}
</abp-modal-body>

37
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Roles/EditModal.cshtml

@ -35,23 +35,28 @@
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<CreateModalModel.RoleInfoModel>())
{
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
if (!propertyInfo.Name.EndsWith("_Text"))
{
<abp-select asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.Role.ExtraProperties[propertyInfo.Name])" />
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
{
<abp-select asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-selected-item-name="@Model.Role.ExtraProperties[propertyInfo.Name+"_Text"]"
autocomplete-selected-item-value="@Model.Role.ExtraProperties[propertyInfo.Name]"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="Role.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.Role.ExtraProperties[propertyInfo.Name])" />
}
}
}
</abp-modal-body>

37
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml

@ -29,23 +29,28 @@
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<CreateModalModel.UserInfoViewModel>())
{
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
if (!propertyInfo.Name.EndsWith("_Text"))
{
<abp-select asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.UserInfo.ExtraProperties[propertyInfo.Name])" />
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
{
<abp-select asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-selected-item-name="@Model.UserInfo.ExtraProperties[propertyInfo.Name+"_Text"]"
autocomplete-selected-item-value="@Model.UserInfo.ExtraProperties[propertyInfo.Name]"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.UserInfo.ExtraProperties[propertyInfo.Name])" />
}
}
}
</abp-tab>

37
modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml

@ -31,23 +31,28 @@
@foreach (var propertyInfo in ObjectExtensionManager.Instance.GetProperties<EditModalModel.UserInfoViewModel>())
{
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
if (!propertyInfo.Name.EndsWith("_Text"))
{
<abp-select asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.UserInfo.ExtraProperties[propertyInfo.Name])" />
if (propertyInfo.Type.IsEnum || !propertyInfo.Lookup.Url.IsNullOrEmpty())
{
<abp-select asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
autocomplete-api-url="@propertyInfo.Lookup.Url"
autocomplete-selected-item-name="@Model.UserInfo.ExtraProperties[propertyInfo.Name+"_Text"]"
autocomplete-selected-item-value="@Model.UserInfo.ExtraProperties[propertyInfo.Name]"
autocomplete-filter-param-name="@propertyInfo.Lookup.FilterParamName"
autocomplete-items-property-name="@propertyInfo.Lookup.ResultListPropertyName"
autocomplete-display-property-name="@propertyInfo.Lookup.DisplayPropertyName"
autocomplete-value-property-name="@propertyInfo.Lookup.ValuePropertyName"></abp-select>
}
else
{
<abp-input type="@propertyInfo.GetInputType()"
asp-for="UserInfo.ExtraProperties[propertyInfo.Name]"
label="@propertyInfo.GetLocalizedDisplayName(StringLocalizerFactory)"
asp-format="@propertyInfo.GetInputFormatOrNull()"
value="@propertyInfo.GetInputValueOrNull(Model.UserInfo.ExtraProperties[propertyInfo.Name])" />
}
}
}

14
modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/es.json

@ -0,0 +1,14 @@
{
"culture": "es",
"texts": {
"Volo.IdentityServer:DuplicateIdentityResourceName": "El nombre de recurso de identidad ya existe: {Name}",
"Volo.IdentityServer:DuplicateApiResourceName": "El nombre de recurso de Api ya existe: {Name}",
"Volo.IdentityServer:DuplicateApiScopeName": "El nombre de ámbito de Api ya existe: {Name}",
"Volo.IdentityServer:DuplicateClientId": "ClientId ya existe: {ClientId}",
"UserLockedOut": "La cuenta de usuario ha sido bloqueada debido a inicios de sesión no validos. Por favor, espera un rato e intentalo de nuevo.",
"InvalidUserNameOrPassword": "Nombre de usuario o contraseña no válido!",
"LoginIsNotAllowed": "No puedes iniciar sesión!, necesitas confirmar tu e-mail/ número de teléfono.",
"InvalidUsername": "",
"TheTargetUserIsNotLinkedToYou": "El usuario de destino no está asociado a tí"
}
}

2
modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/AbpIdentityServerEfCoreQueryableExtensions.cs

@ -17,7 +17,6 @@ namespace Volo.Abp.IdentityServer
}
return queryable
.AsSplitQuery()
.Include(x => x.Secrets)
.Include(x => x.UserClaims)
.Include(x => x.Scopes)
@ -57,7 +56,6 @@ namespace Volo.Abp.IdentityServer
}
return queryable
.AsSplitQuery()
.Include(x => x.AllowedGrantTypes)
.Include(x => x.RedirectUris)
.Include(x => x.PostLogoutRedirectUris)

10
modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/es.json

@ -0,0 +1,10 @@
{
"culture": "es",
"texts": {
"Permissions": "Permisos",
"OnlyProviderPermissons": "Sólo este proveedor",
"All": "Todos",
"SelectAllInAllTabs": "Condeder todos los permisos",
"SelectAllInThisTab": "Seleccionar todo"
}
}

7
modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/es.json

@ -0,0 +1,7 @@
{
"culture": "es",
"texts": {
"Settings": "Configuraciones",
"SuccessfullySaved": "Guardado correctamente"
}
}

23
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/es.json

@ -0,0 +1,23 @@
{
"culture": "es",
"texts": {
"Menu:TenantManagement": "Gestión de tenants",
"Tenants": "Inquilinos",
"NewTenant": "Nuevo inquilino",
"TenantName": "Nombre del inquilino",
"DisplayName:TenantName": "Nombre del inquilino",
"TenantDeletionConfirmationMessage": "Se eliminará el inquilino '{0}'. Confirmas eso?",
"ConnectionStrings": "Connection Strings",
"DisplayName:DefaultConnectionString": "Connection String predeterminado",
"DisplayName:UseSharedDatabase": "Usar la base de datos compartida",
"ManageHostFeatures": "Administrar funciones de host",
"Permission:TenantManagement": "Gestión de tenants",
"Permission:Create": "Crear",
"Permission:Edit": "Editar",
"Permission:Delete": "Borrar",
"Permission:ManageConnectionStrings": "Gestión de cadenas de conexión",
"Permission:ManageFeatures": "Gestión de características",
"DisplayName:AdminEmailAddress": "Dirección de e-mail de administrador",
"DisplayName:AdminPassword": "Contraseña de administrador"
}
}

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

Loading…
Cancel
Save