Browse Source

Merge branch 'dev' into FeatureManagementModal

pull/22628/head
maliming 1 year ago
parent
commit
600de5ba37
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 4
      .github/workflows/angular.yml
  2. 2
      Directory.Packages.props
  3. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  4. 44
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md
  5. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/after.png
  6. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/before.png
  7. BIN
      docs/en/Blog-Posts/2025-03-27 v9_2_Preview/configure-timezone.png
  8. 1
      docs/en/cli/index.md
  9. 5
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs
  10. 15
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs
  11. 8
      framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProviderCompatible.cs
  12. 2
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  13. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs
  14. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs
  15. 22
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs
  16. 43
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs
  17. 47
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs
  18. 13
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpGuidCustomBsonTypeMapper.cs
  19. 11
      framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs
  20. 11
      framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs
  21. 37
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs
  22. 21
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json
  23. 18
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs
  24. 4
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj
  25. 2
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/AbpAspNetCoreMvcUiThemeBasicDemoModule.cs
  26. 32
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Program.cs
  27. 17
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Properties/launchSettings.json
  28. 18
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Startup.cs
  29. 17
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor
  30. 2
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.cs
  31. 17
      modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css
  32. 4
      npm/ng-packs/packages/account/config/src/providers/route.provider.ts
  33. 15
      npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html
  34. 9
      npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts
  35. 1
      npm/ng-packs/packages/theme-basic/src/lib/pipes/index.ts
  36. 20
      npm/ng-packs/packages/theme-basic/src/lib/pipes/lazy-translate.pipe.ts
  37. 2
      npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts
  38. 1
      npm/ng-packs/packages/theme-basic/src/public-api.ts

4
.github/workflows/angular.yml

@ -27,12 +27,12 @@ jobs:
with:
fetch-depth: 0
- uses: actions/cache@v2
- uses: actions/cache@v4
with:
path: 'npm/ng-packs/node_modules'
key: ${{ runner.os }}-${{ hashFiles('npm/ng-packs/yarn.lock') }}
- uses: actions/cache@v2
- uses: actions/cache@v4
with:
path: 'templates/app/angular/node_modules'
key: ${{ runner.os }}-${{ hashFiles('templates/app/angular/yarn.lock') }}

2
Directory.Packages.props

@ -119,7 +119,7 @@
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.6.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.6.0" />
<PackageVersion Include="Minio" Version="6.0.3" />
<PackageVersion Include="MongoDB.Driver" Version="3.1.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.3.0" />
<PackageVersion Include="NEST" Version="7.17.5" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Nito.AsyncEx.Context" Version="5.1.2" />

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

@ -695,7 +695,8 @@
"ModuleMainImage": "Module Main Image",
"ModuleImageInfo1": "Accepted file types : <strong> JPEG, JPG, PNG </strong>",
"ModuleImageInfo2": "Max file size : <strong> 1 MB </strong>",
"ModuleImageInfo3": "<a href='/images/example-module-img.png' download> Download a sample cover image </a>",
"ModuleImageInfo3": "Image Proportion : <strong> 1:1 </strong>",
"ModuleImageInfo4": "<a href='/images/example-module-img.png' download> Download a sample cover image </a>",
"AreYouSureToDeleteImage": "Are you sure you want to delete this image?"
}
}

44
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/POST.md

@ -25,6 +25,7 @@ Here is a brief list of titles explained in the next sections:
* Docs Module: Added "Alternative Words" to Filter Items
* Introducing the Bunny BLOB Storage Provider
* Upgraded `MongoDB.Driver` to v3.1.0
* Using Timezone Settings to Display Datetime
* Identity Pro Module: Require Email Verification to Register
* Switching users during OAuth login
@ -114,6 +115,49 @@ The upgrade provides:
We have prepared a [migration guide](https://abp.io/docs/9.2/release-info/migration-guides/MongoDB-Driver-2-to-3) for this upgrade. Please refer to it to learn more about the changes and how to migrate your application.
### Using Timezone Settings to Display Datetime
A significant enhancement in ABP v9.2 is the ability to use timezone settings to display `DateTime` values according to the user's or application's configured timezone. Introduced in `v9.2.0-rc.2`, this feature addresses the common challenge of ensuring users see accurate time information, regardless of their geographical location.
Previously, `DateTime` values were often shown in the server's timezone or in UTC, which could cause confusion for users in different timezones. With this new feature, ABP applications can now respect the configured timezone and automatically convert and display datetime values accordingly.
**Before setting the timezone:**
Consider a scenario where you have a list of books, and the `CreationTime` property is displayed without any timezone consideration. It may appear in the server's default timezone:
![before.png](before.png)
*(Screenshot of a Books page showing the CreationTime in a default timezone.)*
**Setting the timezone:**
To set the timezone, start by configuring the `AbpClockOptions` in your module's `ConfigureServices` method:
```csharp
Configure<AbpClockOptions>(options =>
{
options.Kind = DateTimeKind.Utc;
});
```
> By setting the `Kind` property of `AbpClockOptions` to `DateTimeKind.Utc`, ABP will normalize all datetime values. Times stored in the database and returned to the frontend will be in UTC. Additionally, the `SupportsMultipleTimezone` property of the `IClock` service will be **true**, and you’ll be able to configure the timezone from the UI under the _Settings_ page.
After setting the `Kind` property, you can run your application and configure the timezone from the UI under the _Settings_ page. For example, set the timezone to "Asia/Tokyo (+09:00)":
![configure-timezone.png](configure-timezone.png)
*(Screenshot showing the configuration setting for Abp.Timing.TimeZone, set to "Asia/Tokyo (+09:00)".)*
> ABP provides the `Abp.Timing.TimeZone` setting, which allows you to configure the desired timezone at the application, tenant, or user level and this setting can be configured in the UI under the _Settings_ page, inside of the _Time Zone_ tab.
**After setting the timezone:**
Once the timezone is configured, ABP automatically handles the conversion and display of `DateTime` values. The `CreationTime` on the _Books_ page will now be shown in the **"Asia/Tokyo"** timezone.
![after.png](after.png)
*(Screenshot of the _Books_ page after setting the timezone, showing the `CreationTime` adjusted to the "Asia/Tokyo" timezone.)*
This feature utilizes the `IClock` service, which provides methods like `ConvertToUserTime` and `ConvertToUtc` to facilitate timezone conversions. By configuring the `Abp.Timing.TimeZone` setting, developers can ensure a consistent and user-friendly experience across applications with a global user base.
> For a more detailed guide on implementing and using this feature, refer to the article: [Developing a Multi-Timezone Application Using the ABP Framework](https://abp.io/community/articles/developing-a-multitimezone-application-using-the-abp-framework-zk7fnrdq). It offers step-by-step instructions and examples for handling multi-timezone scenarios in ABP applications.
### Identity Pro Module: Require Email Verification to Register
[ABP Identity Pro module](https://abp.io/docs/9.2/modules/identity-pro) has been enhanced with a new feature that allows administrators to require email verification during the registration process. This security improvement ensures that users must verify their email addresses before their registration is considered complete. Enabling this feature is especially important for applications that want to prevent spam registrations.

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/after.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/before.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
docs/en/Blog-Posts/2025-03-27 v9_2_Preview/configure-timezone.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

1
docs/en/cli/index.md

@ -342,6 +342,7 @@ Note that this command can upgrade your solution from a previous version, and al
* `--solution-name` or `-sn`: Specify the solution name. Search `*.sln` files in the directory by default.
* `--check-all`: Check the new version of each package separately. Default is `false`.
* `--version` or `-v`: Specifies the version to use for update. If not specified, latest version is used.
* * `--leptonx-version` or `-lv`: Specifies the LeptonX version to use for update. If not specified, latest version or the version that is compatible with `--version` argument is used.
### clean

5
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Microsoft/Extensions/DependencyInjection/AbpBlazorWebAppServiceCollectionExtensions.cs

@ -1,3 +1,4 @@
using System;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.DependencyInjection.Extensions;
@ -19,10 +20,14 @@ public static class AbpBlazorWebAppServiceCollectionExtensions
return services;
}
[Obsolete("Use AddBlazorWebAppServices instead. See https://github.com/abpframework/abp/issues/22622")]
public static IServiceCollection AddBlazorWebAppTieredServices([NotNull] this IServiceCollection services)
{
Check.NotNull(services, nameof(services));
// Compatibility with old template code
services.AddTransient<AddBlazorWebAppTieredServicesHasBeenCalled>();
services.AddScoped<AuthenticationStateProvider, RemoteAuthenticationStateProvider>();
services.Replace(ServiceDescriptor.Singleton<IAbpAccessTokenProvider, PersistentComponentStateAbpAccessTokenProvider>());

15
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProvider.cs

@ -1,5 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp;
@ -8,21 +10,26 @@ public class RemoteAuthenticationStateProvider : AuthenticationStateProvider
{
protected ICurrentPrincipalAccessor CurrentPrincipalAccessor { get; }
protected WebAssemblyCachedApplicationConfigurationClient WebAssemblyCachedApplicationConfigurationClient { get; }
protected IServiceProvider ServiceProvider { get; }
public RemoteAuthenticationStateProvider(
ICurrentPrincipalAccessor currentPrincipalAccessor,
WebAssemblyCachedApplicationConfigurationClient webAssemblyCachedApplicationConfigurationClient)
WebAssemblyCachedApplicationConfigurationClient webAssemblyCachedApplicationConfigurationClient,
IServiceProvider serviceProvider)
{
CurrentPrincipalAccessor = currentPrincipalAccessor;
WebAssemblyCachedApplicationConfigurationClient = webAssemblyCachedApplicationConfigurationClient;
ServiceProvider = serviceProvider;
}
public async override Task<AuthenticationState> GetAuthenticationStateAsync()
{
if (CurrentPrincipalAccessor.Principal.Identity == null ||
!CurrentPrincipalAccessor.Principal.Identity.IsAuthenticated)
if (ServiceProvider.GetService<AddBlazorWebAppTieredServicesHasBeenCalled>() != null)
{
await WebAssemblyCachedApplicationConfigurationClient.InitializeAsync();
if (CurrentPrincipalAccessor.Principal.Identity == null || !CurrentPrincipalAccessor.Principal.Identity.IsAuthenticated)
{
await WebAssemblyCachedApplicationConfigurationClient.InitializeAsync();
}
}
return new AuthenticationState(CurrentPrincipalAccessor.Principal);

8
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly/Volo/Abp/AspNetCore/Components/WebAssembly/WebApp/RemoteAuthenticationStateProviderCompatible.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.AspNetCore.Components.WebAssembly.WebApp;
/// <summary>
/// This class is used to indicate that the AddBlazorWebAppTieredServices method has been called for compatibility with the old template code
/// </summary>
internal sealed class AddBlazorWebAppTieredServicesHasBeenCalled
{
}

2
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -115,7 +115,7 @@ public static class AbpApplicationBuilderExtensions
return app.UseMiddleware<AbpExceptionHandlingMiddleware>();
}
[Obsolete("Replace with AbpClaimsTransformation")]
[Obsolete("Use the TransformAbpClaims extension method from IServiceCollection instead.")]
public static IApplicationBuilder UseAbpClaimsMap(this IApplicationBuilder app)
{
return app.UseMiddleware<AbpClaimsMapMiddleware>();

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpClaimsMapMiddleware.cs

@ -11,7 +11,7 @@ using Volo.Abp.Security.Claims;
namespace Volo.Abp.AspNetCore.Security.Claims;
[Obsolete("Replace with AbpClaimsTransformation")]
[Obsolete("Use the TransformAbpClaims extension method from IServiceCollection instead.")]
public class AbpClaimsMapMiddleware : AbpMiddlewareBase, ITransientDependency
{
public async override Task InvokeAsync(HttpContext context, RequestDelegate next)

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/HelpCommand.cs

@ -68,7 +68,7 @@ public class HelpCommand : IConsoleCommand, ITransientDependency
sb.AppendLine("Command List:");
sb.AppendLine("");
foreach (var command in AbpCliOptions.Commands.ToArray().Where(NotHiddenFromCommandList))
foreach (var command in AbpCliOptions.Commands.ToArray().Where(NotHiddenFromCommandList).OrderBy(x => x.Key))
{
var method = command.Value.GetMethod("GetShortDescription", BindingFlags.Static | BindingFlags.Public);
if (method == null)

22
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/UpdateCommand.cs

@ -38,24 +38,25 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency
var directory = commandLineArgs.Options.GetOrNull(Options.SolutionPath.Short, Options.SolutionPath.Long) ??
Directory.GetCurrentDirectory();
var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
var leptonXVersion = commandLineArgs.Options.GetOrNull(Options.LeptonXVersion.Short, Options.LeptonXVersion.Long);
if (updateNuget || !updateNpm)
{
await UpdateNugetPackages(commandLineArgs, directory, version);
await UpdateNugetPackages(commandLineArgs, directory, version, leptonXVersion);
}
if (updateNpm || !updateNuget)
{
await UpdateNpmPackages(directory, version);
await UpdateNpmPackages(directory, version, leptonXVersion);
}
}
private async Task UpdateNpmPackages(string directory, string version)
private async Task UpdateNpmPackages(string directory, string version, string leptonXVersion)
{
await _npmPackagesUpdater.Update(directory, version: version);
await _npmPackagesUpdater.Update(directory, version: version, leptonXVersion: leptonXVersion);
}
private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory, string version)
private async Task UpdateNugetPackages(CommandLineArgs commandLineArgs, string directory, string version, string leptonXVersion)
{
var solutions = new List<string>();
var givenSolution = commandLineArgs.Options.GetOrNull(Options.SolutionName.Short, Options.SolutionName.Long);
@ -77,7 +78,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency
{
var solutionName = Path.GetFileName(solution).RemovePostFix(".sln");
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll, version: version);
await _nugetPackagesVersionUpdater.UpdateSolutionAsync(solution, checkAll: checkAll, version: version, leptonXVersion: leptonXVersion);
Logger.LogInformation("Volo packages are updated in {SolutionName} solution", solutionName);
}
@ -90,7 +91,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency
{
var projectName = Path.GetFileName(project).RemovePostFix(".csproj");
await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll, version: version);
await _nugetPackagesVersionUpdater.UpdateProjectAsync(project, checkAll: checkAll, version: version, leptonXVersion: leptonXVersion);
Logger.LogInformation("Volo packages are updated in {ProjectName} project", projectName);
return;
@ -120,6 +121,7 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency
sb.AppendLine("-sn|--solution-name (Specify the solution name)");
sb.AppendLine("--check-all (Check the new version of each package separately)");
sb.AppendLine("-v|--version <version> (default: latest version)");
sb.AppendLine("-lv|--leptonx-version <version> (default: latest LeptonX version)");
sb.AppendLine("");
sb.AppendLine("Some examples:");
sb.AppendLine("");
@ -167,5 +169,11 @@ public class UpdateCommand : IConsoleCommand, ITransientDependency
public const string Short = "v";
public const string Long = "version";
}
public static class LeptonXVersion
{
public const string Short = "lv";
public const string Long = "leptonx-version";
}
}
}

43
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NpmPackagesUpdater.cs

@ -50,7 +50,7 @@ public class NpmPackagesUpdater : ITransientDependency
public async Task Update(string rootDirectory, bool includePreviews = false,
bool includeReleaseCandidates = false,
bool switchToStable = false, string version = null, bool includePreRc = false)
bool switchToStable = false, string version = null, string leptonXVersion = null, bool includePreRc = false)
{
var fileList = _packageJsonFileFinder.Find(rootDirectory);
@ -80,6 +80,7 @@ public class NpmPackagesUpdater : ITransientDependency
var updated = await UpdatePackagesInFile(file, includePreviews, includeReleaseCandidates,
switchToStable,
version,
leptonXVersion,
includePreRc);
packagesUpdated.TryAdd(file, updated);
@ -162,6 +163,7 @@ public class NpmPackagesUpdater : ITransientDependency
bool includeReleaseCandidates = false,
bool switchToStable = false,
string specifiedVersion = null,
string specifiedLeptonXVersion = null,
bool includePreRc = false)
{
var packagesUpdated = false;
@ -177,7 +179,7 @@ public class NpmPackagesUpdater : ITransientDependency
foreach (var abpPackage in abpPackages)
{
var updated = await TryUpdatingPackage(filePath, abpPackage, includePreviews, includeReleaseCandidates,
switchToStable, specifiedVersion, includePreRc);
switchToStable, specifiedVersion, specifiedLeptonXVersion, includePreRc);
if (updated)
{
@ -188,7 +190,7 @@ public class NpmPackagesUpdater : ITransientDependency
var updatedContent = packageJson.ToString(Formatting.Indented);
File.WriteAllText(filePath, updatedContent);
return packagesUpdated;
}
@ -199,6 +201,7 @@ public class NpmPackagesUpdater : ITransientDependency
bool includeReleaseCandidates = false,
bool switchToStable = false,
string specifiedVersion = null,
string specifiedLeptonXVersion = null,
bool includePreRc = false)
{
var currentVersion = (string)package.Value;
@ -207,18 +210,36 @@ public class NpmPackagesUpdater : ITransientDependency
if (!specifiedVersion.IsNullOrWhiteSpace())
{
if (!SpecifiedVersionExists(specifiedVersion, package))
if (package.Name.IndexOf("leptonx", StringComparison.InvariantCultureIgnoreCase) > 0 && !specifiedLeptonXVersion.IsNullOrWhiteSpace())
{
return false;
}
if (!SpecifiedVersionExists(specifiedLeptonXVersion, package))
{
return false;
}
if (SemanticVersion.Parse(specifiedVersion) <=
SemanticVersion.Parse(currentVersion.RemovePreFix("~", "^")))
{
return false;
if (SemanticVersion.Parse(specifiedLeptonXVersion) <=
SemanticVersion.Parse(currentVersion.RemovePreFix("~", "^")))
{
return false;
}
version = specifiedLeptonXVersion.EnsureStartsWith('^');
}
else
{
if (!SpecifiedVersionExists(specifiedVersion, package))
{
return false;
}
version = specifiedVersion.EnsureStartsWith('^');
if (SemanticVersion.Parse(specifiedVersion) <=
SemanticVersion.Parse(currentVersion.RemovePreFix("~", "^")))
{
return false;
}
version = specifiedVersion.EnsureStartsWith('^');
}
}
else
{

47
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/VoloNugetPackagesVersionUpdater.cs

@ -27,7 +27,14 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
Logger = NullLogger<VoloNugetPackagesVersionUpdater>.Instance;
}
public async Task UpdateSolutionAsync(string solutionPath, bool includePreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null)
public async Task UpdateSolutionAsync(
string solutionPath,
bool includePreviews = false,
bool includeReleaseCandidates = false,
bool switchToStable = false,
bool checkAll = false,
string version = null,
string leptonXVersion = null)
{
var projectPaths = ProjectFinder.GetProjectFiles(solutionPath);
@ -58,6 +65,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
latestReleaseCandidateVersionInfo.Version,
latestVersionFromMyGet,
version,
leptonXVersion,
latestStableVersions: latestStableVersions);
fs.Seek(0, SeekOrigin.Begin);
@ -75,7 +83,14 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
}
}
public async Task UpdateProjectAsync(string projectPath, bool includeNightlyPreviews = false, bool includeReleaseCandidates = false, bool switchToStable = false, bool checkAll = false, string version = null)
public async Task UpdateProjectAsync(
string projectPath,
bool includeNightlyPreviews = false,
bool includeReleaseCandidates = false,
bool switchToStable = false,
bool checkAll = false,
string version = null,
string leptonXVersion = null)
{
if (checkAll && version.IsNullOrWhiteSpace())
{
@ -102,6 +117,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
latestReleaseCandidateVersionInfo.Version,
latestVersionFromMyGet,
version,
leptonXVersion,
latestStableVersions: latestStableVersions);
fs.Seek(0, SeekOrigin.Begin);
@ -166,6 +182,7 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
SemanticVersion latestNugetReleaseCandidateVersion = null,
string latestMyGetVersion = null,
string specifiedVersion = null,
string specifiedLeptonXVersion = null,
List<PackageVersionCheckerService.LatestStableVersionResult> latestStableVersions = null)
{
string packageId = null;
@ -222,21 +239,35 @@ public class VoloNugetPackagesVersionUpdater : ITransientDependency
var leptonXPackageVersion = latestStableVersions?
.FirstOrDefault(v => v.Version.Equals(specifiedVersion, StringComparison.InvariantCultureIgnoreCase))?.LeptonX?.Version;
if ((isLeptonXPackage && string.IsNullOrWhiteSpace(leptonXPackageVersion)) || isStudioPackage)
if ((isLeptonXPackage && string.IsNullOrWhiteSpace(leptonXPackageVersion) && specifiedLeptonXVersion.IsNullOrWhiteSpace()) || isStudioPackage)
{
Logger.LogWarning("Package: {PackageId} could not be updated. Please manually update the package version yourself to prevent version mismatches!", packageId);
continue;
}
var isLeptonXPackageWithVersion = isLeptonXPackage && !string.IsNullOrWhiteSpace(leptonXPackageVersion);
if (isLeptonXPackageWithVersion || await SpecifiedVersionExists(specifiedVersion, packageId))
if (isLeptonXPackage)
{
TryUpdatingPackage(isLeptonXPackageWithVersion ? leptonXPackageVersion : specifiedVersion);
var isLeptonXPackageWithVersion = isLeptonXPackage && !string.IsNullOrWhiteSpace(leptonXPackageVersion);
if (isLeptonXPackageWithVersion || await SpecifiedVersionExists(specifiedLeptonXVersion, packageId))
{
TryUpdatingPackage(specifiedLeptonXVersion ?? leptonXPackageVersion);
}
else
{
Logger.LogWarning($"Package \"{packageId}\" specified version v{specifiedLeptonXVersion} does not exist!");
}
}
else
{
Logger.LogWarning("Package \"{PackageId}\" specified version v{SpecifiedVersion} does not exist!", packageId, specifiedVersion);
if (await SpecifiedVersionExists(specifiedVersion, packageId))
{
TryUpdatingPackage(specifiedVersion);
}
else
{
Logger.LogWarning($"Package \"{packageId}\" specified version v{specifiedVersion} does not exist!");
}
}
void TryUpdatingPackage(string versionToUpdate)

13
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpGuidCustomBsonTypeMapper.cs

@ -0,0 +1,13 @@
using System;
using MongoDB.Bson;
namespace Volo.Abp.MongoDB;
public class AbpGuidCustomBsonTypeMapper : ICustomBsonTypeMapper
{
public bool TryMapToBsonValue(object value, out BsonValue bsonValue)
{
bsonValue = new BsonBinaryData((Guid)value, GuidRepresentation.Standard);
return true;
}
}

11
framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/AbpMongoDbModule.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
@ -16,6 +17,12 @@ namespace Volo.Abp.MongoDB;
[DependsOn(typeof(AbpDddDomainModule))]
public class AbpMongoDbModule : AbpModule
{
static AbpMongoDbModule()
{
BsonSerializer.TryRegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
BsonTypeMapper.RegisterCustomTypeMapper(typeof(Guid), new AbpGuidCustomBsonTypeMapper());
}
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddConventionalRegistrar(new AbpMongoDbConventionalRegistrar());
@ -23,8 +30,6 @@ public class AbpMongoDbModule : AbpModule
public override void ConfigureServices(ServiceConfigurationContext context)
{
BsonSerializer.TryRegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
context.Services.TryAddTransient(
typeof(IMongoDbContextProvider<>),
typeof(UnitOfWorkMongoDbContextProvider<>)

11
framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/Repositories/Repository_Basic_Tests.cs

@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver.Linq;
using Shouldly;
using Volo.Abp.Data;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.TestApp;
using Volo.Abp.TestApp.Domain;
@ -52,10 +53,12 @@ public class Repository_Basic_Tests : Repository_Basic_Tests<AbpMongoDbTestModul
}
[Fact]
public override async Task InsertAsync()
public async override Task InsertAsync()
{
var person = new Person(Guid.NewGuid(), "New Person", 35);
person.Phones.Add(new Phone(person.Id, "1234567890"));
person.SetProperty("test-guid-property", person.Id);
person.SetProperty("test-nullable-guid-property", (Guid?)person.Id);
await PersonRepository.InsertAsync(person);
@ -64,15 +67,17 @@ public class Repository_Basic_Tests : Repository_Basic_Tests<AbpMongoDbTestModul
person.Name.ShouldBe("New Person");
person.Phones.Count.ShouldBe(1);
person.Phones.Any(p => p.PersonId == person.Id && p.Number == "1234567890").ShouldBeTrue();
person.GetProperty<Guid>("test-guid-property").ShouldBe(person.Id);
person.GetProperty<Guid?>("test-nullable-guid-property").ShouldBe(person.Id);
}
[Fact]
public async Task Filter_Case_Insensitive()
{
(await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "ISTANBUL").ShouldBeNull();
(await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "istanbul").ShouldBeNull();
(await CityRepository.GetQueryableAsync()).FirstOrDefault(c => c.Name == "Istanbul").ShouldNotBeNull();
(await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "douglas").ShouldNotBeNull();
(await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "DOUGLAS").ShouldNotBeNull();
(await PersonRepository.GetQueryableAsync()).FirstOrDefault(p => p.Name == "Douglas").ShouldNotBeNull();

37
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Program.cs

@ -1,31 +1,42 @@
using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo;
public class Program
{
public static int Main(string[] args)
public async static Task<int> Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug() //TODO: Should be configurable!
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.File("Logs/logs.txt")
.WriteTo.Async(c => c.Console())
.CreateLogger();
try
{
Log.Information("Starting web host.");
CreateHostBuilder(args).Build().Run();
var builder = WebApplication.CreateBuilder(args);
builder.Host.AddAppSettingsSecretsJson()
.UseAutofac()
.UseSerilog();
await builder.AddApplicationAsync<AbpAspNetCoreMvcUiBootstrapDemoModule>();
var app = builder.Build();
await app.InitializeApplicationAsync();
await app.RunAsync();
return 0;
}
catch (Exception ex)
{
if (ex is HostAbortedException)
{
throw;
}
Log.Fatal(ex, "Host terminated unexpectedly!");
return 1;
}
@ -34,14 +45,4 @@ public class Program
Log.CloseAndFlush();
}
}
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac()
.UseSerilog();
}

21
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Properties/launchSettings.json

@ -1,27 +1,12 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:51339",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.AbpIo.Commercial.Web": {
"Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"applicationUrl": "https://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
}

18
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Startup.cs

@ -1,18 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AbpAspNetCoreMvcUiBootstrapDemoModule>();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
}

4
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj

@ -10,7 +10,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" />
<PackageReference Include="Serilog.AspNetCore" />
<PackageReference Include="Serilog.Sinks.File" />
<PackageReference Include="Serilog.Sinks.Async" />
</ItemGroup>
<ItemGroup>
@ -23,5 +23,5 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

2
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/AbpAspNetCoreMvcUiThemeBasicDemoModule.cs

@ -55,8 +55,8 @@ public class AbpAspNetCoreMvcUiThemeBasicDemoModule : AbpModule
app.UseDeveloperExceptionPage();
}
app.MapAbpStaticAssets();
app.UseRouting();
app.MapAbpStaticAssets();
app.UseConfiguredEndpoints();
}
}

32
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Program.cs

@ -1,30 +1,42 @@
using System;
using Microsoft.AspNetCore.Hosting;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo;
public class Program
{
public static int Main(string[] args)
public async static Task<int> Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Async(c => c.File("Logs/logs.txt"))
.WriteTo.Async(c => c.Console())
.CreateLogger();
try
{
Log.Information("Starting web host.");
CreateHostBuilder(args).Build().Run();
var builder = WebApplication.CreateBuilder(args);
builder.Host.AddAppSettingsSecretsJson()
.UseAutofac()
.UseSerilog();
await builder.AddApplicationAsync<AbpAspNetCoreMvcUiThemeBasicDemoModule>();
var app = builder.Build();
await app.InitializeApplicationAsync();
await app.RunAsync();
return 0;
}
catch (Exception ex)
{
if (ex is HostAbortedException)
{
throw;
}
Log.Fatal(ex, "Host terminated unexpectedly!");
return 1;
}
@ -33,14 +45,4 @@ public class Program
Log.CloseAndFlush();
}
}
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseAutofac()
.UseSerilog();
}

17
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Properties/launchSettings.json

@ -1,24 +1,9 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:61659",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"applicationUrl": "https://localhost:5001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}

18
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Startup.cs

@ -1,18 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<AbpAspNetCoreMvcUiThemeBasicDemoModule>();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.InitializeApplication();
}
}

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

@ -37,22 +37,25 @@
@if (_groups != null && _groups.Any())
{
<div class="lpx-scroll-pills-container" >
<Tabs @key="_groups" TabPosition="TabPosition.Start" Pills="true" SelectedTab="@_selectedTabName" SelectedTabChanged="@OnSelectedTabChangedAsync">
<Tabs @key="_groups"
VerticalItemsColumnSize="ColumnSize.Is4.OnDesktop"
TabPosition="TabPosition.Start"
Pills="true"
SelectedTab="@_selectedTabName"
SelectedTabChanged="@OnSelectedTabChangedAsync">
<Items>
@foreach (var group in _groups)
{
<Tab Name="@GetNormalizedGroupName(group.Name)">
@if (group.Permissions.Any(x => x.IsGranted))
{
<span>
<b>@group.DisplayName ( @(group.Permissions.Count(x => x.IsGranted)) )</b>
</span>
<b>@group.DisplayName (@(group.Permissions.Count(x => x.IsGranted)))</b>
}
else
{
<span>
@group.DisplayName ( @(group.Permissions.Count(x => x.IsGranted)) )
</span>
<small>
@group.DisplayName (@(group.Permissions.Count(x => x.IsGranted)))
</small>
}
</Tab>
}

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

@ -58,7 +58,7 @@ public partial class PermissionManagementModal
var result = await PermissionAppService.GetAsync(_providerName, _providerKey);
_entityDisplayName = entityDisplayName ?? result.EntityDisplayName;
_allGroups = result.Groups;
_allGroups = result.Groups.OrderBy(x => x.DisplayName).ToList();
_groups = _allGroups.ToList();
NormalizePermissionGroup();

17
modules/permission-management/src/Volo.Abp.PermissionManagement.Blazor/Components/PermissionManagementModal.razor.css

@ -15,7 +15,7 @@ fieldset legend {
}
::deep .lpx-scroll-pills-container ul li {
border: 1px solid #e8eef3;
border: 1px solid var(--lpx-border-color);
margin-bottom: 10px;
border-radius: 10px;
}
@ -26,6 +26,15 @@ fieldset legend {
background-color: #6c5dd3 !important;
}
::deep .lpx-theme-dark .lpx-scroll-pills-container ul li {
border: 1px solid #23262a;
}
::deep .nav-pills .nav-link {
background: none;
border: 0;
border-radius: var(--bs-nav-pills-border-radius);
}
::deep .nav-pills .nav-link:disabled {
color: var(--bs-nav-link-disabled-color);
background-color: transparent;
border-color: transparent;
}

4
npm/ng-packs/packages/account/config/src/providers/route.provider.ts

@ -24,12 +24,14 @@ export function configureRoutes() {
path: '/account/login',
name: eAccountRouteNames.Login,
parentName: eAccountRouteNames.Account,
layout: eLayoutType.account,
order: 1,
},
{
path: '/account/register',
name: eAccountRouteNames.Register,
parentName: eAccountRouteNames.Account,
layout: eLayoutType.account,
order: 2,
},
{
@ -45,12 +47,14 @@ export function configureRoutes() {
path: '/account/forgot-password',
parentName: eAccountRouteNames.Account,
name: eAccountRouteNames.ForgotPassword,
layout: eLayoutType.account,
invisible: true,
},
{
path: '/account/reset-password',
parentName: eAccountRouteNames.Account,
name: eAccountRouteNames.ResetPassword,
layout: eLayoutType.account,
invisible: true,
},
]);

15
npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.html

@ -3,8 +3,7 @@
<ng-container
[ngTemplateOutlet]="isDropdown(route) ? dropdownLink : defaultLink"
[ngTemplateOutletContext]="{ $implicit: route }"
>
</ng-container>
/>
}
<ng-template #defaultLink let-route>
@ -13,7 +12,7 @@
@if (route.iconClass) {
<i [ngClass]="route.iconClass"></i>
}
{{ route.name | abpLocalization }}
{{ route.name | abpLazyTranslate | async }}
</a>
</li>
</ng-template>
@ -40,7 +39,7 @@
@if (route.iconClass) {
<i [ngClass]="route.iconClass"></i>
}
{{ route.name | abpLocalization }}
{{ route.name | abpLazyTranslate | async }}
</a>
<div
#routeContainer
@ -48,9 +47,7 @@
(click)="$event.preventDefault(); $event.stopPropagation()"
[class.d-block]="smallScreen && rootDropdownExpand[route.name]"
>
<ng-container
*ngTemplateOutlet="forTemplate; context: { $implicit: route }"
></ng-container>
<ng-container *ngTemplateOutlet="forTemplate; context: { $implicit: route }" />
</div>
</li>
}
@ -61,7 +58,7 @@
<ng-template
[ngTemplateOutlet]="child.children?.length ? dropdownChild : defaultChild"
[ngTemplateOutletContext]="{ $implicit: child }"
></ng-template>
/>
}
</ng-template>
@ -105,7 +102,7 @@
class="dropdown-menu dropdown-menu-start border-0 shadow-sm"
[class.d-block]="smallScreen && dropdownSubmenu.isOpen()"
>
<ng-container *ngTemplateOutlet="forTemplate; context: { $implicit: child }"></ng-container>
<ng-container *ngTemplateOutlet="forTemplate; context: { $implicit: child }" />
</div>
</div>
</ng-template>

9
npm/ng-packs/packages/theme-basic/src/lib/components/routes/routes.component.ts

@ -2,6 +2,7 @@ import { ABP, RoutesService, TreeNode } from '@abp/ng.core';
import {
Component,
ElementRef,
inject,
Input,
QueryList,
Renderer2,
@ -15,6 +16,9 @@ import {
templateUrl: 'routes.component.html',
})
export class RoutesComponent {
public readonly routesService = inject(RoutesService);
protected renderer = inject(Renderer2);
@Input() smallScreen?: boolean;
@ViewChildren('childrenContainer') childrenContainers!: QueryList<ElementRef<HTMLDivElement>>;
@ -23,11 +27,6 @@ export class RoutesComponent {
trackByFn: TrackByFunction<TreeNode<ABP.Route>> = (_, item) => item.name;
constructor(
public readonly routesService: RoutesService,
protected renderer: Renderer2,
) {}
isDropdown(node: TreeNode<ABP.Route>) {
return !node?.isLeaf || this.routesService.hasChildren(node.name);
}

1
npm/ng-packs/packages/theme-basic/src/lib/pipes/index.ts

@ -0,0 +1 @@
export * from './lazy-translate.pipe';

20
npm/ng-packs/packages/theme-basic/src/lib/pipes/lazy-translate.pipe.ts

@ -0,0 +1,20 @@
import { LocalizationService, ConfigStateService } from '@abp/ng.core';
import { inject, Pipe, PipeTransform } from '@angular/core';
import { Observable, filter, take, switchMap, shareReplay } from 'rxjs';
@Pipe({
name: 'abpLazyTranslate',
})
export class LazyTranslatePipe implements PipeTransform {
private localizationService = inject(LocalizationService);
private configStateService = inject(ConfigStateService);
transform(key: string): Observable<string> {
return this.configStateService.getAll$().pipe(
filter(config => !!config.localization),
take(1),
switchMap(() => this.localizationService.get(key)),
shareReplay({ bufferSize: 1, refCount: true }),
);
}
}

2
npm/ng-packs/packages/theme-basic/src/lib/theme-basic.module.ts

@ -16,6 +16,7 @@ import { PageAlertContainerComponent } from './components/page-alert-container/p
import { RoutesComponent } from './components/routes/routes.component';
import { ValidationErrorComponent } from './components/validation-error/validation-error.component';
import { provideThemeBasicConfig } from './providers';
import { LazyTranslatePipe } from './pipes';
export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, EmptyLayoutComponent];
@ -48,6 +49,7 @@ export const LAYOUTS = [ApplicationLayoutComponent, AccountLayoutComponent, Empt
NgbCollapseModule,
NgbDropdownModule,
NgxValidateCoreModule,
LazyTranslatePipe,
],
})
export class BaseThemeBasicModule {}

1
npm/ng-packs/packages/theme-basic/src/public-api.ts

@ -6,6 +6,7 @@ export * from './lib/components';
export * from './lib/enums';
export * from './lib/handlers';
export * from './lib/models';
export * from './lib/pipes';
export * from './lib/providers';
export * from './lib/theme-basic.module';
export * from './lib/tokens';

Loading…
Cancel
Save