Create DocumentNotFoundPage

https://github.com/volosoft/volo/issues/751
pull/2797/head
Yunus Emre Kalkan 6 years ago
parent 1a84e8ade1
commit 9a2e84de68

@ -57,9 +57,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.Web", "app\VoloDoc
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VoloDocs.Migrator", "app\VoloDocs.Migrator\VoloDocs.Migrator.csproj", "{8A5E5001-C017-44A8-ADDA-DC66C102556E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.MongoDB", "src\Volo.Docs.MongoDB\Volo.Docs.MongoDB.csproj", "{DBE846CD-1BED-4F2C-ABF2-94F6240BCB9B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.MongoDB", "src\Volo.Docs.MongoDB\Volo.Docs.MongoDB.csproj", "{DBE846CD-1BED-4F2C-ABF2-94F6240BCB9B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Docs.MongoDB.Tests", "test\Volo.Docs.MongoDB.Tests\Volo.Docs.MongoDB.Tests.csproj", "{C5E2A2A3-D54D-4C2E-97BA-EA50A49ED7AD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Docs.MongoDB.Tests", "test\Volo.Docs.MongoDB.Tests\Volo.Docs.MongoDB.Tests.csproj", "{C5E2A2A3-D54D-4C2E-97BA-EA50A49ED7AD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

@ -5,7 +5,9 @@ using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Packages;
using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
@ -18,7 +20,11 @@ namespace Volo.Docs
{
[DependsOn(
typeof(DocsHttpApiModule),
typeof(AbpAspNetCoreMvcUiBootstrapModule)
typeof(AbpAutoMapperModule),
typeof(AbpAspNetCoreMvcUiBootstrapModule),
typeof(AbpAspNetCoreMvcUiThemeSharedModule),
typeof(AbpAspNetCoreMvcUiPackagesModule),
typeof(AbpAspNetCoreMvcUiBundlingModule)
)]
public class DocsWebModule : AbpModule
{

@ -7,6 +7,7 @@
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Popper
@using Volo.Abp.AspNetCore.Mvc.UI.Packages.Prismjs
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@using Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
@using Volo.Docs
@using Volo.Docs.Localization
@using Volo.Docs.Pages.Documents.Project
@ -39,268 +40,283 @@
<abp-script src="/Pages/Documents/Project/index.js" />
</abp-script-bundle>
}
<div class="docs-page" data-spy="scroll" data-target="#docs-sticky-index">
<div class="row justify-content-end">
<div class="col-md-3 docs-sidebar dark-sidebar">
<div class="docs-sidebar-wrapper">
@if (Model.DocumentFound)
{
<div class="docs-page" data-spy="scroll" data-target="#docs-sticky-index">
<div class="row justify-content-end">
<div class="col-md-3 docs-sidebar dark-sidebar">
<div class="docs-sidebar-wrapper">
<div class="docs-top">
<nav class="navbar navbar-logo">
@if (!Model.Project.Name.IsNullOrWhiteSpace())
{
<a class="navbar-brand w-100" href="@Model.CreateVersionLink(Model.LatestVersionInfo, Model.GetSpecificVersionOrLatest())">
<span id="ProjectName">@Model.Project.Name</span><br>
<strong class="display-block">
@L["Documents"]
</strong>
</a>
}
@if (!Model.Document.Project.MainWebsiteUrl.IsNullOrWhiteSpace())
{
<a href="@Model.Document.Project.MainWebsiteUrl" class="go-back-site" id="GoToMainWebSite">
<i class="fa fa-chevron-left"></i>
@L["BackToWebsite"]
</a>
}
<div class="for-mobile">
<div class="navbar-light">
<button type="button" class="open-dmenu navbar-toggler" aria-label="Close">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
</nav>
</div>
<div class="docs-tree-list">
<div class="docs-top">
<nav class="navbar navbar-logo">
@if (!Model.Project.Name.IsNullOrWhiteSpace())
{
<a class="navbar-brand w-100" href="@Model.CreateVersionLink(Model.LatestVersionInfo, Model.GetSpecificVersionOrLatest())">
<span id="ProjectName">@Model.Project.Name</span><br>
<strong class="display-block">
@L["Documents"]
</strong>
</a>
}
@if (Model.ShowProjectsCombobox && Model.ProjectSelectItems.Count > 1)
{
<div class="docs-version">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text">
<i class="fa fa-folder-open" aria-hidden="true" data-toggle="tooltip" title="@L["Project"]"></i>
</label>
</div>
@if (!Model.Document.Project.MainWebsiteUrl.IsNullOrWhiteSpace())
{
<a href="@Model.Document.Project.MainWebsiteUrl" class="go-back-site" id="GoToMainWebSite">
<i class="fa fa-chevron-left"></i>
@L["BackToWebsite"]
</a>
}
<select asp-items="Model.ProjectSelectItems" class="form-control" onchange="window.location.pathname = this.value"></select>
<div class="for-mobile">
<div class="navbar-light">
<button type="button" class="open-dmenu navbar-toggler" aria-label="Close">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
</div>
}
</nav>
</div>
<div class="row">
@if (Model.VersionSelectItems.Any())
{
<div class="col @(Model.LanguageSelectListItems.Count > 1?"pr-0":"")">
<div class="docs-version @(Model.LanguageSelectListItems.Count > 1?"pr-1":"")">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text">
<i class="fa fa-check-square-o" aria-hidden="true" data-toggle="tooltip" title="@L["Version"]"></i>
</label>
</div>
<div class="docs-tree-list">
<select asp-items="Model.VersionSelectItems" class="form-control" onchange="if (this.value) { window.location.replace(this.value) }"></select>
@if (Model.ShowProjectsCombobox && Model.ProjectSelectItems.Count > 1)
{
<div class="docs-version">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text">
<i class="fa fa-folder-open" aria-hidden="true" data-toggle="tooltip" title="@L["Project"]"></i>
</label>
</div>
<select asp-items="Model.ProjectSelectItems" class="form-control" onchange="window.location.pathname = this.value"></select>
</div>
</div>
</div>
}
@if (Model.LanguageSelectListItems.Count > 1)
{
<div class="col @(Model.VersionSelectItems.Any()?"pl-0":"")">
<div class="docs-version docs-language @(Model.VersionSelectItems.Any()?"pl-1":"")">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text">
<i class="fa fa-globe" aria-hidden="true" data-toggle="tooltip" title="@L["Language"]"></i>
</label>
<div class="row">
@if (Model.VersionSelectItems.Any())
{
<div class="col @(Model.LanguageSelectListItems.Count > 1 ? "pr-0" : "")">
<div class="docs-version @(Model.LanguageSelectListItems.Count > 1 ? "pr-1" : "")">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text">
<i class="fa fa-check-square-o" aria-hidden="true" data-toggle="tooltip" title="@L["Version"]"></i>
</label>
</div>
<select asp-items="Model.VersionSelectItems" class="form-control" onchange="if (this.value) { window.location.replace(this.value) }"></select>
</div>
<select asp-items="Model.LanguageSelectListItems" class="form-control" onchange="window.location.replace(this.value)"></select>
</div>
</div>
</div>
</div>
}
</div>
}
<div class="docs-version mb-4">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text"><i class="fa fa-filter"></i></label>
@if (Model.LanguageSelectListItems.Count > 1)
{
<div class="col @(Model.VersionSelectItems.Any() ? "pl-0" : "")">
<div class="docs-version docs-language @(Model.VersionSelectItems.Any() ? "pl-1" : "")">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text">
<i class="fa fa-globe" aria-hidden="true" data-toggle="tooltip" title="@L["Language"]"></i>
</label>
</div>
<select asp-items="Model.LanguageSelectListItems" class="form-control" onchange="window.location.replace(this.value)"></select>
</div>
</div>
</div>
</div>
<input class="form-control" type="search" placeholder="@L["FilterTopics"].Value" aria-label="Filter">
</div>
}
</div>
</div>
<div class="docs-version mb-4">
<div class="version-select">
<div class="input-group">
<div class="input-group-prepend">
<label class="input-group-text"><i class="fa fa-filter"></i></label>
</div>
@if (Model.Navigation == null || Model.Navigation.Content.IsNullOrEmpty())
{
<div class="text-muted p-3">
<i class="fa fa-warning"></i> @L["NavigationDocumentNotFound"]
<input class="form-control" type="search" placeholder="@L["FilterTopics"].Value" aria-label="Filter">
</div>
</div>
</div>
}
else
{
<ul root-node="@Model.Navigation.RootNode"
version="@(Model.LatestVersionInfo == null || Model.LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Model.Version)"
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>
}
</div>
</div>
</div>
@if (Model.Document != null)
{
<div class="col-md-7 docs-content bg-white">
<div class="docs-link-btns">
<div class="float-left">
@(L["ShareOn"].Value + " :")
<a href="#" target="_blank" class="share-button twitter" id="TwitterShareLink" title="Twitter">
<i class="fa fa-twitter"></i>
</a>
<a href="#" target="_blank" class="share-button linkedin" id="LinkedinShareLink" title="LinkedIn">
<i class="fa fa-linkedin"></i>
</a>
<a href="#" target="_blank" class="share-button email" id="EmailShareLink" title="E-mail">
<i class="fa fa-envelope-square"></i>
</a>
</div>
<div class="float-right">
@if (!string.IsNullOrEmpty(Model.Document.EditLink))
@if (Model.Navigation == null || Model.Navigation.Content.IsNullOrEmpty())
{
<div class="text-muted p-3">
<i class="fa fa-warning"></i> @L["NavigationDocumentNotFound"]
</div>
}
else
{
<a href="@Model.Document.EditLink" target="_blank"> <i class="fa fa-edit"></i> @L["Edit"]</a>
<ul root-node="@Model.Navigation.RootNode"
version="@(Model.LatestVersionInfo == null || Model.LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Model.Version)"
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>
}
</div>
</div>
</div>
<div class="docs-content-field">
<div class="docs-text-field">
<div class="position-relative">
@if (Model.Document.Contributors != null && Model.Document.Contributors.Count > 0)
{
<div class="contributors">
<small class="text-muted">@(L["Contributors"].Value + " :")</small>
@foreach (var contributor in Model.Document.Contributors)
{
<a href="@contributor.UserProfileUrl" target="_blank">
<img src="@contributor.AvatarUrl"
class="contributors-avatar" height="21" width="21" title="@contributor.Username" />
</a>
}
</div>
}
@if (Model.Document != null)
{
<div class="col-md-7 docs-content bg-white">
<div class="docs-link-btns">
<div class="float-left">
@(L["ShareOn"].Value + " :")
<a href="#" target="_blank" class="share-button twitter" id="TwitterShareLink" title="Twitter">
<i class="fa fa-twitter"></i>
</a>
<a href="#" target="_blank" class="share-button linkedin" id="LinkedinShareLink" title="LinkedIn">
<i class="fa fa-linkedin"></i>
</a>
<a href="#" target="_blank" class="share-button email" id="EmailShareLink" title="E-mail">
<i class="fa fa-envelope-square"></i>
</a>
</div>
@if (Model.DocumentPreferences != null && Model.DocumentPreferences.Parameters != null && Model.DocumentPreferences.Parameters.Any())
<div class="float-right">
@if (!string.IsNullOrEmpty(Model.Document.EditLink))
{
<div class="alert alert-primary alert-criteria">
<abp-row>
<abp-column>
<p class="alert-p mb-2">
<i class="fa fa-info-circle"></i>
@L["MultipleVersionDocumentInfo"]
</p>
</abp-column>
</abp-row>
<abp-form-row>
@foreach (var parameter in Model.DocumentPreferences.Parameters)
{
<abp-column size="_4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="@("Section" + parameter.Name + "ComboboxAddonId")">@(parameter.DisplayName)</span>
</div>
<select class="doc-section-combobox form-control"
aria-describedby="@("Section" + parameter.Name + "ComboboxAddonId")"
id="@("Section" + parameter.Name + "ComboboxId")" data-key="@parameter.Name">
@foreach (var value in parameter.Values)
{
@if (value.Key == (Model.UserPreferences.ContainsKey(parameter.Name) ? Model.UserPreferences[parameter.Name] : null))
{
<option value="@value.Key" selected="selected">@value.Value</option>
}
else
{
<option value="@value.Key">@value.Value</option>
}
}
</select>
</div>
</abp-column>
}
</abp-form-row>
</div>
<a href="@Model.Document.EditLink" target="_blank"> <i class="fa fa-edit"></i> @L["Edit"]</a>
}
</div>
</div>
<div data-spy="scroll" data-target="#docs-sticky-index" data-offset="0">
<article class="docs-body">
<div class="docs-content-field">
<div class="docs-text-field">
<div class="position-relative">
@if (Model.Document.Contributors != null && Model.Document.Contributors.Count > 0)
{
<div class="contributors">
<small class="text-muted">@(L["Contributors"].Value + " :")</small>
@foreach (var contributor in Model.Document.Contributors)
{
<a href="@contributor.UserProfileUrl" target="_blank">
<img src="@contributor.AvatarUrl"
class="contributors-avatar" height="21" width="21" title="@contributor.Username" />
</a>
}
</div>
}
@if (Model.DocumentLanguageIsDifferent)
@if (Model.DocumentPreferences != null && Model.DocumentPreferences.Parameters != null && Model.DocumentPreferences.Parameters.Any())
{
<abp-alert alert-type="Warning" dismissible="true" class="mb-0">
@L["DocumentNotFoundInSelectedLanguage"]
</abp-alert>
<div class="alert alert-primary alert-criteria">
<abp-row>
<abp-column>
<p class="alert-p mb-2">
<i class="fa fa-info-circle"></i>
@L["MultipleVersionDocumentInfo"]
</p>
</abp-column>
</abp-row>
<abp-form-row>
@foreach (var parameter in Model.DocumentPreferences.Parameters)
{
<abp-column size="_4">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="@("Section" + parameter.Name + "ComboboxAddonId")">@(parameter.DisplayName)</span>
</div>
<select class="doc-section-combobox form-control"
aria-describedby="@("Section" + parameter.Name + "ComboboxAddonId")"
id="@("Section" + parameter.Name + "ComboboxId")" data-key="@parameter.Name">
@foreach (var value in parameter.Values)
{
@if (value.Key == (Model.UserPreferences.ContainsKey(parameter.Name) ? Model.UserPreferences[parameter.Name] : null))
{
<option value="@value.Key" selected="selected">@value.Value</option>
}
else
{
<option value="@value.Key">@value.Value</option>
}
}
</select>
</div>
</abp-column>
}
</abp-form-row>
</div>
}
@Html.Raw(Model.Document.Content)
</article>
</div>
<div data-spy="scroll" data-target="#docs-sticky-index" data-offset="0">
<article class="docs-body">
@if (Model.DocumentLanguageIsDifferent)
{
<abp-alert alert-type="Warning" dismissible="true" class="mb-0">
@L["DocumentNotFoundInSelectedLanguage"]
</abp-alert>
}
@Html.Raw(Model.Document.Content)
</article>
<div id="crawler_link" style="display:none;">
<div id="crawler_link" style="display:none;">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-2 docs-page-index position-relative bg-light">
<div class="col-md-2 docs-page-index position-relative bg-light">
<div id="scroll-index" class="docs-inner-anchors mt-2">
<div id="scroll-index" class="docs-inner-anchors mt-2">
<h5>@L["InThisDocument"]</h5>
<nav id="docs-sticky-index" class="navbar index-scroll">
</nav>
<h5>@L["InThisDocument"]</h5>
<nav id="docs-sticky-index" class="navbar index-scroll">
</nav>
<div class="row">
<div class="col p-0 py-3">
<a href="javascript:;" class="scroll-top-btn"><i class="fa fa-chevron-up"></i> @L["GoToTop"]</a>
<div class="row">
<div class="col p-0 py-3">
<a href="javascript:;" class="scroll-top-btn"><i class="fa fa-chevron-up"></i> @L["GoToTop"]</a>
</div>
</div>
</div>
</div>
</div>
</div>
}
else
{
<div class="col-md-9 p-5 bg-white">
<p>@L["DocumentNotFound"]</p>
}
else
{
<div class="col-md-9 p-5 bg-white">
<p>@L["DocumentNotFound"]</p>
<a href="/">
<i class="fa fa-chevron-left"></i>
@L["BackToWebsite"]
</a>
</div>
}
<a href="/">
<i class="fa fa-chevron-left"></i>
@L["BackToWebsite"]
</a>
</div>
}
</div>
</div>
</div>
}
else
{
@(await Component.InvokeAsync<DocumentNotFoundViewComponent>(new
{
model = new DocumentNotFoundPageModel
{
ProjectName = Model.ProjectName,
DocumentName = Model.DocumentName,
LanguageCode = Model.LanguageCode,
Version = Model.Version,
}
}))
}

@ -33,6 +33,8 @@ namespace Volo.Docs.Pages.Documents.Project
[BindProperty(SupportsGet = true)]
public string LanguageCode { get; set; }
public bool DocumentFound { get; set; } = true;
public string DefaultLanguageCode { get; set; }
public ProjectDto Project { get; set; }
@ -86,6 +88,21 @@ namespace Volo.Docs.Pages.Documents.Project
}
public async Task<IActionResult> OnGetAsync()
{
try
{
return await SetPageAsync();
}
catch (DocumentNotFoundException exception)
{
Logger.LogWarning(exception.Message);
DocumentFound = false;
return Page();
}
}
private async Task<IActionResult> SetPageAsync()
{
DocumentsUrlPrefix = _uiOptions.RoutePrefix;
ShowProjectsCombobox = _uiOptions.ShowProjectsCombobox;

@ -0,0 +1,11 @@
@using Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
@model DocumentNotFoundPageModel
@{
}
<h1>"@Model.DocumentName" not found in "@Model.ProjectName" documents, with "@Model.Version" version and "@Model.LanguageCode" language</h1>
<br/>
<a href="@(Model.DocumentsUrlPrefix + Model.LanguageCode + "/" +Model.ProjectName + "/" + Model.Version)">
click here to return.
</a>

@ -0,0 +1,15 @@
namespace Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
{
public class DocumentNotFoundPageModel
{
public string ProjectName { get; set; }
public string LanguageCode { get; set; }
public string Version { get; set; }
public string DocumentName { get; set; }
public string DocumentsUrlPrefix { get; set; }
}
}

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc;
namespace Volo.Docs.Pages.Documents.Shared.DocumentNotFoundComponent
{
public class DocumentNotFoundViewComponent : AbpViewComponent
{
private readonly DocsUiOptions _options;
public DocumentNotFoundViewComponent(IOptions<DocsUiOptions> options)
{
_options = options.Value;
}
public IViewComponentResult Invoke(DocumentNotFoundPageModel model, string defaultErrorMessageKey)
{
model.DocumentsUrlPrefix = _options.RoutePrefix;
return View("~/Pages/Documents/Shared/DocumentNotFoundComponent/Default.cshtml", model);
}
}
}

@ -18,6 +18,7 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bundling\Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Packages\Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />
<ProjectReference Include="..\Volo.Docs.HttpApi\Volo.Docs.HttpApi.csproj" />
<PackageReference Include="Markdig.Signed" Version="0.18.0" />
<PackageReference Include="Scriban" Version="2.1.1" />

Loading…
Cancel
Save