diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs index c64614e814..e59bf0e357 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs @@ -23,7 +23,5 @@ namespace Volo.Docs.Documents public string FileName { get; set; } public ProjectDto Project { get; set; } - - public bool SuccessfullyRetrieved { get; set; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs index d47ff0dab6..1c4f37ec00 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs @@ -6,6 +6,8 @@ namespace Volo.Docs.Documents { public interface IDocumentAppService : IApplicationService { + //TODO: Create input DTOs for methods and add validation annotations. + Task GetByNameAsync( string projectShortName, string documentName, diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/NavigationWithDetailsDto.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/NavigationWithDetailsDto.cs index 4624a33bf8..a85c6eeb01 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/NavigationWithDetailsDto.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/NavigationWithDetailsDto.cs @@ -10,7 +10,7 @@ namespace Volo.Docs.Documents public void ConvertItems() { - if (!SuccessfullyRetrieved || Content.IsNullOrEmpty()) + if (Content.IsNullOrEmpty()) { RootNode = new NavigationNode(); return; diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/Document.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/Document.cs index d52184f00f..c8ad716607 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/Document.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/Document.cs @@ -19,7 +19,5 @@ namespace Volo.Docs.Documents public string LocalDirectory { get; set; } public string FileName { get; set; } - - public bool SuccessfullyRetrieved { get; set; } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs index f640d023bc..61fed0ee2d 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs @@ -85,16 +85,15 @@ namespace Volo.Docs.Documents return dto; } - public async Task> GetVersions( - string projectShortName - ) + public async Task> GetVersions(string projectShortName) { - var project = await _projectRepository.GetByShortNameAsync(projectShortName); + //TODO: What if there is no version? + var project = await _projectRepository.GetByShortNameAsync(projectShortName); var documentStore = _documentStoreFactory.Create(project.DocumentStoreType); + //TODO: Why not use GetOrAddAsync var versions = await GetVersionsFromCache(projectShortName); - if (versions == null) { versions = await documentStore.GetVersions(project); @@ -125,8 +124,14 @@ namespace Volo.Docs.Documents private async Task SetVersionsToCache(string projectShortName, List versions) { - var options = new DistributedCacheEntryOptions() { SlidingExpiration = TimeSpan.FromDays(1) }; - await _distributedCache.SetAsync(projectShortName, versions, options); + await _distributedCache.SetAsync( + projectShortName, + versions, + new DistributedCacheEntryOptions + { + SlidingExpiration = TimeSpan.FromDays(1) + } + ); } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentStoreFactory.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentStoreFactory.cs index cad104b561..387d4b2d83 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentStoreFactory.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentStoreFactory.cs @@ -13,8 +13,10 @@ namespace Volo.Docs.Documents _serviceProvider = serviceProvider; } - public IDocumentStore Create(string documentStoreType) + public virtual IDocumentStore Create(string documentStoreType) { + //TODO: Should be extensible + switch (documentStoreType) { case GithubDocumentStore.Type: diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/GithubDocumentStore.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/GithubDocumentStore.cs index 488d60652d..061909fd4a 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/GithubDocumentStore.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/GithubDocumentStore.cs @@ -3,13 +3,9 @@ using Octokit; using Octokit.Internal; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Net; -using System.Net.Http; -using System.Net.Sockets; using System.Threading.Tasks; -using Volo.Abp; using Volo.Abp.Domain.Services; using ProductHeaderValue = Octokit.ProductHeaderValue; @@ -19,27 +15,35 @@ namespace Volo.Docs.Documents { public const string Type = "Github"; //TODO: Convert to "github" - public const int DocumentNotFoundExceptionCode = 20181001; - - public async Task Find(Volo.Docs.Projects.Project project, string documentName, string version) + public Task Find( + Projects.Project project, + string documentName, + string version) { - var rootUrl = project.ExtraProperties["GithubRootUrl"].ToString().Replace("_version_/", version + "/").Replace("www.", ""); + var rootUrl = project.GetGithubUrl() + .Replace("_version_/", version + "/") + .Replace("www.", ""); //TODO: Can be a problem? - var token = project.ExtraProperties["GithubAccessToken"]?.ToString(); + var rawRootUrl = rootUrl + .Replace("github.com", "raw.githubusercontent.com") + .Replace("/tree/", "/"); //TODO: Replacing this can be a problem if I have a tree folder inside the repository - var rawRootUrl = rootUrl.Replace("github.com", "raw.githubusercontent.com").Replace("/tree/", "/"); var rawUrl = rawRootUrl + documentName; var editLink = rootUrl.Replace("/tree/", "/blob/") + documentName; - string localDirectory = ""; - string fileName = documentName; + var localDirectory = ""; + var fileName = documentName; if (documentName.Contains("/")) { localDirectory = documentName.Substring(0, documentName.LastIndexOf('/')); - fileName = documentName.Substring(documentName.LastIndexOf('/') + 1, - documentName.Length - documentName.LastIndexOf('/') - 1); + fileName = documentName.Substring( + documentName.LastIndexOf('/') + 1, + documentName.Length - documentName.LastIndexOf('/') - 1 + ); } + var token = project.ExtraProperties["GithubAccessToken"]?.ToString(); //TODO: Define GetGithubAccessToken extension method + var document = new Document { Title = documentName, @@ -50,34 +54,31 @@ namespace Volo.Docs.Documents LocalDirectory = localDirectory, FileName = fileName, Version = version, - SuccessfullyRetrieved = TryDownloadWebContent(rawUrl, token, out var content), - Content = content + Content = DownloadWebContent(rawUrl, token) }; - return await Task.FromResult(document); + return Task.FromResult(document); } - private bool TryDownloadWebContent(string rawUrl, string token, out string content) + private string DownloadWebContent(string rawUrl, string token) { - using (var webClient = new WebClient()) + try { - try + using (var webClient = new WebClient()) { if (!token.IsNullOrWhiteSpace()) { webClient.Headers.Add("Authorization", "token " + token); } - content = webClient.DownloadString(rawUrl); - return true; - } - catch (Exception ex) - { - content = null; - Logger.LogError(ex, ex.Message); - return false; + return webClient.DownloadString(rawUrl); } } + catch (Exception ex) //TODO: Only handle when document is really not available + { + Logger.LogWarning(ex.Message, ex); + throw new DocumentNotFoundException(rawUrl); + } } public async Task> GetVersions(Volo.Docs.Projects.Project project) diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/ProjectGithubExtensions.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/ProjectGithubExtensions.cs new file mode 100644 index 0000000000..efe53e2de1 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/ProjectGithubExtensions.cs @@ -0,0 +1,28 @@ +using System; +using Volo.Docs.Projects; + +namespace Volo.Docs.Documents +{ + public static class ProjectGithubExtensions + { + public static string GetGithubUrl(this Projects.Project project) + { + CheckGithubProject(project); + return project.ExtraProperties["GithubRootUrl"] as string; + } + + public static void SetGithubUrl(this Projects.Project project, string value) + { + CheckGithubProject(project); + project.ExtraProperties["GithubRootUrl"] = value; + } + + private static void CheckGithubProject(Project project) + { + if (project.DocumentStoreType != GithubDocumentStore.Type) + { + throw new ApplicationException("Given project has not a Github document store!"); + } + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/DocumentNotFoundException.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/DocumentNotFoundException.cs new file mode 100644 index 0000000000..877452c260 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/DocumentNotFoundException.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.Serialization; +using Volo.Abp; + +namespace Volo.Docs.Documents +{ + [Serializable] + public class DocumentNotFoundException : BusinessException + { + public string DocumentUrl { get; set; } + + public DocumentNotFoundException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + + public DocumentNotFoundException(string documentUrl) + { + DocumentUrl = documentUrl; + } + } +} diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 798621ff12..4e66bee56b 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -97,7 +97,7 @@ } - @if (!Model.Navigation.SuccessfullyRetrieved || Model.Navigation.Content.IsNullOrEmpty()) + @if (Model.Navigation == null || Model.Navigation.Content.IsNullOrEmpty()) {
@L["NavigationDocumentNotFound"] @@ -118,9 +118,8 @@
- @if (Model.Document.SuccessfullyRetrieved) + @if (Model.Document != null) { -