Browse Source

Merge pull request #1180 from abpframework/Docs-multi-language

Docs multi language
pull/1190/head
Halil İbrahim Kalkan 7 years ago
committed by GitHub
parent
commit
60233fedf2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs
  2. 2
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs
  3. 4
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDefaultDocumentInput.cs
  4. 4
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentInput.cs
  5. 4
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentResourceInput.cs
  6. 4
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetNavigationDocumentInput.cs
  7. 2
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs
  8. 2
      modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/ProjectDto.cs
  9. 4
      modules/docs/src/Volo.Docs.Application/Volo/Docs/DocsApplicationAutoMapperProfile.cs
  10. 62
      modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs
  11. 13
      modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs
  12. 8
      modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConsts.cs
  13. 7
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs
  14. 9
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/LanguageConfig.cs
  15. 11
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/LanguageConfigElement.cs
  16. 20
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs
  17. 34
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs
  18. 7
      modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Projects/DocsProjectController.cs
  19. 9
      modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs
  20. 4
      modules/docs/src/Volo.Docs.Web/DocsWebModule.cs
  21. 3
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs
  22. 20
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml
  23. 51
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs
  24. 2
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js
  25. 4
      modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs

3
modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs

@ -18,7 +18,7 @@ namespace VoloDocs.Web.Pages
_projectAppService = projectAppService;
}
public async Task<IActionResult> OnGet()
public async Task<IActionResult> OnGetAsync()
{
Projects = (await _projectAppService.GetListAsync()).Items;
@ -28,6 +28,7 @@ namespace VoloDocs.Web.Pages
{
projectName = Projects[0].ShortName,
version = DocsAppConsts.Latest,
languageCode = await _projectAppService.GetDefaultLanguageCode(Projects[0].ShortName),
documentName = Projects[0].DefaultDocumentName
});
}

2
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/ContentWithDetailsDto.cs

@ -25,6 +25,8 @@ namespace Volo.Docs.Documents
public string FileName { get; set; }
public string CurrentLanguageCode { get; set; }
public ProjectDto Project { get; set; }
public List<DocumentContributorDto> Contributors { get; set; }

4
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDefaultDocumentInput.cs

@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Docs.Language;
using Volo.Docs.Projects;
namespace Volo.Docs.Documents
@ -10,5 +11,8 @@ namespace Volo.Docs.Documents
[StringLength(ProjectConsts.MaxVersionNameLength)]
public string Version { get; set; }
[StringLength(LanguageConsts.MaxLanguageCodeLength)]
public string LanguageCode { get; set; }
}
}

4
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentInput.cs

@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Docs.Language;
using Volo.Docs.Projects;
namespace Volo.Docs.Documents
@ -14,5 +15,8 @@ namespace Volo.Docs.Documents
[StringLength(ProjectConsts.MaxVersionNameLength)]
public string Version { get; set; }
[StringLength(LanguageConsts.MaxLanguageCodeLength)]
public string LanguageCode { get; set; }
}
}

4
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetDocumentResourceInput.cs

@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Docs.Language;
using Volo.Docs.Projects;
namespace Volo.Docs.Documents
@ -14,5 +15,8 @@ namespace Volo.Docs.Documents
[StringLength(ProjectConsts.MaxVersionNameLength)]
public string Version { get; set; }
[StringLength(LanguageConsts.MaxLanguageCodeLength)]
public string LanguageCode { get; set; }
}
}

4
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/GetNavigationDocumentInput.cs

@ -1,5 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Docs.Language;
using Volo.Docs.Projects;
namespace Volo.Docs.Documents
@ -10,5 +11,8 @@ namespace Volo.Docs.Documents
[StringLength(ProjectConsts.MaxVersionNameLength)]
public string Version { get; set; }
[StringLength(LanguageConsts.MaxLanguageCodeLength)]
public string LanguageCode { get; set; }
}
}

2
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/IProjectAppService.cs

@ -9,6 +9,8 @@ namespace Volo.Docs.Projects
Task<ListResultDto<ProjectDto>> GetListAsync();
Task<ProjectDto> GetAsync(string shortName);
Task<string> GetDefaultLanguageCode(string shortName);
Task<ListResultDto<VersionInfoDto>> GetVersionsAsync(string shortName);
}

2
modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Projects/ProjectDto.cs

@ -26,5 +26,7 @@ namespace Volo.Docs.Projects
public string DocumentStoreType { get; set; }
public Dictionary<string, object> ExtraProperties { get; set; }
public Dictionary<string, string> Languages { get; set; }
}
}

4
modules/docs/src/Volo.Docs.Application/Volo/Docs/DocsApplicationAutoMapperProfile.cs

@ -9,10 +9,10 @@ namespace Volo.Docs
{
public DocsApplicationAutoMapperProfile()
{
CreateMap<Project, ProjectDto>();
CreateMap<Project, ProjectDto>().Ignore(x=>x.Languages);
CreateMap<VersionInfo, VersionInfoDto>();
CreateMap<Document, DocumentWithDetailsDto>()
.Ignore(x => x.Project).Ignore(x => x.Contributors);
.Ignore(x => x.Project).Ignore(x => x.Contributors).Ignore(x => x.CurrentLanguageCode);
CreateMap<DocumentContributor, DocumentContributorDto>();
CreateMap<DocumentResource, DocumentResourceDto>();
}

62
modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
@ -15,17 +16,20 @@ namespace Volo.Docs.Documents
private readonly IProjectRepository _projectRepository;
private readonly IDocumentStoreFactory _documentStoreFactory;
protected IDistributedCache<DocumentWithDetailsDto> DocumentCache { get; }
protected IDistributedCache<LanguageConfig> LanguageCache { get; }
protected IDistributedCache<DocumentResourceDto> ResourceCache { get; }
public DocumentAppService(
IProjectRepository projectRepository,
IDocumentStoreFactory documentStoreFactory,
IDistributedCache<DocumentWithDetailsDto> documentCache,
IDistributedCache<LanguageConfig> languageCache,
IDistributedCache<DocumentResourceDto> resourceCache)
{
_projectRepository = projectRepository;
_documentStoreFactory = documentStoreFactory;
DocumentCache = documentCache;
LanguageCache = languageCache;
ResourceCache = resourceCache;
}
@ -33,9 +37,10 @@ namespace Volo.Docs.Documents
{
var project = await _projectRepository.GetAsync(input.ProjectId);
return await GetDocumentWithDetailsDto(
return await GetDocument(
project,
input.Name,
input.LanguageCode,
input.Version
);
}
@ -44,9 +49,10 @@ namespace Volo.Docs.Documents
{
var project = await _projectRepository.GetAsync(input.ProjectId);
return await GetDocumentWithDetailsDto(
return await GetDocument(
project,
project.DefaultDocumentName,
input.LanguageCode,
input.Version
);
}
@ -55,9 +61,10 @@ namespace Volo.Docs.Documents
{
var project = await _projectRepository.GetAsync(input.ProjectId);
return await GetDocumentWithDetailsDto(
return await GetDocument(
project,
project.NavigationDocumentName,
input.LanguageCode,
input.Version
);
}
@ -65,12 +72,12 @@ namespace Volo.Docs.Documents
public async Task<DocumentResourceDto> GetResourceAsync(GetDocumentResourceInput input)
{
var project = await _projectRepository.GetAsync(input.ProjectId);
var cacheKey = $"Resource@{project.ShortName}#{input.Name}#{input.Version}";
var cacheKey = $"Resource@{project.ShortName}#{input.LanguageCode}#{input.Name}#{input.Version}";
async Task<DocumentResourceDto> GetResourceAsync()
{
var store = _documentStoreFactory.Create(project.DocumentStoreType);
var documentResource = await store.GetResource(project, input.Name, input.Version);
var documentResource = await store.GetResource(project, input.Name, input.LanguageCode, input.Version);
return ObjectMapper.Map<DocumentResource, DocumentResourceDto>(documentResource);
}
@ -92,20 +99,23 @@ namespace Volo.Docs.Documents
);
}
protected virtual async Task<DocumentWithDetailsDto> GetDocumentWithDetailsDto(
protected virtual async Task<DocumentWithDetailsDto> GetDocument(
Project project,
string documentName,
string languageCode,
string version)
{
var cacheKey = $"Document@{project.ShortName}#{documentName}#{version}";
var cacheKey = $"Document@{project.ShortName}#{languageCode}#{documentName}#{version}";
async Task<DocumentWithDetailsDto> GetDocumentAsync()
{
Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the store...");
var store = _documentStoreFactory.Create(project.DocumentStoreType);
var document = await store.GetDocumentAsync(project, documentName, version);
var languages = await GetLanguageListAsync(store, project, version);
var language = GetLanguageByCode(languages, languageCode);
var document = await store.GetDocumentAsync(project, documentName, language.Code, version);
Logger.LogInformation($"Document retrieved: {documentName}");
return CreateDocumentWithDetailsDto(project, document);
return CreateDocumentWithDetailsDto(project, document, languages, language.Code);
}
if (Debugger.IsAttached)
@ -125,11 +135,43 @@ namespace Volo.Docs.Documents
);
}
protected virtual DocumentWithDetailsDto CreateDocumentWithDetailsDto(Project project, Document document)
protected virtual LanguageConfigElement GetLanguageByCode(LanguageConfig languageCodes, string languageCode)
{
var language = languageCodes.Languages.FirstOrDefault(l => l.Code == languageCode);
return language ?? languageCodes.Languages.Single(l => l.IsDefault);
}
protected virtual async Task<LanguageConfig> GetLanguageListAsync(IDocumentStore store, Project project, string version)
{
async Task<LanguageConfig> GetLanguagesAsync()
{
return await store.GetLanguageListAsync(project, version);
}
return await LanguageCache.GetOrAddAsync(
project.ShortName,
GetLanguagesAsync,
() => new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(24)
}
);
}
protected virtual DocumentWithDetailsDto CreateDocumentWithDetailsDto(Project project, Document document, LanguageConfig languages, string languageCode)
{
var documentDto = ObjectMapper.Map<Document, DocumentWithDetailsDto>(document);
documentDto.Project = ObjectMapper.Map<Project, ProjectDto>(project);
documentDto.Contributors = ObjectMapper.Map<List<DocumentContributor>, List<DocumentContributorDto>>(document.Contributors);
documentDto.Project.Languages = new Dictionary<string, string>();
foreach (var language in languages.Languages)
{
documentDto.Project.Languages.Add(language.Code, language.DisplayName);
}
documentDto.CurrentLanguageCode = languageCode;
return documentDto;
}
}

13
modules/docs/src/Volo.Docs.Application/Volo/Docs/Projects/ProjectAppService.cs

@ -16,17 +16,15 @@ namespace Volo.Docs.Projects
private readonly IProjectRepository _projectRepository;
private readonly IDistributedCache<List<VersionInfo>> _versionCache;
private readonly IDocumentStoreFactory _documentStoreFactory;
private readonly IGuidGenerator _guidGenerator;
public ProjectAppService(
IProjectRepository projectRepository,
IDistributedCache<List<VersionInfo>> versionCache,
IDocumentStoreFactory documentStoreFactory, IGuidGenerator guidGenerator)
IDocumentStoreFactory documentStoreFactory)
{
_projectRepository = projectRepository;
_versionCache = versionCache;
_documentStoreFactory = documentStoreFactory;
_guidGenerator = guidGenerator;
}
public async Task<ListResultDto<ProjectDto>> GetListAsync()
@ -45,6 +43,15 @@ namespace Volo.Docs.Projects
return ObjectMapper.Map<Project, ProjectDto>(project);
}
public async Task<string> GetDefaultLanguageCode(string shortName)
{
var project = await _projectRepository.GetByShortNameAsync(shortName);
var store = _documentStoreFactory.Create(project.DocumentStoreType);
var languageList = await store.GetLanguageListAsync(project, project.LatestVersionBranchName);
return languageList.Languages.Single(l=>l.IsDefault).Code;
}
public async Task<ListResultDto<VersionInfoDto>> GetVersionsAsync(string shortName)
{
var project = await _projectRepository.GetByShortNameAsync(shortName);

8
modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/Language/LanguageConsts.cs

@ -0,0 +1,8 @@

namespace Volo.Docs.Language
{
public static class LanguageConsts
{
public const int MaxLanguageCodeLength = 10;
}
}

7
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentStore.cs

@ -1,16 +1,19 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.Docs.GitHub.Documents;
using Volo.Docs.Projects;
namespace Volo.Docs.Documents
{
public interface IDocumentStore : IDomainService
{
Task<Document> GetDocumentAsync(Project project, string documentName, string version);
Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version);
Task<List<VersionInfo>> GetVersionsAsync(Project project);
Task<DocumentResource> GetResource(Project project, string resourceName, string version);
Task<DocumentResource> GetResource(Project project, string resourceName, string languageCode, string version);
Task<LanguageConfig> GetLanguageListAsync(Project project, string version);
}
}

9
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/LanguageConfig.cs

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Volo.Docs.Documents
{
public class LanguageConfig
{
public List<LanguageConfigElement> Languages { get; set; }
}
}

11
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/LanguageConfigElement.cs

@ -0,0 +1,11 @@
namespace Volo.Docs.Documents
{
public class LanguageConfigElement
{
public string DisplayName { get; set; }
public string Code { get; set; }
public bool IsDefault { get; set; }
}
}

20
modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentStore.cs

@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Volo.Abp.Domain.Services;
using Volo.Abp.IO;
using Volo.Docs.Documents;
@ -14,10 +16,10 @@ namespace Volo.Docs.FileSystem.Documents
{
public const string Type = "FileSystem";
public async Task<Document> GetDocumentAsync(Project project, string documentName, string version)
public async Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version)
{
var projectFolder = project.GetFileSystemPath();
var path = Path.Combine(projectFolder, documentName);
var path = Path.Combine(projectFolder, languageCode, documentName);
CheckDirectorySecurity(projectFolder, path);
@ -46,10 +48,18 @@ namespace Volo.Docs.FileSystem.Documents
return Task.FromResult(new List<VersionInfo>());
}
public async Task<DocumentResource> GetResource(Project project, string resourceName, string version)
public async Task<LanguageConfig> GetLanguageListAsync(Project project, string version)
{
var path = Path.Combine(project.GetFileSystemPath(), "languageConfig.json");
var configAsJson = await FileHelper.ReadAllTextAsync(path);
return JsonConvert.DeserializeObject<LanguageConfig>(configAsJson);
}
public async Task<DocumentResource> GetResource(Project project, string resourceName, string languageCode, string version)
{
var projectFolder = project.GetFileSystemPath();
var path = Path.Combine(projectFolder, resourceName);
var path = Path.Combine(projectFolder, languageCode, resourceName);
if (!DirectoryHelper.IsSubDirectoryOf(projectFolder, path))
{

34
modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentStore.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Volo.Abp.Domain.Services;
using Volo.Docs.Documents;
using Volo.Docs.GitHub.Projects;
@ -27,14 +28,14 @@ namespace Volo.Docs.GitHub.Documents
_githubRepositoryManager = githubRepositoryManager;
}
public virtual async Task<Document> GetDocumentAsync(Project project, string documentName, string version)
public virtual async Task<Document> GetDocumentAsync(Project project, string documentName, string languageCode, string version)
{
var token = project.GetGitHubAccessTokenOrNull();
var rootUrl = project.GetGitHubUrl(version);
var rawRootUrl = CalculateRawRootUrl(rootUrl);
var userAgent = project.GetGithubUserAgentOrNull();
var rawRootUrl = CalculateRawRootUrlWithLanguageCode(rootUrl, languageCode);
var rawDocumentUrl = rawRootUrl + documentName;
var commitHistoryUrl = project.GetGitHubUrlForCommitHistory() + documentName;
var userAgent = project.GetGithubUserAgentOrNull();
var isNavigationDocument = documentName == project.NavigationDocumentName;
var editLink = rootUrl.ReplaceFirst("/tree/", "/blob/") + documentName;
var localDirectory = "";
@ -90,9 +91,9 @@ namespace Volo.Docs.GitHub.Documents
return versions;
}
public async Task<DocumentResource> GetResource(Project project, string resourceName, string version)
public async Task<DocumentResource> GetResource(Project project, string resourceName, string languageCode, string version)
{
var rawRootUrl = CalculateRawRootUrl(project.GetGitHubUrl(version));
var rawRootUrl = CalculateRawRootUrlWithLanguageCode(project.GetGitHubUrl(version), languageCode);
var content = await DownloadWebContentAsByteArrayAsync(
rawRootUrl + resourceName,
project.GetGitHubAccessTokenOrNull(),
@ -102,6 +103,19 @@ namespace Volo.Docs.GitHub.Documents
return new DocumentResource(content);
}
public async Task<LanguageConfig> GetLanguageListAsync(Project project, string version)
{
var token = project.GetGitHubAccessTokenOrNull();
var rootUrl = project.GetGitHubUrl(version);
var userAgent = project.GetGithubUserAgentOrNull();
var url = CalculateRawRootUrl(rootUrl) + "languageConfig.json";
var configAsJson = await DownloadWebContentAsStringAsync(url, token, userAgent);
return JsonConvert.DeserializeObject<LanguageConfig>(configAsJson);
}
private async Task<IReadOnlyList<Release>> GetReleasesAsync(Project project)
{
var url = project.GetGitHubUrl();
@ -202,6 +216,16 @@ namespace Volo.Docs.GitHub.Documents
return contributors;
}
private static string CalculateRawRootUrlWithLanguageCode(string rootUrl, string languageCode)
{
return (rootUrl
.Replace("github.com", "raw.githubusercontent.com")
.ReplaceFirst("/tree/", "/")
.EnsureEndsWith('/')
+ languageCode
).EnsureEndsWith('/');
}
private static string CalculateRawRootUrl(string rootUrl)
{
return rootUrl

7
modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Projects/DocsProjectController.cs

@ -34,6 +34,13 @@ namespace Volo.Docs.Projects
return ProjectAppService.GetAsync(shortName);
}
[HttpGet]
[Route("{shortName}/defaultLanguage")]
public Task<string> GetDefaultLanguageCode(string shortName)
{
return ProjectAppService.GetDefaultLanguageCode(shortName);
}
[HttpGet]
[Route("{shortName}/versions")]
public virtual Task<ListResultDto<VersionInfoDto>> GetVersionsAsync(string shortName)

9
modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs

@ -35,6 +35,9 @@ namespace Volo.Docs.Areas.Documents.TagHelpers
[HtmlAttributeName("project-format")]
public string ProjectFormat { get; set; }
[HtmlAttributeName("language")]
public string LanguageCode { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var content = new StringBuilder();
@ -107,7 +110,7 @@ namespace Volo.Docs.Areas.Documents.TagHelpers
}
else
{
listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path, node.HasChildItems), textCss, node.Text.IsNullOrEmpty() ? "?" : node.Text);
listInnerItem = string.Format(ListItemAnchor, NormalizePath(node.Path), textCss, node.Text.IsNullOrEmpty() ? "?" : node.Text);
}
return string.Format(LiItemTemplateWithLink,
@ -117,7 +120,7 @@ namespace Volo.Docs.Areas.Documents.TagHelpers
content);
}
private string NormalizePath(string path, bool hasChildItems)
private string NormalizePath(string path)
{
if (UrlHelper.IsExternalLink(path))
{
@ -131,7 +134,7 @@ namespace Volo.Docs.Areas.Documents.TagHelpers
return "javascript:;";
}
return "/documents/" + ProjectName + "/" + Version + "/" + pathWithoutFileExtension;
return "/documents/" + LanguageCode + "/" + ProjectName + "/" + Version + "/" + pathWithoutFileExtension;
}
private string RemoveFileExtensionFromPath(string path)

4
modules/docs/src/Volo.Docs.Web/DocsWebModule.cs

@ -39,8 +39,8 @@ namespace Volo.Docs
{
//TODO: Make configurable!
options.Conventions.AddPageRoute("/Documents/Project/Index", "documents/{projectName}");
options.Conventions.AddPageRoute("/Documents/Project/Index", "documents/{projectName}/{version}/{*documentName}");
options.Conventions.AddPageRoute("/Documents/Project/Index", "documents/{languageCode}/{projectName}");
options.Conventions.AddPageRoute("/Documents/Project/Index", "documents/{languageCode}/{projectName}/{version}/{*documentName}");
});
Configure<AbpAutoMapperOptions>(options =>

3
modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs

@ -17,7 +17,7 @@ namespace Volo.Docs.Pages.Documents
_projectAppService = projectAppService;
}
public async Task<IActionResult> OnGet()
public async Task<IActionResult> OnGetAsync()
{
var listResult = await _projectAppService.GetListAsync();
@ -27,6 +27,7 @@ namespace Volo.Docs.Pages.Documents
{
projectName = listResult.Items[0].ShortName,
version = DocsAppConsts.Latest,
languageCode = await _projectAppService.GetDefaultLanguageCode(listResult.Items[0].ShortName),
documentName = listResult.Items[0].DefaultDocumentName
});
}

20
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml

@ -107,7 +107,7 @@
</div>
}
<div class="docs-version">
<div class="docs-version">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
@ -116,7 +116,7 @@
<input class="form-control" type="search" placeholder="Filter topics" aria-label="Filter">
</div>
</div>
</div>
</div>
@if (Model.Navigation == null || Model.Navigation.Content.IsNullOrEmpty())
@ -132,6 +132,7 @@
project-name="@Model.ProjectName"
project-format="@Model.Project.Format"
selected-document-name="@Model.DocumentNameWithExtension"
language="@Model.LanguageCode"
id="sidebar-scroll"
class="nav nav-list"></ul>
}
@ -158,10 +159,17 @@
</a>
</div>
@if (!string.IsNullOrEmpty(Model.Document.EditLink))
{
<a href="@Model.Document.EditLink" target="_blank"> <i class="fa fa-edit"></i> @L["Edit"]</a>
}
<div class="float-right">
@if (Model.LanguageSelectListItems.Count > 1)
{
<select asp-items="Model.LanguageSelectListItems" class="mr-2" onchange="window.location.replace(this.value)"></select>
}
@if (!string.IsNullOrEmpty(Model.Document.EditLink))
{
<a href="@Model.Document.EditLink" target="_blank"> <i class="fa fa-edit"></i> @L["Edit"]</a>
}
</div>
</div>
<div class="docs-content-field">

51
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Volo.Abp.AspNetCore.Mvc.UI.RazorPages;
using Volo.Abp.Localization;
using Volo.Docs.Documents;
using Volo.Docs.HtmlConverting;
using Volo.Docs.Models;
@ -23,8 +24,13 @@ namespace Volo.Docs.Pages.Documents.Project
[BindProperty(SupportsGet = true)]
public string DocumentName { get; set; }
[BindProperty(SupportsGet = true)]
public string LanguageCode { get; set; }
public ProjectDto Project { get; set; }
public List<SelectListItem> LanguageSelectListItems { get; set; }
public string DocumentNameWithExtension { get; private set; }
public DocumentWithDetailsDto Document { get; private set; }
@ -58,6 +64,8 @@ namespace Volo.Docs.Pages.Documents.Project
await SetVersionAsync();
await SetDocumentAsync();
await SetNavigationAsync();
SetLanguageSelectListItems();
AddLanguageCodePrefixToLinks();
}
private async Task SetProjectAsync()
@ -72,7 +80,7 @@ namespace Volo.Docs.Pages.Documents.Project
ProjectSelectItems = projects.Items.Select(p => new SelectListItem
{
Text = p.Name,
Value = p.Id != Project.Id ? "/documents/" + p.ShortName + "/" + DocsAppConsts.Latest : null,
Value = p.Id != Project.Id ? "/documents/" + LanguageCode + "/" + p.ShortName + "/" + DocsAppConsts.Latest : null,
Selected = p.Id == Project.Id
}).ToList();
}
@ -133,6 +141,7 @@ namespace Volo.Docs.Pages.Documents.Project
new GetNavigationDocumentInput
{
ProjectId = Project.Id,
LanguageCode = LanguageCode,
Version = Version
}
);
@ -144,6 +153,8 @@ namespace Volo.Docs.Pages.Documents.Project
return;
}
LanguageCode = Document.CurrentLanguageCode;
Navigation.ConvertItems();
}
@ -154,7 +165,7 @@ namespace Volo.Docs.Pages.Documents.Project
version = DocsAppConsts.Latest;
}
var link = "/documents/" + ProjectName + "/" + version;
var link = "/documents/" + LanguageCode + "/" + ProjectName + "/" + version;
if (documentName != null)
{
@ -193,6 +204,7 @@ namespace Volo.Docs.Pages.Documents.Project
new GetDefaultDocumentInput
{
ProjectId = Project.Id,
LanguageCode = LanguageCode,
Version = Version
}
);
@ -204,20 +216,46 @@ namespace Volo.Docs.Pages.Documents.Project
{
ProjectId = Project.Id,
Name = DocumentNameWithExtension,
LanguageCode = LanguageCode,
Version = Version
}
);
}
}
catch (DocumentNotFoundException)
{
//TODO: Handle it!
throw;
Document = await _documentAppService.GetDefaultAsync(
new GetDefaultDocumentInput
{
ProjectId = Project.Id,
LanguageCode = LanguageCode,
Version = Version
}
);
}
LanguageCode = Document.CurrentLanguageCode;
ConvertDocumentContentToHtml();
}
private void SetLanguageSelectListItems()
{
LanguageSelectListItems = new List<SelectListItem>();
foreach (var language in Document.Project.Languages)
{
LanguageSelectListItems.Add(
new SelectListItem(
language.Value,
"/documents/" + language.Key + "/" + Project.ShortName + "/" + Version + "/" + DocumentName,
language.Key == LanguageCode
)
);
}
}
private void ConvertDocumentContentToHtml()
{
var converter = _documentToHtmlConverterFactory.Create(Document.Format ?? Project.Format);
@ -238,5 +276,10 @@ namespace Volo.Docs.Pages.Documents.Project
Document.Content = content;
}
private void AddLanguageCodePrefixToLinks()
{
Document.Content = Document.Content.Replace("href=\"/documents", "href=\"/documents/" + LanguageCode);
}
}
}

2
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js

@ -1,11 +1,11 @@
(function ($) {
$(function () {
var initNavigationFilter = function (navigationContainerId) {
var $navigation = $("#" + navigationContainerId);
var getShownDocumentLinks = function () {
return $navigation.find(".mCSB_container > li a:visible").not(".tree-toggle");
};

4
modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/GithubDocumentStore_Tests.cs

@ -28,7 +28,7 @@ namespace Volo.Docs
var project = await _projectRepository.FindAsync(_testData.PorjectId);
project.ShouldNotBeNull();
var document = await store.GetDocumentAsync(project, "index2", "0.123.0");
var document = await store.GetDocumentAsync(project, "index2", "en", "0.123.0");
document.ShouldNotBeNull();
document.Title.ShouldBe("index2");
@ -60,7 +60,7 @@ namespace Volo.Docs
var project = await _projectRepository.FindAsync(_testData.PorjectId);
project.ShouldNotBeNull();
var documentResource = await store.GetResource(project, "index.md", "0.123.0");
var documentResource = await store.GetResource(project, "index.md", "en", "0.123.0");
documentResource.ShouldNotBeNull();
documentResource.Content.ShouldBe(new byte[]

Loading…
Cancel
Save