Browse Source

Merge branch 'dev' into cms-kit-enhancements

pull/17925/head
Enis Necipoglu 3 years ago
parent
commit
d12e020c97
No known key found for this signature in database GPG Key ID: 1EC55E13241E1680
  1. 3
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  2. 8
      abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json
  3. 1
      docs/en/Deployment/Index.md
  4. 34
      docs/en/Deployment/SSL.md
  5. 2
      docs/en/Getting-Started-Running-Solution-Single-Layer.md
  6. 4
      docs/en/Getting-Started-Running-Solution.md
  7. 29
      docs/en/Image-Manipulation.md
  8. 5
      docs/en/Migration-Guides/Abp-7_3.md
  9. 3
      docs/en/Migration-Guides/Abp-7_4.md
  10. 10
      docs/en/Modules/Cms-Kit/Pages.md
  11. 2
      docs/en/Tutorials/Part-1.md
  12. 2
      docs/en/Tutorials/Todo/Index.md
  13. 2
      docs/en/Tutorials/Todo/Single-Layer/Index.md
  14. 4
      docs/en/docs-nav.json
  15. BIN
      docs/en/images/cmskit-module-pages-page.png
  16. 9
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js
  17. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs
  18. 6
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs
  19. 5
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateRemoveMongodbCollectionFixtureStep.cs
  20. 67
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs
  21. 34
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs
  22. 27
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs
  23. 8
      framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeHelper.cs
  24. 23
      framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageCompressor.cs
  25. 23
      framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageResizer.cs
  26. 9
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json
  27. 9
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json
  28. 2
      modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json
  29. 112
      npm/ng-packs/migrations.json
  30. 128
      npm/ng-packs/package.json
  31. 2
      npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts
  32. 17
      npm/ng-packs/packages/core/src/lib/models/dtos.ts
  33. 1
      npm/ng-packs/packages/core/src/lib/utils/file-utils.ts
  34. 8
      npm/ng-packs/packages/schematics/package.json
  35. 2
      npm/ng-packs/packages/schematics/src/constants/system-types.ts
  36. 129
      npm/ng-packs/packages/schematics/src/tests/parse-generic-type.spec.ts
  37. 35
      npm/ng-packs/packages/schematics/src/utils/model.ts
  38. 31
      npm/ng-packs/packages/schematics/src/utils/tree.ts
  39. 1
      npm/ng-packs/packages/theme-basic/src/lib/components/empty-layout/empty-layout.component.ts
  40. 6
      npm/ng-packs/packages/theme-shared/src/lib/services/status-code-error-handler.service.ts
  41. 42
      templates/app-nolayers/angular/package.json
  42. 40
      templates/app/angular/package.json
  43. 46
      templates/module/angular/package.json

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

@ -559,6 +559,7 @@
"SessionDate": "Session Date",
"AddSession": "Add Session",
"AddSponsor": "Add Sponsor",
"SponsorLogo": "Sponsor Logo"
"SponsorLogo": "Sponsor Logo",
"RegistrationUrl": "Registration Url"
}
}

8
abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/en.json

@ -242,6 +242,12 @@
"{0}Posts": "{0} Posts",
"LATESTPOSTS": "LATEST POSTS",
"NoContributorsFound": "No contributors found!",
"LatestPost": "Latest post"
"LatestPost": "Latest post",
"MEMBERSINCE{0}": "MEMBER SINCE {0}",
"CopyLink": "Copy Link",
"ShareOnTwitter": "Share on Twitter",
"ShareOnLinkedIn": "Share on LinkedIn",
"MoreFrom{0}": "More from {0}",
"SeeAllFrom{0}": "See all from {0}"
}
}

1
docs/en/Deployment/Index.md

@ -6,6 +6,7 @@ However, there are some topics that you should care about when you are deploying
## Guides
* [Configuring SSL certificate(HTTPS)](SSL.md): Explains how to configure SSL certificate(HTTPS) for your application.
* [Configuring for OpenIddict](Configuring-OpenIddict.md): Notes for some essential configurations for OpenIddict.
* [Configuring for Production](Configuring-Production.md): Notes for some essential configurations for production environments.
* [Optimization for Production](Optimizing-Production.md): Tips and suggestions for optimizing your application on production environments.

34
docs/en/Deployment/SSL.md

@ -0,0 +1,34 @@
# Configuring Configuring SSL certificate(HTTPS)
A website needs an SSL certificate in order to keep user data secure, verify ownership of the website, prevent attackers from creating a fake version of the site, and gain user trust.
This document introduces how to get and use SSL certificate(HTTPS) for your application.
## Get a SSL Certificate from a Certificate Authority
You can get a SSL certificate from a certificate authority (CA) such as [Let's Encrypt](https://letsencrypt.org/) or [Cloudflare](https://www.cloudflare.com/learning/ssl/what-is-an-ssl-certificate/) and so on.
Once you have a certificate, you need to configure your web server to use it. The following references show how to configure your web server to use a certificate.
* [Host ASP.NET Core on Linux with Apache: HTTPS configuration](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache)
* [Host ASP.NET Core on Linux with Nginx: HTTPS configuration](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx)
* [How to Set Up SSL on IIS 7 or later](https://learn.microsoft.com/en-us/iis/manage/configuring-security/how-to-set-up-ssl-on-iis)
## Create a Self-Signed Certificate
You can create a self-signed certificate for testing purposes or internal use.
There is an article about [how to create a self-signed certificate](https://learn.microsoft.com/en-us/dotnet/core/additional-tools/self-signed-certificates-guide), If you are using IIS, you can use the following this document to [obtain a Certificate](https://learn.microsoft.com/en-us/iis/manage/configuring-security/how-to-set-up-ssl-on-iis#obtain-a-certificate)
## Common Problems
### The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot
This error may occur when using IIS. You need to trust your certificate by `Manage computer certificates`.
## References
* [ABP commercial IIS Deployment](https://docs.abp.io/en/commercial/latest/startup-templates/application/deployment-iis)
* [HTTPS in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl)
* [Let's Encrypt](https://letsencrypt.org/getting-started)
* [Cloudflare's Free SSL / TLS](https://www.cloudflare.com/application-services/products/ssl/)

2
docs/en/Getting-Started-Running-Solution-Single-Layer.md

@ -66,7 +66,7 @@ abp install-libs
> We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet.
{{if UI=="Blazor" || UI="BlazorServer"}}
{{if UI=="Blazor" || UI=="BlazorServer"}}
### Bundling and Minification

4
docs/en/Getting-Started-Running-Solution.md

@ -105,7 +105,7 @@ abp install-libs
> We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet.
{{if UI=="Blazor" || UI="BlazorServer"}}
{{if UI=="Blazor" || UI=="BlazorServer"}}
### Bundling and Minification
@ -125,6 +125,8 @@ abp bundle
{{ if UI == "MVC" || UI == "BlazorServer" }}
> **Note**: Before starting the application, run `abp install-libs` command in your Web directory to restore the client-side libraries. This will populate the `libs` folder.
{{ 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.

29
docs/en/Image-Manipulation.md

@ -76,8 +76,8 @@ public interface IImageResizer
**Example usage:**
```csharp
var result = await _imageResizer.ResizeAsync(
stream, /* A stream object that represents an image */
var resizeResult = await _imageResizer.ResizeAsync(
imageStream, /* A stream object that represents an image */
new ImageResizeArgs
{
Width = 100,
@ -88,6 +88,16 @@ var result = await _imageResizer.ResizeAsync(
);
```
> **Note:** If `resizeResult.State` returns 'Done', then it means that the resize operation was successful. However, if it returns any other state than 'Done', the stream you're using might be corrupted. Therefore, you can perform a check like the one below and assign the correct stream to the main stream:
```csharp
if (resizeResult.Result is not null && imageStream != resizeResult.Result && resizeResult.Result.CanRead)
{
await imageStream.DisposeAsync();
imageStream = resizeResult.Result;
}
```
> You can use `MimeTypes.Image.Jpeg` constant instead of the `image/jpeg` magic string used in that example.
### ImageResizeArgs
@ -170,12 +180,23 @@ public interface IImageCompressor
**Example usage:**
```csharp
var result = await _imageCompressor.CompressAsync(
stream, /* A stream object that represents an image */
var compressResult = await _imageCompressor.CompressAsync(
imageStream, /* A stream object that represents an image */
mimeType: "image/jpeg"
);
```
> **Note:** If `compressResult.State` returns 'Done', then it means that the compression operation was successful. However, if it returns any other state than 'Done', the stream you're using might be corrupted. Therefore, you can perform a check like the one below and assign the correct stream to the main stream:
```csharp
if (compressResult.Result is not null && imageStream != compressResult.Result && compressResult.Result.CanRead)
{
await imageStream.DisposeAsync();
imageStream = compressResult.Result;
}
```
### ImageCompressResult
The `ImageCompressResult` is a generic class that is used to return the result of the image compression operations. It has the following properties:

5
docs/en/Migration-Guides/Abp-7_3.md

@ -25,4 +25,7 @@ This feature comes with a small restriction. If you use any C# code used inside
For example, `<script @string.Empty></script>` will no longer work. However, you can use the C# code for an attribute of script tag, for example, `<script src="@string.Empty"></script>` is completely valid and won't cause any problem.
> Note: You should not use any C# code used inside the script tag, even if you don't use this feature. Because it might cause errors.
> Note: You should not use any C# code used inside the script tag, even if you don't use this feature. Because it might cause errors.
## Angular UI
We would like to inform you that ABP Framework version 7.3 uses Angular version 16. Please migrate your applications to Angular 16. [Update angular](https://update.angular.io/)

3
docs/en/Migration-Guides/Abp-7_4.md

@ -114,3 +114,6 @@ The following packages are included in the templates by default:
### Bumped the `Microsoft.AspNetCore.Components.*` dependency to `7.0.10`
In this version, the `Microsoft.AspNetCore.Components.*` dependencies are upgraded to the `7.0.10` version. Therefore, you should upgrade the `Microsoft.AspNetCore.Components.Web` and `Microsoft.AspNetCore.Components.WebAssembly` packages to `7.0.10` in your `Blazor.csproj` file.
## Angular UI
We would like to inform you that ABP Framework version 7.4 uses Angular version 16. Please migrate your applications to Angular 16. [Update angular](https://update.angular.io/)

10
docs/en/Modules/Cms-Kit/Pages.md

@ -22,13 +22,13 @@ CMS Kit module admin side adds the following items to the main menu, under the *
#### Page Management
Pages page is used to manage dynamic pages in the system.
**Pages** page is used to manage dynamic pages in the system. You can create/edit pages with dynamic routes and contents on this page:
![pages-page](../../images/cmskit-module-pages-page.png)
![pages-edit](../../images/cmskit-module-pages-edit.png)
You can create or edit an existing page on this page.
After you have created pages, you can set one of them as a *home page*. Then, whenever anyone navigates to your application's homepage, they see the dynamic content of the page that you have defined on this page.
![pages-edit](../../images/cmskit-module-pages-edit.png)
![pages-page](../../images/cmskit-module-pages-page.png)
When you create a page, you can access the created page via `/{slug}` URL.
Also when you create a page, you can access the created page via `/{slug}` URL.

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

@ -66,7 +66,7 @@ abp install-libs
> We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet.
{{if UI=="Blazor" || UI="BlazorServer"}}
{{if UI=="Blazor" || UI=="BlazorServer"}}
### Bundling and Minification

2
docs/en/Tutorials/Todo/Index.md

@ -113,7 +113,7 @@ abp install-libs
> We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet.
{{if UI=="Blazor" || UI="BlazorServer"}}
{{if UI=="Blazor" || UI=="BlazorServer"}}
#### Bundling and Minification

2
docs/en/Tutorials/Todo/Single-Layer/Index.md

@ -117,7 +117,7 @@ abp install-libs
> We suggest you install [Yarn](https://classic.yarnpkg.com/) to prevent possible package inconsistencies, if you haven't installed it yet.
{{if UI=="Blazor" || UI="BlazorServer"}}
{{if UI=="Blazor" || UI=="BlazorServer"}}
#### Bundling and Minification

4
docs/en/docs-nav.json

@ -1363,6 +1363,10 @@
"text": "Deployment",
"path": "Deployment/Index.md",
"items": [
{
"text": "Configuring SSL certificate(HTTPS)",
"path": "Deployment/SSL.md"
},
{
"text": "Configuring OpenIddict",
"path": "Deployment/Configuring-OpenIddict.md"

BIN
docs/en/images/cmskit-module-pages-page.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

9
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/bootstrap/modal-manager.js

@ -134,8 +134,15 @@ $.validator.defaults.ignore = ''; //TODO: Would be better if we can apply only f
_args = args || {};
var argsWithoutFunc = {};
for (a in _args) {
if (_args.hasOwnProperty(a) && typeof _args[a] !== 'function') {
argsWithoutFunc[a] = _args[a];
}
}
_createContainer(_modalId)
.load(options.viewUrl, $.param(_args), function (response, status, xhr) {
.load(options.viewUrl, $.param(argsWithoutFunc), function (response, status, xhr) {
if (status === "error") {
//TODO: Handle!
return;

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AspNetCoreApiDescriptionModelProvider.cs

@ -214,6 +214,8 @@ public class AspNetCoreApiDescriptionModelProvider : IApiDescriptionModelProvide
type == typeof(void) ||
type == typeof(Enum) ||
type == typeof(ValueType) ||
type == typeof(DateOnly) ||
type == typeof(TimeOnly) ||
TypeHelper.IsPrimitiveExtended(type))
{
return;

6
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateInfo.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.Cli.ProjectBuilding.Templates.App;
using Volo.Abp.Cli.ProjectBuilding.Templates;
namespace Volo.Abp.Cli.ProjectBuilding.Building;
@ -43,4 +44,9 @@ public abstract class TemplateInfo
{
return Name.EndsWith("-pro", StringComparison.OrdinalIgnoreCase);
}
public bool IsNoLayer()
{
return Name is AppNoLayersTemplate.TemplateName or AppNoLayersProTemplate.TemplateName;
}
}

5
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/App/AppTemplateRemoveMongodbCollectionFixtureStep.cs

@ -8,6 +8,11 @@ public class AppTemplateRemoveMongodbCollectionFixtureStep : ProjectBuildPipelin
{
public override void Execute(ProjectBuildContext context)
{
if (context.Template.IsNoLayer())
{
return;
}
//MyCompanyName.MyProjectName.Application.Tests
RemoveFile(context, "/aspnet-core/test/MyCompanyName.MyProjectName.Application.Tests/MyProjectNameApplicationCollection.cs");
RemoveKeyword(context,

67
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/AngularSourceCodeAdder.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
@ -71,6 +72,7 @@ public class AngularSourceCodeAdder : ITransientDependency
{
await AddProjectToEnvironmentTsAsync(angularPath, moduleName);
await AddProjectToAppModuleTsAsync(angularPath, moduleName);
await AddProjectToAppRoutingTsAsync(angularPath, moduleName);
}
private async Task AddProjectsToAngularJsonAsync(string angularPath, List<string> projects)
@ -244,15 +246,15 @@ public class AngularSourceCodeAdder : ITransientDependency
{
return;
}
var fileContent = File.ReadAllText(filePath);
fileContent = Regex.Replace(fileContent, @"apis\s*:\s*{",
"apis: {"+ Environment.NewLine +
" " + moduleName.Split(".").Last() + ": {"+ Environment.NewLine +
" rootNamespace: '" + moduleName + "',"+ Environment.NewLine +
fileContent = Regex.Replace(fileContent, @"apis\s*:\s*{",
"apis: {" + Environment.NewLine +
" " + moduleName.Split(".").Last() + ": {" + Environment.NewLine +
" rootNamespace: '" + moduleName + "'," + Environment.NewLine +
" },");
File.WriteAllText(filePath, fileContent);
}
@ -264,23 +266,56 @@ public class AngularSourceCodeAdder : ITransientDependency
{
return;
}
var fileContent = File.ReadAllText(filePath);
var moduleNameAsConfigPath = moduleName.ToKebabCase();
if (moduleName.Contains("."))
{
var moduleNameSplited = moduleName.Split(".");
moduleNameAsConfigPath = moduleNameSplited.Take(moduleNameSplited.Length-1).JoinAsString(".").ToKebabCase() + "/" + moduleNameSplited.Last().ToKebabCase();
moduleNameAsConfigPath = moduleNameSplited.Take(moduleNameSplited.Length - 1).JoinAsString(".").ToKebabCase() + "/" + moduleNameSplited.Last().ToKebabCase();
}
fileContent = "import { "+moduleName.Split(".").Last()+"ConfigModule } from '@"+moduleNameAsConfigPath+"/config';" + Environment.NewLine + fileContent;
fileContent = Regex.Replace(fileContent, "imports\\s*:\\s*\\[",
"imports: ["+ Environment.NewLine +
fileContent = "import { " + moduleName.Split(".").Last() + "ConfigModule } from '@" + moduleNameAsConfigPath + "/config';" + Environment.NewLine + fileContent;
fileContent = Regex.Replace(fileContent, "imports\\s*:\\s*\\[",
"imports: [" + Environment.NewLine +
" " + moduleName.Split(".").Last() + "ConfigModule.forRoot(),");
File.WriteAllText(filePath, fileContent);
}
private async Task AddProjectToAppRoutingTsAsync(string angularPath, string moduleName)
{
string filePath = Path.Combine(angularPath, "src", "app", "app-routing.module.ts");
if (!File.Exists(filePath))
{
return;
}
string fileContent = File.ReadAllText(filePath);
string moduleNameAsConfigPath = moduleName.ToKebabCase();
string path = moduleName.ToKebabCase();
if (moduleName.Contains("."))
{
var moduleNameSplitted = moduleName.Split(".");
moduleNameAsConfigPath = moduleNameSplitted.Take(moduleNameSplitted.Length - 1).JoinAsString(".").ToKebabCase() + "/" + moduleNameSplitted.Last().ToKebabCase();
path = $"{moduleNameSplitted.Last().ToKebabCase()}";
}
string pattern = "Routes\\s*=\\s*\\[";
string newContent = $@"Routes = [
{{
path: '{path}',
loadChildren: () => import('@{moduleNameAsConfigPath}')
.then(m => m.{(moduleName.Split(".").Length > 1 ? moduleName.Split(".")[1] : moduleName)}Module.forLazy())
}},
";
fileContent = Regex.Replace(fileContent, pattern, newContent);
File.WriteAllText(filePath, fileContent);
}
@ -311,7 +346,7 @@ public class AngularSourceCodeAdder : ITransientDependency
{
Directory.Delete(vscodeFolder, true);
}
var projectsInFolder = Directory.GetDirectories(folder);
if (projectsInFolder.Length == 1 && Path.GetFileName(projectsInFolder[0]) == "projects")
@ -360,7 +395,7 @@ public class AngularSourceCodeAdder : ITransientDependency
return projects;
}
private async Task<string> GetProjectPackageNameAsync(string angularProjectsPath, string project)
{
var packageJsonPath = Path.Combine(angularProjectsPath, project, "package.json");

34
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs

@ -538,18 +538,9 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
usingNamespaceList?.AddIfNotContains($"using {GetTypeNamespace(typeName)};");
return NormalizeTypeName(typeName.Split(".").Last());
}
if (typeName.Contains("<") && typeName.Contains(">"))
{
var left = typeName.IndexOf("<", StringComparison.Ordinal);
var right = typeName.LastIndexOf(">", StringComparison.Ordinal);
var genericTypes = typeName.Substring(left + 1, right - left - 1);
foreach (var genericType in genericTypes.Split(",").Where(x => x.Contains(".")))
{
usingNamespaceList?.AddIfNotContains($"using {GetTypeNamespace(genericType)};");
}
}
AddGenericTypeUsingNamespace(typeName, usingNamespaceList);
var type = new StringBuilder();
var s1 = typeName.Split("<");
for (var i = 0; i < s1.Length; i++)
@ -579,6 +570,25 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
return type.ToString();
}
private static void AddGenericTypeUsingNamespace(string typeFullName, List<string> usingNamespaceList)
{
if(!typeFullName.Contains("<"))
{
usingNamespaceList.AddIfNotContains($"using {GetTypeNamespace(typeFullName)};");
}
if (typeFullName.Contains("<") && typeFullName.Contains(">"))
{
var left = typeFullName.IndexOf("<", StringComparison.Ordinal);
var right = typeFullName.LastIndexOf(">", StringComparison.Ordinal);
var genericTypes = typeFullName.Substring(left + 1, right - left - 1);
foreach (var genericType in genericTypes.Split(",").Where(x => x.Contains(".")))
{
AddGenericTypeUsingNamespace(genericType, usingNamespaceList);
}
}
}
private static string NormalizeTypeName(string typeName)
{
var nullable = string.Empty;

27
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Version/PackageVersionCheckerService.cs

@ -46,7 +46,7 @@ public class PackageVersionCheckerService : ITransientDependency
{
var versionList = await GetPackageVersionListAsync(packageId, false);
if (versionList == null)
if (!versionList.Any())
{
return false;
}
@ -121,10 +121,10 @@ public class PackageVersionCheckerService : ITransientDependency
}
var searchUrl = CliUrls.GetNuGetPackageSearchUrl(_apiKeyResult.ApiKey, packageId);
return await HasAnyPackageAsync(searchUrl);
return await HasAnyPackageAsync(searchUrl, packageId);
}
private async Task<bool> HasAnyPackageAsync(string url)
private async Task<bool> HasAnyPackageAsync(string url, string packageId)
{
try
{
@ -139,8 +139,9 @@ public class PackageVersionCheckerService : ITransientDependency
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
var responseContent = await responseMessage.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<NuGetSearchResultDto>(responseContent).TotalHits > 0;
var nugetSearchResult = JsonSerializer.Deserialize<NuGetSearchResultDto>(responseContent);
return nugetSearchResult.TotalHits > 0 && nugetSearchResult.Packages.Any(package => package.Id.ToLowerInvariant() == packageId.ToLowerInvariant());
}
}
catch (Exception)
@ -182,7 +183,7 @@ public class PackageVersionCheckerService : ITransientDependency
if (responseMessage.StatusCode == HttpStatusCode.NotFound)
{
//the package doesn't exist...
return null;
return new List<string>();
}
await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage);
@ -193,7 +194,7 @@ public class PackageVersionCheckerService : ITransientDependency
}
catch (Exception)
{
return null;
return new List<string>();
}
}
@ -238,6 +239,18 @@ public class PackageVersionCheckerService : ITransientDependency
{
[JsonProperty("totalHits")]
public int TotalHits { get; set; }
[JsonProperty("data")]
public NuGetSearchResultPackagesDto[] Packages { get; set; }
}
public class NuGetSearchResultPackagesDto
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("version")]
public string Version { get; set; }
}
public class NuGetVersionResultDto

8
framework/src/Volo.Abp.Core/Volo/Abp/Reflection/TypeHelper.cs

@ -257,6 +257,14 @@ public static class TypeHelper
{
return "string";
}
else if (type.FullName == "System.DateOnly")
{
return "string";
}
else if (type.FullName == "System.TimeOnly")
{
return "string";
}
else if (type == typeof(TimeSpan))
{
return "string";

23
framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageCompressor.cs

@ -28,10 +28,25 @@ public class ImageCompressor : IImageCompressor, ITransientDependency
{
Check.NotNull(stream, nameof(stream));
if(!stream.CanRead)
{
return new ImageCompressResult<Stream>(stream, ImageProcessState.Unsupported);
}
if(!stream.CanSeek)
{
var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream, CancellationTokenProvider.FallbackToProvider(cancellationToken));
SeekToBegin(memoryStream);
stream = memoryStream;
}
foreach (var imageCompressorContributor in ImageCompressorContributors)
{
var result = await imageCompressorContributor.TryCompressAsync(stream, mimeType, CancellationTokenProvider.FallbackToProvider(cancellationToken));
SeekToBegin(stream);
if (result.State == ImageProcessState.Unsupported)
{
continue;
@ -64,4 +79,12 @@ public class ImageCompressor : IImageCompressor, ITransientDependency
return new ImageCompressResult<byte[]>(bytes, ImageProcessState.Unsupported);
}
protected virtual void SeekToBegin(Stream stream)
{
if (stream.CanSeek)
{
stream.Seek(0, SeekOrigin.Begin);
}
}
}

23
framework/src/Volo.Abp.Imaging.Abstractions/Volo/Abp/Imaging/ImageResizer.cs

@ -38,9 +38,24 @@ public class ImageResizer : IImageResizer, ITransientDependency
ChangeDefaultResizeMode(resizeArgs);
if(!stream.CanRead)
{
return new ImageResizeResult<Stream>(stream, ImageProcessState.Unsupported);
}
if(!stream.CanSeek)
{
var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream, CancellationTokenProvider.FallbackToProvider(cancellationToken));
SeekToBegin(memoryStream);
stream = memoryStream;
}
foreach (var imageResizerContributor in ImageResizerContributors)
{
var result = await imageResizerContributor.TryResizeAsync(stream, resizeArgs, mimeType, CancellationTokenProvider.FallbackToProvider(cancellationToken));
SeekToBegin(stream);
if (result.State == ImageProcessState.Unsupported)
{
@ -85,4 +100,12 @@ public class ImageResizer : IImageResizer, ITransientDependency
resizeArgs.Mode = ImageResizeOptions.DefaultResizeMode;
}
}
protected virtual void SeekToBegin(Stream stream)
{
if (stream.CanSeek)
{
stream.Seek(0, SeekOrigin.Begin);
}
}
}

9
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json

@ -114,6 +114,13 @@
"Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "用户是否可以确认电话号码",
"Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "登录时是否需要验证的手机号码.",
"Description:Abp.Identity.User.IsUserNameUpdateEnabled": "是否允许用户更新用户名.",
"Description:Abp.Identity.User.IsEmailUpdateEnabled": "是否允许用户更新电子邮箱."
"Description:Abp.Identity.User.IsEmailUpdateEnabled": "是否允许用户更新电子邮箱.",
"Details": "详情",
"CreatedBy": "创建者",
"ModifiedBy": "修改者",
"ModificationTime": "修改时间",
"PasswordUpdateTime": "密码更新时间",
"LockoutEndTime": "锁定结束时间",
"FailedAccessCount": "访问失败次数"
}
}

9
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hant.json

@ -114,6 +114,13 @@
"Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "是否啟用電話認證.",
"Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "決定使用者是否需電話認證後才能登入.",
"Description:Abp.Identity.User.IsUserNameUpdateEnabled": "決定使用者是否能更新帳號.",
"Description:Abp.Identity.User.IsEmailUpdateEnabled": "決定使用者是否能更新信箱."
"Description:Abp.Identity.User.IsEmailUpdateEnabled": "決定使用者是否能更新信箱.",
"Details": "詳情",
"CreatedBy": "創建者",
"ModifiedBy": "修改者",
"ModificationTime": "修改時間",
"PasswordUpdateTime": "密碼更新時間",
"LockoutEndTime": "鎖定結束時間",
"FailedAccessCount": "訪問失敗次數"
}
}

2
modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/zh-Hans.json

@ -25,7 +25,7 @@
"SmtpPassword": "密码",
"SmtpDomain": "域",
"SmtpEnableSsl": "启用ssl",
"SmtpUseDefaultCredentials": "使用默认证书",
"SmtpUseDefaultCredentials": "使用默认凭据",
"DefaultFromAddress": "默认发件人",
"DefaultFromDisplayName": "默认显示名称",
"Feature:SettingManagementGroup": "设置管理",

112
npm/ng-packs/migrations.json

@ -2,19 +2,115 @@
"migrations": [
{
"cli": "nx",
"version": "16.2.0-beta.0",
"description": "Remove outputPath from run commands",
"implementation": "./src/migrations/update-16-2-0/remove-run-commands-output-path",
"version": "16.6.0-beta.6",
"description": "Prefix outputs with {workspaceRoot}/{projectRoot} if needed",
"implementation": "./src/migrations/update-15-0-0/prefix-outputs",
"package": "nx",
"name": "16.2.0-remove-output-path-from-run-commands"
"name": "16.6.0-prefix-outputs"
},
{
"cli": "nx",
"version": "16.2.0-beta.0",
"description": "Normalize tsconfig.cy.json files to be located at '<projectRoot>/cypress/tsconfig.json'",
"implementation": "./src/migrations/update-16-2-0/update-cy-tsconfig",
"version": "16.8.0-beta.3",
"description": "Escape $ in env variables",
"implementation": "./src/migrations/update-16-8-0/escape-dollar-sign-env-variables",
"package": "nx",
"name": "16.8.0-escape-dollar-sign-env"
},
{
"version": "16.8.0",
"description": "update-16-8-0-add-ignored-files",
"implementation": "./src/migrations/update-16-8-0-add-ignored-files/update-16-8-0-add-ignored-files",
"package": "@nx/linter",
"name": "update-16-8-0-add-ignored-files"
},
{
"cli": "nx",
"version": "16.9.0-beta.1",
"description": "Replace imports of Module Federation utils frm @nx/devkit to @nx/webpack",
"implementation": "./src/migrations/update-16-9-0/migrate-mf-util-usage",
"package": "@nx/devkit",
"name": "update-16-9-0-migrate-mf-usage-to-webpack"
},
{
"cli": "nx",
"version": "16.4.0-beta.6",
"requires": {
"@angular-eslint/eslint-plugin-template": ">=16.0.0"
},
"description": "Remove the 'accessibility-' prefix from '@angular-eslint/eslint-plugin-template' rules.",
"factory": "./src/migrations/update-16-4-0/rename-angular-eslint-accesibility-rules",
"package": "@nx/angular",
"name": "rename-angular-eslint-accesibility-rules"
},
{
"cli": "nx",
"version": "16.4.0-beta.11",
"requires": {
"@angular/core": ">=16.1.0"
},
"description": "Update the @angular/cli package version to ~16.1.0.",
"factory": "./src/migrations/update-16-4-0/update-angular-cli",
"package": "@nx/angular",
"name": "update-angular-cli-version-16-1-0"
},
{
"cli": "nx",
"version": "16.6.0-beta.0",
"description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.",
"factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps",
"package": "@nx/angular",
"name": "explicitly-set-projects-to-update-buildable-deps"
},
{
"cli": "nx",
"version": "16.7.0-beta.6",
"requires": {
"@angular/core": ">=16.2.0"
},
"description": "Update the @angular/cli package version to ~16.2.0.",
"factory": "./src/migrations/update-16-7-0/update-angular-cli",
"package": "@nx/angular",
"name": "update-angular-cli-version-16-2-0"
},
{
"cli": "nx",
"version": "16.4.0-beta.10",
"description": "Remove tsconfig.e2e.json and add settings to project tsconfig.json. tsConfigs executor option is now deprecated. The project level tsconfig.json file should be used instead.",
"implementation": "./src/migrations/update-16-4-0/tsconfig-sourcemaps",
"package": "@nx/cypress",
"name": "update-16-2-0-normalize-tsconfigs"
"name": "update-16-3-0-remove-old-tsconfigs"
},
{
"cli": "nx",
"version": "16.8.0-beta.4",
"description": "Update to Cypress v13. Most noteable change is video recording is off by default. This migration will only update if the workspace is already on Cypress v12. https://docs.cypress.io/guides/references/migration-guide#Migrating-to-Cypress-130",
"implementation": "./src/migrations/update-16-8-0/cypress-13",
"package": "@nx/cypress",
"name": "update-16-8-0-cypress-13"
},
{
"cli": "nx",
"version": "16.5.0-beta.2",
"description": "Add test-setup.ts to ignored files in production input",
"implementation": "./src/migrations/update-16-5-0/add-test-setup-to-inputs-ignore",
"package": "@nx/jest",
"name": "add-test-setup-to-inputs-ignore"
},
{
"cli": "nx",
"version": "16.6.0-beta.0",
"description": "Explicitly set 'updateBuildableProjectDepsInPackageJson' to 'true' in targets that rely on that value as the default.",
"factory": "./src/migrations/update-16-6-0/explicitly-set-projects-to-update-buildable-deps",
"package": "@nx/js",
"name": "explicitly-set-projects-to-update-buildable-deps"
},
{
"cli": "nx",
"version": "16.8.2-beta.0",
"description": "Remove invalid options (strict, noInterop) for ES6 type modules.",
"factory": "./src/migrations/update-16-8-2/update-swcrc",
"package": "@nx/js",
"name": "16-8-2-update-swcrc"
}
]
}

128
npm/ng-packs/package.json

@ -44,85 +44,74 @@
},
"private": true,
"devDependencies": {
"@abp/ng.account": "~7.4.0",
"@abp/ng.account.core": "~7.4.0",
"@abp/ng.core": "~7.4.0",
"@abp/ng.feature-management": "~7.4.0",
"@abp/ng.identity": "~7.4.0",
"@abp/ng.oauth": "~7.4.0",
"@abp/ng.permission-management": "~7.4.0",
"@abp/ng.schematics": "~7.4.0",
"@abp/ng.setting-management": "~7.4.0",
"@abp/ng.tenant-management": "~7.4.0",
"@abp/ng.theme.basic": "~7.4.0",
"@abp/ng.theme.lepton-x": "~2.4.0",
"@abp/ng.theme.shared": "~7.4.0",
"@abp/utils": "~7.4.0",
"@angular-devkit/build-angular": "~16.0.0",
"@angular-devkit/core": "~16.0.0",
"@angular-devkit/schematics": "~16.0.0",
"@angular-devkit/schematics-cli": "~16.0.0",
"@angular-eslint/eslint-plugin": "~16.0.0",
"@angular-eslint/eslint-plugin-template": "~16.0.0",
"@angular-eslint/template-parser": "~16.0.0",
"@angular/animations": "~16.0.0",
"@angular/cli": "~16.0.0",
"@angular/common": "~16.0.0",
"@angular/compiler": "~16.0.0",
"@angular/compiler-cli": "~16.0.0",
"@angular/core": "~16.0.0",
"@angular/forms": "~16.0.0",
"@angular/language-service": "~16.0.0",
"@angular/localize": "~16.0.0",
"@angular/platform-browser": "~16.0.0",
"@angular/platform-browser-dynamic": "~16.0.0",
"@angular/router": "~16.0.0",
"@fortawesome/fontawesome-free": "^5.15.4",
"@angular-devkit/build-angular": "~16.2.0",
"@angular-devkit/core": "~16.2.0",
"@angular-devkit/schematics": "~16.2.0",
"@angular-devkit/schematics-cli": "~16.2.0",
"@angular-eslint/eslint-plugin": "~16.2.0",
"@angular-eslint/eslint-plugin-template": "~16.2.0",
"@angular-eslint/template-parser": "~16.2.0",
"@angular/animations": "~16.2.0",
"@angular/cli": "~16.2.0",
"@angular/common": "~16.2.0",
"@angular/compiler": "~16.2.0",
"@angular/compiler-cli": "~16.2.0",
"@angular/core": "~16.2.0",
"@angular/forms": "~16.2.0",
"@angular/language-service": "~16.2.0",
"@angular/localize": "~16.2.0",
"@angular/platform-browser": "~16.2.0",
"@angular/platform-browser-dynamic": "~16.2.0",
"@angular/router": "~16.2.0",
"@fortawesome/fontawesome-free": "^5.0.0",
"@ng-bootstrap/ng-bootstrap": "^15.0.0",
"@ngneat/spectator": "^10.0.0",
"@ngx-validate/core": "^0.2.0",
"@nx/angular": "16.2.2",
"@nx/cypress": "16.2.2",
"@nx/eslint-plugin": "16.2.2",
"@nx/jest": "16.2.2",
"@nx/js": "16.2.2",
"@nx/linter": "16.2.2",
"@nx/workspace": "16.2.2",
"@popperjs/core": "~2.11.2",
"@schematics/angular": "~16.0.0",
"@swc-node/register": "~1.4.2",
"@swc/cli": "~0.1.62",
"@swc/core": "~1.3.51",
"@nx/angular": "16.9.0",
"@nx/cypress": "16.9.0",
"@nx/eslint-plugin": "16.9.0",
"@nx/jest": "16.9.0",
"@nx/js": "16.9.0",
"@nx/linter": "16.9.0",
"@nx/workspace": "16.9.0",
"@popperjs/core": "~2.11.0",
"@schematics/angular": "~16.2.0",
"@swc-node/register": "~1.4.0",
"@swc/cli": "~0.1.0",
"@swc/core": "1.3.94",
"@swimlane/ngx-datatable": "^20.0.0",
"@types/jest": "29.4.4",
"@types/node": "20.2.5",
"@typescript-eslint/eslint-plugin": "5.59.5",
"@typescript-eslint/parser": "5.59.5",
"angular-oauth2-oidc": "^15.0.1",
"bootstrap": "^5.1.1",
"bootstrap-icons": "^1.10.3",
"chart.js": "^3.5.1",
"cypress": "^7.3.0",
"@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.62.0",
"angular-oauth2-oidc": "^15.0.0",
"bootstrap": "^5.0.0",
"bootstrap-icons": "^1.0.0",
"chart.js": "^3.0.0",
"cypress": "^7.0.0",
"dotenv": "10.0.0",
"eslint": "8.15.0",
"eslint": "8.46.0",
"eslint-config-prettier": "8.1.0",
"eslint-plugin-cypress": "2.15.1",
"got": "^11.0.0",
"eslint-plugin-cypress": "^2.10.3",
"got": "^11.5.2",
"jest": "^29.0.0",
"jest-canvas-mock": "^2.3.1",
"jest": "^29.0.0",
"jest-canvas-mock": "^2.0.0",
"jest-environment-jsdom": "^29.0.0",
"jest-preset-angular": "13.1.0",
"jsonc-eslint-parser": "^2.1.0",
"jsonc-parser": "^2.3.0",
"just-clone": "^6.1.1",
"just-compare": "^2.3.0",
"jsonc-eslint-parser": "^2.0.0",
"jsonc-parser": "^2.0.0",
"just-clone": "^6.0.0",
"just-compare": "^2.0.0",
"lerna": "^4.0.0",
"lint-staged": "^13.0.3",
"ng-packagr": "~16.0.0",
"lint-staged": "^13.0.0",
"ng-packagr": "~16.2.0",
"ng-zorro-antd": "^16.0.0",
"nx": "16.2.2",
"perfect-scrollbar": "^1.5.5",
"postcss": "^8.3.9",
"nx": "16.9.0",
"perfect-scrollbar": "^1.0.0",
"postcss": "^8.0.0",
"postcss-import": "14.1.0",
"postcss-preset-env": "7.5.0",
"postcss-url": "10.1.3",
@ -133,13 +122,13 @@
"ts-jest": "29.1.0",
"ts-node": "10.9.1",
"ts-toolbelt": "6.15.4",
"tslib": "^2.3.0",
"tslib": "^2.0.0",
"tslint": "~6.1.0",
"typescript": "5.0.4",
"typescript": "5.1.6",
"zone.js": "~0.13.0",
"@nx/devkit": "16.2.2",
"@nx/plugin": "^16.2.2",
"@swc/helpers": "~0.5.0"
"@nx/devkit": "16.9.0",
"@nx/plugin": "16.9.0",
"@swc/helpers": "0.5.3"
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx,html,css,scss}": [
@ -148,3 +137,4 @@
},
"dependencies": {}
}

2
npm/ng-packs/packages/core/src/lib/directives/caps-lock.directive.ts

@ -21,7 +21,7 @@ export class TrackCapsLockDirective {
if (
(s.toUpperCase() === s && s.toLowerCase() !== s && e.shiftKey) ||
(s.toUpperCase() !== s && s.toLowerCase() === s && e.shiftKey) ||
e.getModifierState('CapsLock')
(e.getModifierState && e.getModifierState('CapsLock'))
) {
return true;
}

17
npm/ng-packs/packages/core/src/lib/models/dtos.ts

@ -114,14 +114,14 @@ export class CreationAuditedEntityDto<TPrimaryKey = string> extends EntityDto<TP
}
}
export class CreationAuditedEntityWithUserDto<
TUserDto,
export class CreationAuditedEntityWithUserDto<
TPrimaryKey = string,
TUserDto = any
> extends CreationAuditedEntityDto<TPrimaryKey> {
creator?: TUserDto;
constructor(
initialValues: Partial<CreationAuditedEntityWithUserDto<TUserDto, TPrimaryKey>> = {},
initialValues: Partial<CreationAuditedEntityWithUserDto<TPrimaryKey,TUserDto>> = {},
) {
super(initialValues);
}
@ -136,14 +136,15 @@ export class AuditedEntityDto<TPrimaryKey = string> extends CreationAuditedEntit
}
}
/** @deprecated the class signature will change in v8.0 */
export class AuditedEntityWithUserDto<
TUserDto,
TPrimaryKey = string,
TUserDto = any,
> extends AuditedEntityDto<TPrimaryKey> {
creator?: TUserDto;
lastModifier?: TUserDto;
constructor(initialValues: Partial<AuditedEntityWithUserDto<TUserDto, TPrimaryKey>> = {}) {
constructor(initialValues: Partial<AuditedEntityWithUserDto< TPrimaryKey,TUserDto>> = {}) {
super(initialValues);
}
}
@ -157,16 +158,16 @@ export class FullAuditedEntityDto<TPrimaryKey = string> extends AuditedEntityDto
super(initialValues);
}
}
/** @deprecated the class signature will change in v8.0 */
export class FullAuditedEntityWithUserDto<
TUserDto,
TPrimaryKey = string,
TUserDto = any
> extends FullAuditedEntityDto<TPrimaryKey> {
creator?: TUserDto;
lastModifier?: TUserDto;
deleter?: TUserDto;
constructor(initialValues: Partial<FullAuditedEntityWithUserDto<TUserDto, TPrimaryKey>> = {}) {
constructor(initialValues: Partial<FullAuditedEntityWithUserDto< TPrimaryKey,TUserDto>> = {}) {
super(initialValues);
}
}

1
npm/ng-packs/packages/core/src/lib/utils/file-utils.ts

@ -1,3 +1,4 @@
/** @deprecated the method will change in v8.0 */
export function downloadBlob(blob: Blob, filename: string) {
const blobUrl = URL.createObjectURL(blob);

8
npm/ng-packs/packages/schematics/package.json

@ -4,16 +4,16 @@
"author": "",
"schematics": "./collection.json",
"dependencies": {
"@angular-devkit/core": "~16.0.0",
"@angular-devkit/schematics": "~16.0.0",
"@angular/cli": "~16.0.0",
"@angular-devkit/core": "~16.2.0",
"@angular-devkit/schematics": "~16.2.0",
"@angular/cli": "~16.2.0",
"got": "^11.5.2",
"jsonc-parser": "^2.3.0",
"should-quote": "^1.0.0",
"typescript": "5.0.4"
},
"devDependencies": {
"@schematics/angular": "~16.0.0",
"@schematics/angular": "~16.2.0",
"@types/jest": "29.4.4",
"@types/node": "20.2.5",
"jest": "29.4.3",

2
npm/ng-packs/packages/schematics/src/constants/system-types.ts

@ -5,6 +5,8 @@ export const SYSTEM_TYPES = new Map([
['Collections.Generic.Dictionary', 'Record'],
['DateTime', 'string'],
['DateTimeOffset', 'string'],
['DateOnly', 'string'],
['TimeOnly', 'string'],
['Decimal', 'number'],
['Double', 'number'],
['Guid', 'string'],

129
npm/ng-packs/packages/schematics/src/tests/parse-generic-type.spec.ts

@ -0,0 +1,129 @@
import { parseBaseTypeWithGenericTypes } from '../utils/model';
import { parseGenerics } from '../utils/tree';
import {test} from '@jest/globals';
const cases: Array<[string, string[]]> = [
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
['Volo.Abp.Application.Dtos.AuditedEntityWithUserDto'],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto>',
['Volo.Abp.Application.Dtos.AuditedEntityWithUserDto', 'Volo.Abp.Identity.IdentityUserDto'],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<string,Volo.Abp.Identity.IdentityUserDto>',
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
'string',
'Volo.Abp.Identity.IdentityUserDto'
],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<string,Volo.Abp.Identity.IdentityUserDto<number>>',
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
'string',
'Volo.Abp.Identity.IdentityUserDto',
'number',
],
],
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<string,Volo.Abp.Identity.IdentityUserDto<Volo.Abp.Core.Dummy<System.String>>>',
[
'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto',
'string',
'Volo.Abp.Identity.IdentityUserDto',
'Volo.Abp.Core.Dummy',
'System.String',
],
],
[
'AuditedEntityWithUserDto',
['AuditedEntityWithUserDto'],
],
];
test.each(cases)('should parse %s', (inputStr, expected) => {
const parsed = parseBaseTypeWithGenericTypes(inputStr);
expect(parsed).toEqual(expected);
})
describe('parseGenerics', () => {
it('should work with simple type', function() {
const node = parseGenerics('System.String');
expect(node.data).toEqual('System.String');
expect(node.index).toBe(0);
expect(node.parent).toBe(null);
});
it('should work with simple Array type', function() {
const node = parseGenerics('System.String[]');
expect(node.data).toEqual('System.String[]');
expect(node.index).toBe(0);
expect(node.parent).toBe(null);
});
it('should work with simple', function() {
const node = parseGenerics('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.index).toBe(0);
expect(node.parent).toBe(null);
});
it('should work with `Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto>`', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(1);
const child = node.children[0];
expect(node.children[0].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(child.parent).toBe(node);
});
it('should work with `Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto>`', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(2);
expect(node.children[0].data).toEqual('System.string');
expect(node.children[0].index).toBe(0)
expect(node.children[1].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(node.children[1].index).toBe(1);
});
it('should Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto<System.Int>>', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<System.string,Volo.Abp.Identity.IdentityUserDto<System.Int>>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(2);
expect(node.children[0].data).toEqual('System.string');
expect((node.children[0]).parent).toBe(node);
expect(node.children[1].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(node.children[1].children.length).toBe(1);
expect(node.children[1].children[0].data).toEqual('System.Int');
expect(node.children[1].children[0].parent).toBe(node.children[1])
expect(node.children[1].children[0].index).toBe(0)
});
it('should Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto<System.Int>,System.string>', function() {
const type = 'Volo.Abp.Application.Dtos.AuditedEntityWithUserDto<Volo.Abp.Identity.IdentityUserDto<System.Int>,System.string>';
const node = parseGenerics(type);
expect(node.data).toEqual('Volo.Abp.Application.Dtos.AuditedEntityWithUserDto');
expect(node.children.length).toBe(2);
expect(node.children[0].data).toEqual('Volo.Abp.Identity.IdentityUserDto');
expect(node.children[0].children.length).toBe(1);
expect(node.children[0].children[0].data).toEqual('System.Int');
expect(node.children[1].data).toEqual('System.string');
});
});

35
npm/ng-packs/packages/schematics/src/utils/model.ts

@ -9,7 +9,7 @@ import {
import { parseNamespace } from './namespace';
import { relativePathToModel } from './path';
import { camel } from './text';
import { parseGenerics } from './tree';
import { parseGenerics, TypeNode } from './tree';
import {
createTypeParser,
createTypeSimplifier,
@ -71,12 +71,16 @@ export function createImportRefsToModelReducer(params: ModelGeneratorParams) {
model.interfaces.forEach(_interface => {
const { baseType } = types[_interface.ref];
if (baseType && parseNamespace(solution, baseType) !== model.namespace)
toBeImported.push({
type: baseType.split('<')[0],
isEnum: false,
});
if (baseType && parseNamespace(solution, baseType) !== model.namespace){
const baseTypeWithGenericParams = parseBaseTypeWithGenericTypes(baseType);
baseTypeWithGenericParams.forEach(t => {
toBeImported.push({
type: t,
isEnum: false,
});
})
}
[..._interface.properties, ..._interface.generics].forEach(prop => {
prop.refs.forEach(ref => {
const propType = types[ref];
@ -172,7 +176,20 @@ export function createRefToImportReducerCreator(params: ModelGeneratorParams) {
}
function isOptionalProperty(prop: PropertyDef) {
return (
prop.typeSimple.endsWith('?') || (prop.typeSimple === 'string' && prop.isRequired === false)
);
return (prop.typeSimple.endsWith('?') || (prop.typeSimple === 'string' && !prop.isRequired));
}
export function parseBaseTypeWithGenericTypes(type: string): string[] {
const parsedTypeNode = parseGenerics(type);
const nodeToText = (node: TypeNode,acc:string[] = []): string[] => {
acc.push(node.data);
if(node.children && node.children.length > 0){
node.children.forEach(child => {
nodeToText(child,acc);
})
}
return acc;
}
return nodeToText(parsedTypeNode);
}

31
npm/ng-packs/packages/schematics/src/utils/tree.ts

@ -39,7 +39,7 @@ export class TypeNode {
}
}
export function parseGenerics(type: string, mapperFn?: TypeNodeMapperFn) {
export function parseGenericsOld(type: string, mapperFn?: TypeNodeMapperFn) {
const [rootType, ...types] = type.split('<');
const root = new TypeNode(rootType, null, mapperFn);
@ -68,4 +68,33 @@ export function parseGenerics(type: string, mapperFn?: TypeNodeMapperFn) {
return root;
}
export function parseGenerics(type: string, mapperFn?: TypeNodeMapperFn, parent?: TypeNode | null): TypeNode {
const regex = /(?<MainType>[\w.]+)<(?<GenericType>.*)>/;
const match = type.match(regex);
if (!match) {
return new TypeNode(type, null, mapperFn);
}
const mainType = match.groups?.MainType || '';
const genericType = match.groups?.GenericType || '';
const root = new TypeNode(mainType, parent ?? null, mapperFn);
if (genericType.includes(',')) {
const genericTypes = genericType.split(',');
genericTypes.forEach((genericType, index) => {
const child = parseGenerics(genericType, mapperFn, root);
child.index = index;
root.children.push(child);
child.parent = root;
});
} else {
const child = parseGenerics(genericType, mapperFn, root);
child.index = root.children.length;
root.children.push(child);
child.parent = root;
}
return root;
}
export type TypeNodeMapperFn = (node: TypeNode) => string;

1
npm/ng-packs/packages/theme-basic/src/lib/components/empty-layout/empty-layout.component.ts

@ -5,7 +5,6 @@ import { eLayoutType } from '@abp/ng.core';
selector: 'abp-layout-empty',
template: `
<router-outlet></router-outlet>
<abp-confirmation></abp-confirmation>
`,
})
export class EmptyLayoutComponent {

6
npm/ng-packs/packages/theme-shared/src/lib/services/status-code-error-handler.service.ts

@ -57,9 +57,9 @@ export class StatusCodeErrorHandlerService implements CustomHttpErrorHandlerServ
this.createErrorComponentService.execute(instance);
}
canHandle({ status }): boolean {
this.status = status || 0;
return this.handledStatusCodes.indexOf(status) > -1;
canHandle(error): boolean {
this.status = error?.status || 0;
return this.handledStatusCodes.indexOf(this.status) > -1;
}
execute(): void {

42
templates/app-nolayers/angular/package.json

@ -21,31 +21,31 @@
"@abp/ng.tenant-management": "~7.4.0",
"@abp/ng.theme.shared": "~7.4.0",
"@abp/ng.theme.lepton-x": "~2.4.0",
"@angular/animations": "~16.0.0",
"@angular/common": "~16.0.0",
"@angular/compiler": "~16.0.0",
"@angular/core": "~16.0.0",
"@angular/forms": "~16.0.0",
"@angular/localize": "~16.0.0",
"@angular/platform-browser": "~16.0.0",
"@angular/platform-browser-dynamic": "~16.0.0",
"@angular/router": "~16.0.0",
"rxjs": "7.8.1",
"@angular/animations": "~16.2.0",
"@angular/common": "~16.2.0",
"@angular/compiler": "~16.2.0",
"@angular/core": "~16.2.0",
"@angular/forms": "~16.2.0",
"@angular/localize": "~16.2.0",
"@angular/platform-browser": "~16.2.0",
"@angular/platform-browser-dynamic": "~16.2.0",
"@angular/router": "~16.2.0",
"rxjs": "~7.4.0",
"tslib": "^2.1.0",
"bootstrap-icons": "~1.8.3",
"zone.js": "~0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~16.2.0",
"@angular-eslint/builder": "~16.2.0",
"@angular-eslint/eslint-plugin": "~16.2.0",
"@angular-eslint/eslint-plugin-template": "~16.2.0",
"@angular-eslint/schematics": "~16.2.0",
"@angular-eslint/template-parser": "~16.2.0",
"@abp/ng.schematics": "~7.4.0",
"@angular-devkit/build-angular": "~16.0.0",
"@angular-eslint/builder": "~16.0.0",
"@angular-eslint/eslint-plugin": "~16.0.0",
"@angular-eslint/eslint-plugin-template": "~16.0.0",
"@angular-eslint/schematics": "~16.0.0",
"@angular-eslint/template-parser": "~16.0.0",
"@angular/cli": "~16.0.0",
"@angular/compiler-cli": "~16.0.0",
"@angular/language-service": "~16.0.0",
"@angular/cli": "~16.2.0",
"@angular/compiler-cli": "~16.2.0",
"@angular/language-service": "~16.2.0",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"@typescript-eslint/eslint-plugin": "^5.36.2",
@ -57,7 +57,7 @@
"karma-coverage": "~2.1.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.7.0",
"ng-packagr": "^16.0.0",
"ng-packagr": "~16.2.0",
"typescript": "~5.0.4"
}
}
}

40
templates/app/angular/package.json

@ -21,31 +21,31 @@
"@abp/ng.tenant-management": "~7.4.0",
"@abp/ng.theme.shared": "~7.4.0",
"@abp/ng.theme.lepton-x": "~2.4.0",
"@angular/animations": "~16.0.0",
"@angular/common": "~16.0.0",
"@angular/compiler": "~16.0.0",
"@angular/core": "~16.0.0",
"@angular/forms": "~16.0.0",
"@angular/localize": "~16.0.0",
"@angular/platform-browser": "~16.0.0",
"@angular/platform-browser-dynamic": "~16.0.0",
"@angular/router": "~16.0.0",
"@angular/animations": "~16.2.0",
"@angular/common": "~16.2.0",
"@angular/compiler": "~16.2.0",
"@angular/core": "~16.2.0",
"@angular/forms": "~16.2.0",
"@angular/localize": "~16.2.0",
"@angular/platform-browser": "~16.2.0",
"@angular/platform-browser-dynamic": "~16.2.0",
"@angular/router": "~16.2.0",
"bootstrap-icons": "~1.8.3",
"rxjs": "7.8.1",
"rxjs": "~7.4.0",
"tslib": "^2.1.0",
"zone.js": "~0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~16.0.0",
"@angular-eslint/builder": "~16.0.0",
"@angular-eslint/eslint-plugin": "~16.0.0",
"@angular-eslint/eslint-plugin-template": "~16.0.0",
"@angular-eslint/schematics": "~16.0.0",
"@angular-eslint/template-parser": "~16.0.0",
"@angular-devkit/build-angular": "~16.2.0",
"@angular-eslint/builder": "~16.2.0",
"@angular-eslint/eslint-plugin": "~16.2.0",
"@angular-eslint/eslint-plugin-template": "~16.2.0",
"@angular-eslint/schematics": "~16.2.0",
"@angular-eslint/template-parser": "~16.2.0",
"@abp/ng.schematics": "~7.4.0",
"@angular/cli": "~16.0.0",
"@angular/compiler-cli": "~16.0.0",
"@angular/language-service": "~16.0.0",
"@angular/cli": "~16.2.0",
"@angular/compiler-cli": "~16.2.0",
"@angular/language-service": "~16.2.0",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"@typescript-eslint/eslint-plugin": "^5.36.2",
@ -59,4 +59,4 @@
"karma-jasmine-html-reporter": "^1.7.0",
"typescript": "~5.0.4"
}
}
}

46
templates/module/angular/package.json

@ -6,12 +6,9 @@
"start": "ng serve dev-app --open",
"build": "ng build my-project-name --configuration production",
"build:app": "npm run symlink:copy -- --no-watch && ng build dev-app --configuration production",
"symlink:copy": "symlink copy --angular --packages @my-company-name/my-project-name --configuration production",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"compile:ivy": "yarn ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points --tsconfig './tsconfig.prod.json' --source node_modules --async false",
"postinstall": "npm run compile:ivy"
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
@ -24,30 +21,30 @@
"@abp/ng.tenant-management": "~7.4.0",
"@abp/ng.theme.basic": "~7.4.0",
"@abp/ng.theme.shared": "~7.4.0",
"@angular/animations": "~16.0.0",
"@angular/common": "~16.0.0",
"@angular/compiler": "~16.0.0",
"@angular/core": "~16.0.0",
"@angular/forms": "~16.0.0",
"@angular/localize": "~16.0.0",
"@angular/platform-browser": "~16.0.0",
"@angular/platform-browser-dynamic": "~16.0.0",
"@angular/router": "~16.0.0",
"rxjs": "7.8.1",
"@angular/animations": "~16.2.0",
"@angular/common": "~16.2.0",
"@angular/compiler": "~16.2.0",
"@angular/core": "~16.2.0",
"@angular/forms": "~16.2.0",
"@angular/localize": "~16.2.0",
"@angular/platform-browser": "~16.2.0",
"@angular/platform-browser-dynamic": "~16.2.0",
"@angular/router": "~16.2.0",
"rxjs": "~7.4.0",
"tslib": "^2.1.0",
"zone.js": "~0.13.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~16.2.0",
"@angular-eslint/builder": "~16.2.0",
"@angular-eslint/eslint-plugin": "~16.2.0",
"@angular-eslint/eslint-plugin-template": "~16.2.0",
"@angular-eslint/schematics": "~16.2.0",
"@angular-eslint/template-parser": "~16.2.0",
"@abp/ng.schematics": "~7.4.0",
"@angular-devkit/build-angular": "~16.0.0",
"@angular-eslint/builder": "~16.0.0",
"@angular-eslint/eslint-plugin": "~16.0.0",
"@angular-eslint/eslint-plugin-template": "~16.0.0",
"@angular-eslint/schematics": "~16.0.0",
"@angular-eslint/template-parser": "~16.0.0",
"@angular/cli": "~16.0.0",
"@angular/compiler-cli": "~16.0.0",
"@angular/language-service": "~16.0.0",
"@angular/cli": "~16.2.0",
"@angular/compiler-cli": "~16.2.0",
"@angular/language-service": "~16.2.0",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"@typescript-eslint/eslint-plugin": "^5.36.2",
@ -59,7 +56,6 @@
"karma-coverage": "~2.1.0",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.7.0",
"symlink-manager": "^1.5.0",
"typescript": "~5.0.4"
}
}
}

Loading…
Cancel
Save