diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index b81733d247..456e8ebd05 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -987,7 +987,7 @@ "Summary": "Summary", "TrainingPack": "Training pack", "TrainingPackDiscount": "Training pack discount", - "Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. Learn more ", + "Purchase_OnboardingTraining_Description": "This live training is valid for a class of 8 students and this discount is only valid when purchased with the new license. Learn more ", "Purchase_Save": "{0}% Save {1}", "RemoveBasket": "Remove from basket", "WhyABPIOPlatform?": "Why ABP.IO Platform?", diff --git a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md index c499f6e33c..2f5cde6d2d 100644 --- a/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md +++ b/docs/en/Community-Articles/2021-06-17-Using-Elsa-Workflow-with-ABP-Framework/POST.md @@ -1,5 +1,7 @@ # Using Elsa Workflow with ABP Framework +> **UPDATE:** There is a newer version of this article, which covers Elsa 3 with ABP Framework. You can check it at https://abp.io/community/articles/using-elsa-3-workflow-with-abp-framework-usqk8afg + **Elsa Core** is an open-source workflows library that can be used in any kind of .NET Core application. Using such a workflow library can be useful to implement business rules visually or programmatically. ![elsa-overview](./elsa-overview.gif) @@ -465,4 +467,4 @@ namespace ElsaDemo.Web.Menus > 🛠 Liked this post? I now share all my content on Substack — real-world .NET, AI, and scalable software design. > 👉 Subscribe here → engincanveske.substack.com > 🎥 Also, check out my YouTube channel for hands-on demos and deep dives: https://www.youtube.com/@engincanv ---- \ No newline at end of file +--- diff --git a/docs/en/framework/infrastructure/features.md b/docs/en/framework/infrastructure/features.md index ef5d97bd91..a6bc52e48b 100644 --- a/docs/en/framework/infrastructure/features.md +++ b/docs/en/framework/infrastructure/features.md @@ -424,7 +424,7 @@ namespace FeaturesDemo return Task.FromResult("true"); } - return null; + return Task.FromResult(null); } } } diff --git a/docs/en/studio/release-notes.md b/docs/en/studio/release-notes.md index ef498fcac5..cfb8e9fb61 100644 --- a/docs/en/studio/release-notes.md +++ b/docs/en/studio/release-notes.md @@ -2,6 +2,19 @@ This document contains **brief release notes** for each ABP Studio release. Release notes only include **major features** and **visible enhancements**. Therefore, they don't include all the development done in the related version. +## 0.9.26 (2025-04-30) + +* Fixed the issue where C# applications would not stop when requested. +* Added idle session timeout feature to Blazor WebAssembly applications. +* Added “Setup as a modular solution” option to application startup templates. +* Automatically added remote service base URL after generating C# proxies. +* Configured Helm charts for Kubernetes health check endpoints. +* Fixed auditing issue in Blazor WebAssembly applications. +* Fixed login error after registering a new user in Blazor WebApp. +* Implemented password login flow in Studio CLI. +* Supported non-root user mode in Docker Compose configurations. +* Upgraded templates to version `9.1.1`. + ## 0.9.25 (2025-03-12) * Added ready/health check for solution runner. diff --git a/docs/en/studio/version-mapping.md b/docs/en/studio/version-mapping.md index cd82da602a..88d9be25fe 100644 --- a/docs/en/studio/version-mapping.md +++ b/docs/en/studio/version-mapping.md @@ -4,6 +4,7 @@ This document provides a general overview of the relationship between various ve | **ABP Studio Version** | **ABP Version of Startup Template** | |------------------------|---------------------------| +| 0.9.26 | 9.1.1 | | 0.9.24 - 0.9.25 | 9.1.0 | | 0.9.22 - 0.9.23 | 9.0.4 | | 0.9.20 - 0.9.21 | 9.0.3 | diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js index e11a8f4d99..d232dbd28a 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js @@ -55,7 +55,7 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f function _createContainer() { _removeContainer(); - _$modalContainer = $('
'); + _$modalContainer = $('
'); var existsModals = $('[id^="Abp_Modal_"]'); if (existsModals.length) { existsModals.last().after(_$modalContainer) diff --git a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs index 6c4fcf07f9..a2c7193437 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/AbpCrudPageBase.cs @@ -357,10 +357,10 @@ public abstract class AbpCrudPageBase< } } - protected virtual Task CloseCreateModalAsync() + protected virtual async Task CloseCreateModalAsync() { + await InvokeAsync(CreateModal!.Hide); NewEntity = new TCreateViewModel(); - return InvokeAsync(CreateModal!.Hide); } protected virtual Task ClosingCreateModal(ModalClosingEventArgs eventArgs) @@ -474,11 +474,11 @@ public abstract class AbpCrudPageBase< protected virtual async Task OnCreatedEntityAsync() { - NewEntity = new TCreateViewModel(); await GetEntitiesAsync(); await InvokeAsync(CreateModal!.Hide); await Notify.Success(GetCreateMessage()); + NewEntity = new TCreateViewModel(); } protected virtual string GetCreateMessage() diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs index 63d6aa82ad..dd5df32b8a 100644 --- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs +++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs @@ -236,6 +236,8 @@ public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConvert errorInfo.ValidationErrors = GetValidationErrorInfos((exception as AbpValidationException)!); } + TryToLocalizeExceptionMessage(exception, errorInfo); + return errorInfo; } diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs index 9d1b706d8b..e5d726526b 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DistributedEvents/MongoDbContextEventInbox.cs @@ -64,7 +64,7 @@ public class MongoDbContextEventInbox : IMongoDbContextEventInb var outgoingEventRecords = await dbContext .IncomingEvents .AsQueryable() - .Where(x => !x.Processed) + .Where(x => x.Processed == false) .WhereIf(transformedFilter != null, transformedFilter!) .OrderBy(x => x.CreationTime) .Take(maxCount) diff --git a/latest-versions.json b/latest-versions.json index 340ed62653..da8c7b754d 100644 --- a/latest-versions.json +++ b/latest-versions.json @@ -1,5 +1,14 @@ [ - { + { + "version": "9.1.3", + "releaseDate": "", + "type": "stable", + "message": "", + "leptonx": { + "version": "4.1.3" + } + }, + { "version": "9.1.1", "releaseDate": "", "type": "stable", diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs index ffd189546c..231f7c56eb 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/GeneratePdf.cshtml.cs @@ -13,18 +13,15 @@ namespace Volo.Docs.Admin.Pages.Docs.Admin.Projects; public class GeneratePdfModal : DocsAdminPageModel { - protected IDocumentPdfGeneratorAppService DocumentPdfGeneratorAppService { get; } protected IProjectAppService ProjectAppService { get; } protected IProjectAdminAppService ProjectAdminAppService { get; } public GeneratePdfViewModel ViewModel { get; set; } public GeneratePdfModal( - IDocumentPdfGeneratorAppService documentPdfGeneratorAppService, IProjectAppService projectAppService, IProjectAdminAppService projectAdminAppService) { - DocumentPdfGeneratorAppService = documentPdfGeneratorAppService; ProjectAppService = projectAppService; ProjectAdminAppService = projectAdminAppService; } diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js index 7b7f4b1bbf..91015b1584 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Projects/generatePdf.js @@ -37,7 +37,7 @@ $(function () { abpHandleError : false, error: function (jqXHR) { if (jqXHR.status === 200) { - abp.message.success(l('PdfFileDeletedSuccessfully')); + abp.message.success(l('PdfFileGeneratedSuccessfully')); $btn.buttonBusy(false); $("#GenerateAndDownloadPdfBtn").buttonBusy(false); } else { diff --git a/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs b/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs index 7787185b50..3960a16179 100644 --- a/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs +++ b/modules/docs/src/Volo.Docs.Common.Application/Volo/Docs/Common/Documents/DocumentPdfGeneratorAppService.cs @@ -1,7 +1,9 @@ +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Services; using Volo.Abp.Content; +using Volo.Abp.Data; using Volo.Docs.Projects; using Volo.Docs.Projects.Pdf; @@ -24,6 +26,27 @@ public class DocumentPdfGeneratorAppService : ApplicationService, IDocumentPdfGe public virtual async Task GeneratePdfAsync(DocumentPdfGeneratorInput input) { var project = await ProjectRepository.GetAsync(input.ProjectId, includeDetails: true); + + // https://github.com/abpframework/abp/blob/e96f601641ab8a4bb7d704d3b9df2c00517d96f6/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs#L73 + var inputVersionStringBuilder = new StringBuilder(); + input.Version = inputVersionStringBuilder.Append(GetProjectVersionPrefixIfExist(project)).Append(input.Version).ToString(); return await ProjectPdfGenerator.GenerateAsync(project, input.Version, input.LanguageCode); } + + private string GetProjectVersionPrefixIfExist(Project project) + { + if (GetGithubVersionProviderSource(project) != GithubVersionProviderSource.Branches) + { + return string.Empty; + } + + return project.GetProperty("VersionBranchPrefix"); + } + + private GithubVersionProviderSource GetGithubVersionProviderSource(Project project) + { + return project.HasProperty("GithubVersionProviderSource") + ? project.GetProperty("GithubVersionProviderSource") + : GithubVersionProviderSource.Releases; + } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs index e16f81d2c9..ca5c1221ad 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs @@ -32,7 +32,8 @@ namespace Volo.Docs.FileSystem.Documents localDirectory = documentName.Substring(0, documentName.LastIndexOf('/')); } - version = File.GetLastWriteTime(path).ToString("yyyyMMddHHmmss"); + // The version is intentionally set to "1.0.0" as part of the versioning strategy for file system documents. + version = "1.0.0"; return new Document(GuidGenerator.Create(), project.Id, diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json index 73b07169f8..6715146b50 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json @@ -44,6 +44,7 @@ "Docs_Page_Title": "ABP Documentation", "Docs_Page_Description": "Access comprehensive guides and API references in the ABP Documentation, aiding in development and troubleshooting.", "GoogleTranslate": "Google Translate", - "DownloadPDF": "Download PDF" + "DownloadPDF": "Download PDF", + "PdfFileGeneratedSuccessfully": "The PDF file is generated successfully." } } diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs index b0b7b6f70f..8a48db4b4a 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Blazor/Components/FeatureManagementModal.razor.cs @@ -152,10 +152,13 @@ public partial class FeatureManagementModal protected virtual bool IsDisabled(FeatureDto feature) { - return feature.Provider.Name != ProviderName && feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName; + return feature.Value != null && + feature.Provider.Name != null && + feature.Provider.Name != ProviderName && + feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName; } - public string GetShownName(FeatureDto featureDto) + public virtual string GetShownName(FeatureDto featureDto) { return !IsDisabled(featureDto) ? featureDto.DisplayName diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs index 39bb3ad4f0..eb27c63aae 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Pages/FeatureManagement/FeatureManagementModal.cshtml.cs @@ -85,12 +85,15 @@ public class FeatureManagementModal : AbpPageModel return NoContent(); } - public bool IsDisabled(FeatureDto featureDto) + public virtual bool IsDisabled(FeatureDto feature) { - return featureDto.Provider.Name != ProviderName && featureDto.Provider.Name != DefaultValueFeatureValueProvider.ProviderName; + return feature.Value != null && + feature.Provider.Name != null && + feature.Provider.Name != ProviderName && + feature.Provider.Name != DefaultValueFeatureValueProvider.ProviderName; } - public string GetShownName(FeatureDto featureDto) + public virtual string GetShownName(FeatureDto featureDto) { return !IsDisabled(featureDto) ? featureDto.DisplayName diff --git a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts index 9e27d31c9f..cb6a216d66 100644 --- a/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts +++ b/npm/ng-packs/packages/schematics/src/commands/change-theme/index.ts @@ -15,6 +15,7 @@ import { getAppConfigPath, cleanEmptyExprFromModule, cleanEmptyExprFromProviders, + getWorkspace, } from '../../utils'; import { ThemeOptionsEnum } from './theme-options.enum'; import { findNodes, getDecoratorMetadata, getMetadataField } from '../../utils/angular/ast-utils'; @@ -82,6 +83,7 @@ function updateAppModule(selectedProject: string, targetThemeName: ThemeOptionsE insertImports(selectedProject, targetThemeName), insertProviders(selectedProject, targetThemeName), adjustProvideAbpThemeShared(appModulePath, targetThemeName), + updateIndexHtml(selectedProject, targetThemeName), formatFile(appModulePath), cleanEmptyExpressions(appModulePath, isStandalone), ]); @@ -534,3 +536,39 @@ function findProvideAbpThemeSharedCalls(source: ts.SourceFile): ts.CallExpressio return result; } + +export function updateIndexHtml(projectName: string, themeName: ThemeOptionsEnum): Rule { + return async (host: Tree) => { + const workspace = await getWorkspace(host); + const project = workspace.projects.get(projectName); + + if (!project) { + throw new Error(`Project "${projectName}" not found in workspace.`); + } + + const buildOptions = project.targets.get('build')?.options; + const indexPath = buildOptions?.index as string; + + if (!indexPath || !host.exists(indexPath)) { + throw new Error(`index.html not found at path: ${indexPath}`); + } + + const buffer = host.read(indexPath); + if (!buffer) return; + const content = buffer.toString('utf-8'); + + const loaderDiv = `
`; + let updatedContent = content; + + if (themeName === ThemeOptionsEnum.LeptonX) { + if (!content.includes(loaderDiv)) { + updatedContent = content.replace(/]*)>/i, `\n ${loaderDiv}`); + } + } else { + if (content.includes(loaderDiv)) { + updatedContent = content.replace(loaderDiv, ''); + } + } + host.overwrite(indexPath, updatedContent); + }; +}