diff --git a/docs/en/CLI.md b/docs/en/CLI.md index 7dccf4ee6d..a1c53e0407 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -55,6 +55,7 @@ abp new Acme.BookStore * `--no-ui`: Specifies to not include the UI. This makes possible to create service-only modules (a.k.a. microservices - without UI). * `--output-folder` or `-o`: Specifies the output folder. Default value is the current directory. * `--version` or `-v`: Specifies the ABP & template version. It can be a [release tag](https://github.com/abpframework/abp/releases) or a [branch name](https://github.com/abpframework/abp/branches). Uses the latest release if not specified. Most of the times, you will want to use the latest version. +* `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D\localTemplate` or `https://.zip`). ### add-package diff --git a/docs/zh-Hans/CLI.md b/docs/zh-Hans/CLI.md index 863c061209..69ca39880a 100644 --- a/docs/zh-Hans/CLI.md +++ b/docs/zh-Hans/CLI.md @@ -43,7 +43,7 @@ abp new Acme.BookStore * `app` (default): [应用程序模板](Startup-Templates/Application.md). 其他选项: * `--ui` 或者 `-u`: 指定ui框架.默认`mvc`框架.其他选项: * `mvc`: ASP.NET Core MVC.此模板的其他选项: - * `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的.如果未指定会创建一个分层的解决方案,此解决方案没有那么复杂,适合大多数场景. + * `--tiered`: 创建分层解决方案,Web和Http Api层在物理上是分开的.如果未指定会创建一个分层的解决方案,此解决方案没有那么复杂,适合大多数场景. * `angular`: Angular. 这个模板还有一些额外的选项: * `--separate-identity-server`: 将Identity Server应用程序与API host应用程序分开. 如果未指定,则服务器端将只有一个端点. * `none`: 无UI. 这个模板还有一些额外的选项: @@ -53,8 +53,9 @@ abp new Acme.BookStore * `mongodb`: MongoDB. * `module`: [Module template](Startup-Templates/Module.md). 其他选项: * `--no-ui`: 不包含UI.仅创建服务模块(也称为微服务 - 没有UI). -* `--output-folder` 或者 `-o`: 指定输出文件夹,默认是当前目录. -* `--version` 或者 `-v`: 指定ABP和模板的版本.它可以是 [release tag](https://github.com/abpframework/abp/releases) 或者 [branch name](https://github.com/abpframework/abp/branches). 如果没有指定,则使用最新版本.大多数情况下,您会希望使用最新的版本. +* `--output-folder` 或者 `-o`: 指定输出文件夹,默认是当前目录. +* `--version` 或者 `-v`: 指定ABP和模板的版本.它可以是 [release tag](https://github.com/abpframework/abp/releases) 或者 [branch name](https://github.com/abpframework/abp/branches). 如果没有指定,则使用最新版本.大多数情况下,您会希望使用最新的版本. +* `--template-source` 或者 `-ts`: 指定自定义模板源用于生成项目,可以使用本地源和网络源(例如 `D\localTemplate` 或 `https://.zip`). ### add-package diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs index 91c5837900..c57833c1f7 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GetSourceCommand.cs @@ -55,7 +55,7 @@ namespace Volo.Abp.Cli.Commands } commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command); - + await _sourceCodeDownloadService.DownloadAsync( commandLineArgs.Target, outputFolder, version, gitHubLocalRepositoryPath, commandLineArgs.Options); } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs index d39a333860..f25a4ad89f 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs @@ -30,7 +30,7 @@ namespace Volo.Abp.Cli.Commands public async Task ExecuteAsync(CommandLineArgs commandLineArgs) { var projectName = NamespaceHelper.NormalizeNamespace(commandLineArgs.Target); - + if (projectName == null) { throw new CliUsageException( @@ -39,7 +39,7 @@ namespace Volo.Abp.Cli.Commands GetUsageInfo() ); } - + Logger.LogInformation("Creating your project..."); Logger.LogInformation("Project name: " + projectName); @@ -79,6 +79,12 @@ namespace Volo.Abp.Cli.Commands Logger.LogInformation("GitHub Local Repository Path: " + gitHubLocalRepositoryPath); } + var templateSource = commandLineArgs.Options.GetOrNull(Options.TemplateSource.Short, Options.TemplateSource.Long); + if (templateSource != null) + { + Logger.LogInformation("Template Source: " + templateSource); + } + var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long); outputFolder = Path.Combine(outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory(), @@ -102,6 +108,7 @@ namespace Volo.Abp.Cli.Commands uiFramework, mobileApp, gitHubLocalRepositoryPath, + templateSource, commandLineArgs.Options ) ); @@ -158,6 +165,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine("-d|--database-provider (if supported by the template)"); sb.AppendLine("-o|--output-folder (default: current folder)"); sb.AppendLine("-v|--version (default: latest version)"); + sb.AppendLine("-ts|--template-source (your local or network abp template source)"); sb.AppendLine("--tiered (if supported by the template)"); sb.AppendLine("--no-ui (if supported by the template)"); sb.AppendLine("--separate-identity-server (if supported by the template)"); @@ -173,6 +181,7 @@ namespace Volo.Abp.Cli.Commands sb.AppendLine(" abp new Acme.BookStore -d mongodb -o d:\\my-project"); sb.AppendLine(" abp new Acme.BookStore -t module"); sb.AppendLine(" abp new Acme.BookStore -t module --no-ui"); + sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\""); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); sb.AppendLine(""); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); @@ -271,6 +280,12 @@ namespace Volo.Abp.Cli.Commands public const string Short = "m"; public const string Long = "mobile"; } + + public static class TemplateSource + { + public const string Short = "ts"; + public const string Long = "template-source"; + } } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs index c8c6c0453c..7c8d068e1e 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs @@ -40,6 +40,7 @@ namespace Volo.Abp.Cli.Commands.Services UiFramework.NotSpecified, null, gitHubLocalRepositoryPath, + null, options ) ); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs index fd0a0e5246..03504251f5 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/AbpIoSourceCodeStore.cs @@ -2,9 +2,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; @@ -46,7 +44,8 @@ namespace Volo.Abp.Cli.ProjectBuilding public async Task GetAsync( string name, string type, - string version = null) + string version = null, + string templateSource = null) { var latestVersion = await GetLatestSourceCodeVersionAsync(name, type); @@ -57,8 +56,14 @@ namespace Volo.Abp.Cli.ProjectBuilding DirectoryHelper.CreateIfNotExists(CliPaths.TemplateCache); + if (!string.IsNullOrWhiteSpace(templateSource) && !IsNetworkSource(templateSource)) + { + Logger.LogInformation("Using local " + type + ": " + name + ", version: " + version); + return new TemplateFile(File.ReadAllBytes(Path.Combine(templateSource, name + "-" + version + ".zip")), version, latestVersion); + } + var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip"); - if (Options.CacheTemplates && File.Exists(localCacheFile)) + if (Options.CacheTemplates && File.Exists(localCacheFile) && templateSource.IsNullOrWhiteSpace()) { Logger.LogInformation("Using cached " + type + ": " + name + ", version: " + version); return new TemplateFile(File.ReadAllBytes(localCacheFile), version, latestVersion); @@ -71,11 +76,12 @@ namespace Volo.Abp.Cli.ProjectBuilding { Name = name, Type = type, + TemplateSource = templateSource, Version = version } ); - if (Options.CacheTemplates) + if (Options.CacheTemplates && templateSource.IsNullOrWhiteSpace()) { File.WriteAllBytes(localCacheFile, fileContent); } @@ -114,11 +120,20 @@ namespace Volo.Abp.Cli.ProjectBuilding using (var client = new CliHttpClient(TimeSpan.FromMinutes(10))) { - var responseMessage = await client.PostAsync( - $"{CliUrls.WwwAbpIo}api/download/{input.Type}/", - new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), - CancellationTokenProvider.Token - ); + HttpResponseMessage responseMessage; + + if (input.TemplateSource.IsNullOrWhiteSpace()) + { + responseMessage = await client.PostAsync( + $"{CliUrls.WwwAbpIo}api/download/{input.Type}/", + new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), + CancellationTokenProvider.Token + ); + } + else + { + responseMessage = await client.GetAsync(input.TemplateSource, CancellationTokenProvider.Token); + } await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); @@ -126,6 +141,11 @@ namespace Volo.Abp.Cli.ProjectBuilding } } + private bool IsNetworkSource(string source) + { + return source.ToLower().StartsWith("http"); + } + public class SourceCodeDownloadInputDto { public string Name { get; set; } @@ -133,6 +153,8 @@ namespace Volo.Abp.Cli.ProjectBuilding public string Version { get; set; } public string Type { get; set; } + + public string TemplateSource { get; set; } } public class GetLatestSourceCodeVersionDto diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs index 4d1ed7aa0c..de082d4bcf 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ISourceCodeStore.cs @@ -8,7 +8,8 @@ namespace Volo.Abp.Cli.ProjectBuilding Task GetAsync( string name, string type, - [CanBeNull] string version = null + [CanBeNull] string version = null, + [CanBeNull] string templateSource = null ); } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs index 48f109e1d3..6a7132769a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ModuleProjectBuilder.cs @@ -83,6 +83,8 @@ namespace Volo.Abp.Cli.ProjectBuilding !x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals(NewCommand.Options.Version.Long, StringComparison.InvariantCultureIgnoreCase) && !x.Key.Equals(NewCommand.Options.Version.Short, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => !x.Key.Equals(NewCommand.Options.TemplateSource.Short, StringComparison.InvariantCultureIgnoreCase) && + !x.Key.Equals(NewCommand.Options.TemplateSource.Long, StringComparison.InvariantCultureIgnoreCase)) .Select(x => x.Key).ToList(); await CliAnalyticsCollect.CollectAsync(new CliAnalyticsCollectInputDto diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs index 4a6a2fbe9d..ea207bc426 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs @@ -24,17 +24,21 @@ namespace Volo.Abp.Cli.ProjectBuilding [CanBeNull] public string AbpGitHubLocalRepositoryPath { get; set; } + [CanBeNull] + public string TemplateSource { get; set; } + [NotNull] public Dictionary ExtraProperties { get; set; } public ProjectBuildArgs( - [NotNull] SolutionName solutionName, + [NotNull] SolutionName solutionName, [CanBeNull] string templateName = null, [CanBeNull] string version = null, DatabaseProvider databaseProvider = DatabaseProvider.NotSpecified, UiFramework uiFramework = UiFramework.NotSpecified, MobileApp? mobileApp = null, [CanBeNull] string abpGitHubLocalRepositoryPath = null, + [CanBeNull] string templateSource = null, Dictionary extraProperties = null) { SolutionName = Check.NotNull(solutionName, nameof(solutionName)); @@ -44,6 +48,7 @@ namespace Volo.Abp.Cli.ProjectBuilding UiFramework = uiFramework; MobileApp = mobileApp; AbpGitHubLocalRepositoryPath = abpGitHubLocalRepositoryPath; + TemplateSource = templateSource; ExtraProperties = extraProperties ?? new Dictionary(); } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs index 80a25660fc..f7d9eaf3be 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/TemplateProjectBuilder.cs @@ -24,11 +24,11 @@ namespace Volo.Abp.Cli.ProjectBuilding protected IJsonSerializer JsonSerializer { get; } protected IApiKeyService ApiKeyService { get; } - public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore, + public TemplateProjectBuilder(ISourceCodeStore sourceCodeStore, ITemplateInfoProvider templateInfoProvider, - ICliAnalyticsCollect cliAnalyticsCollect, + ICliAnalyticsCollect cliAnalyticsCollect, IOptions options, - IJsonSerializer jsonSerializer, + IJsonSerializer jsonSerializer, IApiKeyService apiKeyService) { SourceCodeStore = sourceCodeStore; @@ -40,7 +40,7 @@ namespace Volo.Abp.Cli.ProjectBuilding Logger = NullLogger.Instance; } - + public async Task BuildAsync(ProjectBuildArgs args) { var templateInfo = GetTemplateInfo(args); @@ -50,9 +50,10 @@ namespace Volo.Abp.Cli.ProjectBuilding var templateFile = await SourceCodeStore.GetAsync( args.TemplateName, SourceCodeTypes.Template, - args.Version + args.Version, + args.TemplateSource ); - + var apiKeyResult = await ApiKeyService.GetApiKeyOrNullAsync(); if (apiKeyResult?.ApiKey != null) { @@ -82,7 +83,7 @@ namespace Volo.Abp.Cli.ProjectBuilding var options = args.ExtraProperties .Where(x => !x.Key.Equals(CliConsts.Command, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals("tiered", StringComparison.InvariantCultureIgnoreCase)) - .Where(x => !x.Key.Equals(NewCommand.Options.DatabaseProvider.Long, StringComparison.InvariantCultureIgnoreCase) && + .Where(x => !x.Key.Equals(NewCommand.Options.DatabaseProvider.Long, StringComparison.InvariantCultureIgnoreCase) && !x.Key.Equals(NewCommand.Options.DatabaseProvider.Short, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals(NewCommand.Options.OutputFolder.Long, StringComparison.InvariantCultureIgnoreCase) && !x.Key.Equals(NewCommand.Options.OutputFolder.Short, StringComparison.InvariantCultureIgnoreCase)) @@ -92,6 +93,8 @@ namespace Volo.Abp.Cli.ProjectBuilding !x.Key.Equals(NewCommand.Options.Mobile.Short, StringComparison.InvariantCultureIgnoreCase)) .Where(x => !x.Key.Equals(NewCommand.Options.Version.Long, StringComparison.InvariantCultureIgnoreCase) && !x.Key.Equals(NewCommand.Options.Version.Short, StringComparison.InvariantCultureIgnoreCase)) + .Where(x => !x.Key.Equals(NewCommand.Options.TemplateSource.Short, StringComparison.InvariantCultureIgnoreCase) && + !x.Key.Equals(NewCommand.Options.TemplateSource.Long, StringComparison.InvariantCultureIgnoreCase)) .Select(x => x.Key).ToList(); await CliAnalyticsCollect.CollectAsync(new CliAnalyticsCollectInputDto diff --git a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj index ce26fe7bea..3e4ae78b91 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj +++ b/framework/src/Volo.Abp.IdentityModel/Volo.Abp.IdentityModel.csproj @@ -16,7 +16,6 @@ - diff --git a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs index 6487f6ce65..ca6e41d60d 100644 --- a/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs +++ b/framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs @@ -21,15 +21,12 @@ namespace Volo.Abp.IdentityModel public ILogger Logger { get; set; } protected AbpIdentityClientOptions ClientOptions { get; } protected ICancellationTokenProvider CancellationTokenProvider { get; } - protected IHttpClientFactory HttpClientFactory { get; } public IdentityModelAuthenticationService( IOptions options, - ICancellationTokenProvider cancellationTokenProvider, - IHttpClientFactory httpClientFactory) + ICancellationTokenProvider cancellationTokenProvider) { CancellationTokenProvider = cancellationTokenProvider; - HttpClientFactory = httpClientFactory; ClientOptions = options.Value; Logger = NullLogger.Instance; } @@ -98,7 +95,7 @@ namespace Volo.Abp.IdentityModel protected virtual async Task GetDiscoveryResponse( IdentityClientConfiguration configuration) { - using (var httpClient = HttpClientFactory.CreateClient()) + using (var httpClient = new HttpClient()) { return await httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest { @@ -112,10 +109,10 @@ namespace Volo.Abp.IdentityModel } protected virtual async Task GetTokenResponse( - DiscoveryDocumentResponse discoveryResponse, + DiscoveryDocumentResponse discoveryResponse, IdentityClientConfiguration configuration) { - using (var httpClient = HttpClientFactory.CreateClient()) + using (var httpClient = new HttpClient()) { switch (configuration.GrantType) { @@ -137,7 +134,7 @@ namespace Volo.Abp.IdentityModel protected virtual Task CreatePasswordTokenRequestAsync(DiscoveryDocumentResponse discoveryResponse, IdentityClientConfiguration configuration) { - var request = new PasswordTokenRequest + var request = new PasswordTokenRequest { Address = discoveryResponse.TokenEndpoint, Scope = configuration.Scope, @@ -152,11 +149,11 @@ namespace Volo.Abp.IdentityModel return Task.FromResult(request); } - protected virtual Task CreateClientCredentialsTokenRequestAsync( - DiscoveryDocumentResponse discoveryResponse, + protected virtual Task CreateClientCredentialsTokenRequestAsync( + DiscoveryDocumentResponse discoveryResponse, IdentityClientConfiguration configuration) { - var request = new ClientCredentialsTokenRequest + var request = new ClientCredentialsTokenRequest { Address = discoveryResponse.TokenEndpoint, Scope = configuration.Scope, diff --git a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs index aee0a26a23..55b64d29de 100644 --- a/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Posts/IPostAppService.cs @@ -9,6 +9,8 @@ namespace Volo.Blogging.Posts { Task> GetListByBlogIdAndTagName(Guid blogId, string tagName); + Task> GetTimeOrderedListAsync(Guid blogId); + Task GetForReadingAsync(GetPostInput input); Task GetAsync(Guid id); diff --git a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs index d798814caa..44b8e9866e 100644 --- a/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs +++ b/modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Posts/PostAppService.cs @@ -44,11 +44,6 @@ namespace Volo.Blogging.Posts postDtos = await FilterPostsByTag(postDtos, tag); } - foreach (var postDto in postDtos) - { - postDto.CommentCount = await _commentRepository.GetCommentCountOfPostAsync(postDto.Id); - } - foreach (var postDto in postDtos) { if (postDto.CreatorId.HasValue) @@ -72,6 +67,24 @@ namespace Volo.Blogging.Posts return new ListResultDto(postDtos); } + public async Task> GetTimeOrderedListAsync(Guid blogId) + { + var posts = await _postRepository.GetOrderedList(blogId); + + var postDtos = new List(ObjectMapper.Map, List>(posts)); + + foreach (var postDto in postDtos) + { + var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value); + if (creatorUser != null) + { + postDto.Writer = ObjectMapper.Map(creatorUser); + } + } + + return new ListResultDto(postDtos); + } + public async Task GetForReadingAsync(GetPostInput input) { var post = await _postRepository.GetPostByUrl(input.BlogId, input.Url); @@ -172,7 +185,7 @@ namespace Volo.Blogging.Posts { var postList = await _postRepository.GetListAsync(); - if (postList.Where(p => p.Url == url).WhereIf(existingPost != null, p => existingPost.Id != p.Id).Any()) + if (postList.Where(p => p.Url == url).WhereIf(existingPost != null, p => existingPost.Id != p.Id).Any()) { return url + "-" + Guid.NewGuid().ToString().Substring(0, 5); } @@ -252,7 +265,7 @@ namespace Volo.Blogging.Posts private Task> FilterPostsByTag(IEnumerable allPostDtos, Tag tag) { var filteredPostDtos = allPostDtos.Where(p => p.Tags?.Any(t => t.Id == tag.Id) ?? false).ToList(); - + return Task.FromResult(filteredPostDtos); } } diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostRepository.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostRepository.cs index d38cd5c0d7..02bd68a6b0 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostRepository.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Posts/IPostRepository.cs @@ -10,5 +10,7 @@ namespace Volo.Blogging.Posts Task> GetPostsByBlogId(Guid id); Task GetPostByUrl(Guid blogId, string url); + + Task> GetOrderedList(Guid blogId,bool descending = false); } } diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs index fd4bec2de4..01c5652902 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/Posts/EfCorePostRepository.cs @@ -35,6 +35,19 @@ namespace Volo.Blogging.Posts return post; } + public async Task> GetOrderedList(Guid blogId,bool descending = false) + { + if (!descending) + { + return await DbSet.Where(x=>x.BlogId==blogId).OrderByDescending(x => x.CreationTime).ToListAsync(); + } + else + { + return await DbSet.Where(x => x.BlogId == blogId).OrderBy(x => x.CreationTime).ToListAsync(); + } + + } + public override IQueryable WithDetails() { return GetQueryable().IncludeDetails(); diff --git a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs index 79e7d920f8..332f60c256 100644 --- a/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs +++ b/modules/blogging/src/Volo.Blogging.HttpApi/Volo/Blogging/PostsController.cs @@ -27,6 +27,13 @@ namespace Volo.Blogging return _postAppService.GetListByBlogIdAndTagName(blogId, tagName); } + [HttpGet] + [Route("{blogId}/all/by-time")] + public Task> GetTimeOrderedListAsync(Guid blogId) + { + return _postAppService.GetTimeOrderedListAsync(blogId); + } + [HttpGet] [Route("read")] public Task GetForReadingAsync(GetPostInput input) @@ -60,5 +67,6 @@ namespace Volo.Blogging { return _postAppService.DeleteAsync(id); } + } } diff --git a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs index 52a614df90..2e7675a898 100644 --- a/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs +++ b/modules/blogging/src/Volo.Blogging.MongoDB/Volo/Blogging/Posts/MongoPostRepository.cs @@ -32,5 +32,17 @@ namespace Volo.Blogging.Posts return post; } + + public async Task> GetOrderedList(Guid blogId, bool @descending = false) + { + var query = GetMongoQueryable().Where(x => x.BlogId == blogId); + + if (!descending) + { + return await query.OrderBy(x => x.CreationTime).ToListAsync(); + } + + return await query.OrderByDescending(x => x.CreationTime).ToListAsync(); + } } }