single post page / admin dashboard
need to go back and revisit dynamic interop and the admin dashboard to see if that can be one query instead of 3
This commit is contained in:
parent
6b24d416fc
commit
2e8d002e30
@ -26,3 +26,11 @@ let getAllCategories conn webLogId =
|
||||
|> runCursorAsync<Category> conn
|
||||
|> Seq.toList
|
||||
|> sortCategories
|
||||
|
||||
/// Count categories for a web log
|
||||
let countCategories conn webLogId =
|
||||
table Table.Category
|
||||
|> getAll [| webLogId |]
|
||||
|> optArg "index" "webLogId"
|
||||
|> count
|
||||
|> runAtomAsync<int> conn
|
||||
|
@ -23,3 +23,20 @@ let tryFindPageWithoutRevisions conn webLogId pageId : Page option =
|
||||
|> box with
|
||||
| null -> None
|
||||
| page -> Some <| unbox page
|
||||
|
||||
/// Find a page by its permalink
|
||||
let tryFindPageByPermalink conn webLogId permalink =
|
||||
table Table.Page
|
||||
|> getAll [| webLogId, permalink |]
|
||||
|> optArg "index" "permalink"
|
||||
|> without [| "revisions" |]
|
||||
|> runCursorAsync<Page> conn
|
||||
|> Seq.tryHead
|
||||
|
||||
/// Count pages for a web log
|
||||
let countPages conn webLogId =
|
||||
table Table.Page
|
||||
|> getAll [| webLogId |]
|
||||
|> optArg "index" "webLogId"
|
||||
|> count
|
||||
|> runAtomAsync<int> conn
|
||||
|
@ -1,8 +1,11 @@
|
||||
module myWebLog.Data.Post
|
||||
|
||||
open FSharp.Interop.Dynamic
|
||||
open myWebLog.Entities
|
||||
open Rethink
|
||||
open RethinkDb.Driver
|
||||
open RethinkDb.Driver.Ast
|
||||
open System.Dynamic
|
||||
|
||||
let private r = RethinkDB.R
|
||||
|
||||
@ -58,6 +61,34 @@ let tryFindPost conn webLogId postId : Post option =
|
||||
| null -> None
|
||||
| post -> Some <| unbox post
|
||||
|
||||
/// Try to find a post by its permalink
|
||||
let tryFindPostByPermalink conn webLogId permalink =
|
||||
(table Table.Post
|
||||
|> getAll [| webLogId, permalink |]
|
||||
|> optArg "index" "permalink"
|
||||
|> without [| "revisions" |])
|
||||
.Merge(fun post -> ExpandoObject()?categories <-
|
||||
post.["categoryIds"]
|
||||
.Map(ReqlFunction1(fun cat -> upcast r.Table(Table.Category).Get(cat).Without("children")))
|
||||
.CoerceTo("array"))
|
||||
.Merge(fun post -> ExpandoObject()?comments <-
|
||||
r.Table(Table.Comment)
|
||||
.GetAll(post.["id"]).OptArg("index", "postId")
|
||||
.OrderBy("postedOn")
|
||||
.CoerceTo("array"))
|
||||
|> runCursorAsync<Post> conn
|
||||
|> Seq.tryHead
|
||||
|
||||
/// Try to find a post by its prior permalink
|
||||
let tryFindPostByPriorPermalink conn webLogId permalink =
|
||||
(table Table.Post
|
||||
|> getAll [| webLogId |]
|
||||
|> optArg "index" "webLogId")
|
||||
.Filter(fun post -> post.["priorPermalinks"].Contains(permalink :> obj))
|
||||
|> without [| "revisions" |]
|
||||
|> runCursorAsync<Post> conn
|
||||
|> Seq.tryHead
|
||||
|
||||
/// Save a post
|
||||
let savePost conn post =
|
||||
match post.id with
|
||||
@ -73,3 +104,11 @@ let savePost conn post =
|
||||
|> runResultAsync conn
|
||||
|> ignore
|
||||
post.id
|
||||
|
||||
/// Count posts for a web log
|
||||
let countPosts conn webLogId =
|
||||
table Table.Post
|
||||
|> getAll [| webLogId |]
|
||||
|> optArg "index" "webLogId"
|
||||
|> count
|
||||
|> runAtomAsync<int> conn
|
||||
|
@ -6,6 +6,7 @@ open RethinkDb.Driver.Net
|
||||
let private r = RethinkDb.Driver.RethinkDB.R
|
||||
let private await task = task |> Async.AwaitTask |> Async.RunSynchronously
|
||||
|
||||
let count (expr : ReqlExpr) = expr.Count ()
|
||||
let delete (expr : ReqlExpr) = expr.Delete ()
|
||||
let filter (expr : ReqlExpr -> ReqlExpr) (table : ReqlExpr) = table.Filter expr
|
||||
let get (expr : obj) (table : Table) = table.Get expr
|
||||
|
@ -64,17 +64,26 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Common.Logging">
|
||||
<HintPath>..\packages\Common.Logging.3.3.0\lib\net40\Common.Logging.dll</HintPath>
|
||||
<HintPath>..\packages\Common.Logging.3.3.1\lib\net40\Common.Logging.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Common.Logging.Core">
|
||||
<HintPath>..\packages\Common.Logging.Core.3.3.0\lib\net40\Common.Logging.Core.dll</HintPath>
|
||||
<HintPath>..\packages\Common.Logging.Core.3.3.1\lib\net40\Common.Logging.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Dynamitey">
|
||||
<HintPath>..\packages\Dynamitey.1.0.2.0\lib\net40\Dynamitey.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="FSharp.Core">
|
||||
<HintPath>..\packages\FSharp.Core.4.0.0.1\lib\net40\FSharp.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="FSharp.Interop.Dynamic">
|
||||
<HintPath>..\packages\FSharp.Interop.Dynamic.3.0.0.0\lib\portable-net45+sl50+win\FSharp.Interop.Dynamic.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
|
@ -1,7 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Common.Logging" version="3.3.0" targetFramework="net452" />
|
||||
<package id="Common.Logging.Core" version="3.3.0" targetFramework="net452" />
|
||||
<package id="Common.Logging" version="3.3.1" targetFramework="net452" />
|
||||
<package id="Common.Logging.Core" version="3.3.1" targetFramework="net452" />
|
||||
<package id="Dynamitey" version="1.0.2.0" targetFramework="net452" />
|
||||
<package id="FSharp.Core" version="4.0.0.1" targetFramework="net452" />
|
||||
<package id="FSharp.Interop.Dynamic" version="3.0.0.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="RethinkDb.Driver" version="2.3.8" targetFramework="net452" />
|
||||
</packages>
|
45
src/myWebLog.Resources/Resources.Designer.cs
generated
45
src/myWebLog.Resources/Resources.Designer.cs
generated
@ -177,6 +177,15 @@ namespace myWebLog {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to List All.
|
||||
/// </summary>
|
||||
public static string ListAll {
|
||||
get {
|
||||
return ResourceManager.GetString("ListAll", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Log Off.
|
||||
/// </summary>
|
||||
@ -213,6 +222,15 @@ namespace myWebLog {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Next Post.
|
||||
/// </summary>
|
||||
public static string NextPost {
|
||||
get {
|
||||
return ResourceManager.GetString("NextPost", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Older Posts.
|
||||
/// </summary>
|
||||
@ -231,6 +249,15 @@ namespace myWebLog {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Pages.
|
||||
/// </summary>
|
||||
public static string Pages {
|
||||
get {
|
||||
return ResourceManager.GetString("Pages", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Permalink.
|
||||
/// </summary>
|
||||
@ -267,6 +294,15 @@ namespace myWebLog {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Posts tagged.
|
||||
/// </summary>
|
||||
public static string PostsTagged {
|
||||
get {
|
||||
return ResourceManager.GetString("PostsTagged", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Post Status.
|
||||
/// </summary>
|
||||
@ -276,6 +312,15 @@ namespace myWebLog {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Previous Post.
|
||||
/// </summary>
|
||||
public static string PreviousPost {
|
||||
get {
|
||||
return ResourceManager.GetString("PreviousPost", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to PublishedDate.
|
||||
/// </summary>
|
||||
|
@ -156,6 +156,9 @@
|
||||
<data name="ErrNotConfigured" xml:space="preserve">
|
||||
<value>is not properly configured for myWebLog</value>
|
||||
</data>
|
||||
<data name="ListAll" xml:space="preserve">
|
||||
<value>List All</value>
|
||||
</data>
|
||||
<data name="LogOff" xml:space="preserve">
|
||||
<value>Log Off</value>
|
||||
</data>
|
||||
@ -168,12 +171,18 @@
|
||||
<data name="NewerPosts" xml:space="preserve">
|
||||
<value>Newer Posts</value>
|
||||
</data>
|
||||
<data name="NextPost" xml:space="preserve">
|
||||
<value>Next Post</value>
|
||||
</data>
|
||||
<data name="OlderPosts" xml:space="preserve">
|
||||
<value>Older Posts</value>
|
||||
</data>
|
||||
<data name="PageHash" xml:space="preserve">
|
||||
<value>Page #</value>
|
||||
</data>
|
||||
<data name="Pages" xml:space="preserve">
|
||||
<value>Pages</value>
|
||||
</data>
|
||||
<data name="Permalink" xml:space="preserve">
|
||||
<value>Permalink</value>
|
||||
</data>
|
||||
@ -186,9 +195,15 @@
|
||||
<data name="Posts" xml:space="preserve">
|
||||
<value>Posts</value>
|
||||
</data>
|
||||
<data name="PostsTagged" xml:space="preserve">
|
||||
<value>Posts tagged</value>
|
||||
</data>
|
||||
<data name="PostStatus" xml:space="preserve">
|
||||
<value>Post Status</value>
|
||||
</data>
|
||||
<data name="PreviousPost" xml:space="preserve">
|
||||
<value>Previous Post</value>
|
||||
</data>
|
||||
<data name="PublishedDate" xml:space="preserve">
|
||||
<value>PublishedDate</value>
|
||||
</data>
|
||||
|
25
src/myWebLog.Web/AdminModule.fs
Normal file
25
src/myWebLog.Web/AdminModule.fs
Normal file
@ -0,0 +1,25 @@
|
||||
namespace myWebLog
|
||||
|
||||
open myWebLog.Data.Category
|
||||
open myWebLog.Data.Page
|
||||
open myWebLog.Data.Post
|
||||
open myWebLog.Entities
|
||||
open Nancy
|
||||
open RethinkDb.Driver.Net
|
||||
|
||||
/// Handle /admin routes
|
||||
type AdminModule(conn : IConnection) as this =
|
||||
inherit NancyModule("/admin")
|
||||
|
||||
do
|
||||
this.Get.["/"] <- fun _ -> upcast this.Dashboard ()
|
||||
|
||||
/// Admin dashboard
|
||||
member this.Dashboard () =
|
||||
this.RequiresAccessLevel AuthorizationLevel.Administrator
|
||||
let model = DashboardModel(this.Context, this.WebLog)
|
||||
model.posts <- countPosts conn this.WebLog.id
|
||||
model.pages <- countPages conn this.WebLog.id
|
||||
model.categories <- countCategories conn this.WebLog.id
|
||||
model.pageTitle <- Resources.Dashboard
|
||||
this.View.["admin/dashboard", model]
|
@ -6,14 +6,13 @@ open myWebLog.Data.Page
|
||||
open myWebLog.Data.Post
|
||||
open myWebLog.Entities
|
||||
open Nancy
|
||||
open Nancy.Authentication.Forms
|
||||
open Nancy.ModelBinding
|
||||
open Nancy.Security
|
||||
open Nancy.Session.Persistable
|
||||
open NodaTime
|
||||
open RethinkDb.Driver.Net
|
||||
|
||||
/// Routes dealing with posts (including the home page)
|
||||
/// Routes dealing with posts (including the home page and catch-all routes)
|
||||
type PostModule(conn : IConnection, clock : IClock) as this =
|
||||
inherit NancyModule()
|
||||
|
||||
@ -21,6 +20,7 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
||||
|
||||
do
|
||||
this.Get .["/" ] <- fun _ -> upcast this.HomePage ()
|
||||
this.Get .["/{permalink*}" ] <- fun parms -> upcast this.CatchAll (downcast parms)
|
||||
this.Get .["/posts/page/{page:int}" ] <- fun parms -> upcast this.DisplayPageOfPublishedPosts (getPage parms)
|
||||
this.Get .["/posts/list" ] <- fun _ -> upcast this.PostList 1
|
||||
this.Get .["/posts/list/page/{page:int}"] <- fun parms -> upcast this.PostList (getPage parms)
|
||||
@ -56,6 +56,31 @@ type PostModule(conn : IConnection, clock : IClock) as this =
|
||||
this.ThemedView "page" model
|
||||
| None -> this.NotFound ()
|
||||
|
||||
/// Derive a post or page from the URL, or redirect from a prior URL to the current one
|
||||
member this.CatchAll (parameters : DynamicDictionary) =
|
||||
let url : string = downcast parameters.["permalink"]
|
||||
match tryFindPostByPermalink conn this.WebLog.id url with
|
||||
| Some post -> // Hopefully the most common result; the permalink is a permalink!
|
||||
let model = PostModel(this.Context, this.WebLog, post)
|
||||
model.newerPost <- tryFindNewerPost conn post
|
||||
model.olderPost <- tryFindOlderPost conn post
|
||||
model.pageTitle <- post.title
|
||||
this.ThemedView "single" model
|
||||
| None -> // Maybe it's a page permalink instead...
|
||||
match tryFindPageByPermalink conn this.WebLog.id url with
|
||||
| Some page -> // ...and it is!
|
||||
let model = PageModel(this.Context, this.WebLog, page)
|
||||
model.pageTitle <- page.title
|
||||
this.ThemedView "page" model
|
||||
| None -> // Maybe it's an old permalink for a post
|
||||
match tryFindPostByPriorPermalink conn this.WebLog.id url with
|
||||
| Some post -> // Redirect them to the proper permalink
|
||||
this.Negotiate
|
||||
.WithHeader("Location", sprintf "/%s" post.permalink)
|
||||
.WithStatusCode(HttpStatusCode.MovedPermanently)
|
||||
| None -> this.NotFound ()
|
||||
|
||||
|
||||
// ---- Administer posts ----
|
||||
|
||||
/// Display a page of posts in the admin area
|
||||
|
@ -78,6 +78,52 @@ type MyWebLogModel(ctx : NancyContext, webLog : WebLog) =
|
||||
(this.zonedTime ticks
|
||||
|> ZonedDateTimePattern.CreateWithCurrentCulture("h':'mmtt", DateTimeZoneProviders.Tzdb).Format).ToLower()
|
||||
|
||||
|
||||
// ---- Admin models ----
|
||||
|
||||
/// Admin Dashboard view model
|
||||
type DashboardModel(ctx, webLog) =
|
||||
inherit MyWebLogModel(ctx, webLog)
|
||||
/// The number of posts for the current web log
|
||||
member val posts = 0 with get, set
|
||||
/// The number of pages for the current web log
|
||||
member val pages = 0 with get, set
|
||||
/// The number of categories for the current web log
|
||||
member val categories = 0 with get, set
|
||||
|
||||
|
||||
// ---- Page models ----
|
||||
|
||||
/// Model for page display
|
||||
type PageModel(ctx, webLog, page) =
|
||||
inherit MyWebLogModel(ctx, webLog)
|
||||
|
||||
/// The page to be displayed
|
||||
member this.page : Page = page
|
||||
|
||||
|
||||
// ---- Post models ----
|
||||
|
||||
/// Model for post display
|
||||
type PostModel(ctx, webLog, post) =
|
||||
inherit MyWebLogModel(ctx, webLog)
|
||||
/// The post being displayed
|
||||
member this.post : Post = post
|
||||
/// The next newer post
|
||||
member val newerPost = Option<Post>.None with get, set
|
||||
/// The next older post
|
||||
member val olderPost = Option<Post>.None with get, set
|
||||
/// The date the post was published
|
||||
member this.publishedDate = this.displayLongDate this.post.publishedOn
|
||||
/// The time the post was published
|
||||
member this.publishedTime = this.displayTime this.post.publishedOn
|
||||
/// Does the post have tags?
|
||||
member this.hasTags = List.length post.tags > 0
|
||||
/// Get the tags sorted
|
||||
member this.tags = post.tags
|
||||
|> List.sort
|
||||
|> List.map (fun tag -> tag, tag.Replace(' ', '+'))
|
||||
|
||||
/// Model for all page-of-posts pages
|
||||
type PostsModel(ctx, webLog) =
|
||||
inherit MyWebLogModel(ctx, webLog)
|
||||
@ -107,14 +153,6 @@ type PostsModel(ctx, webLog) =
|
||||
member this.olderLink = sprintf "%s/page/%i" this.urlPrefix (this.pageNbr + 1)
|
||||
|
||||
|
||||
/// Model for page display
|
||||
type PageModel(ctx, webLog, page) =
|
||||
inherit MyWebLogModel(ctx, webLog)
|
||||
|
||||
/// The page to be displayed
|
||||
member this.page : Page = page
|
||||
|
||||
|
||||
/// Form for editing a post
|
||||
type EditPostForm() =
|
||||
/// The title of the post
|
||||
|
@ -54,6 +54,7 @@
|
||||
<Compile Include="Keys.fs" />
|
||||
<Compile Include="ViewModels.fs" />
|
||||
<Compile Include="ModuleExtensions.fs" />
|
||||
<Compile Include="AdminModule.fs" />
|
||||
<Compile Include="PostModule.fs" />
|
||||
<Compile Include="App.fs" />
|
||||
<Content Include="packages.config" />
|
||||
|
@ -69,6 +69,7 @@
|
||||
<Content Include="content\scripts\tinymce-init.js" />
|
||||
<Content Include="content\styles\admin.css" />
|
||||
<Content Include="views\admin\admin-layout.html" />
|
||||
<Content Include="views\admin\dashboard.html" />
|
||||
<Content Include="views\admin\post\edit.html" />
|
||||
<Content Include="views\admin\post\list.html" />
|
||||
<Content Include="views\default\index-content.html" />
|
||||
@ -76,6 +77,8 @@
|
||||
<Content Include="views\default\layout.html" />
|
||||
<Content Include="views\default\page-content.html" />
|
||||
<Content Include="views\default\page.html" />
|
||||
<Content Include="views\default\single-content.html" />
|
||||
<Content Include="views\default\single.html" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
32
src/myWebLog/views/admin/dashboard.html
Normal file
32
src/myWebLog/views/admin/dashboard.html
Normal file
@ -0,0 +1,32 @@
|
||||
@Master['admin/admin-layout']
|
||||
|
||||
@Section['Content']
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<h3>@Translate.Posts <span class="badge">@Model.posts</span></h3>
|
||||
<p>
|
||||
<a href="/posts/list"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
||||
|
||||
<a href="/post/new/edit"><i class="fa fa-plus"></i> @Translate.AddNew</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<h3>@Translate.Pages <span class="badge">@Model.pages</span></h3>
|
||||
<p>
|
||||
<a href="/pages/list"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
||||
|
||||
<a href="/page/new/edit"><i class="fa fa-plus"></i> @Translate.AddNew</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<h3>@Translate.Categories <span class="badge">@Model.categories</span></h3>
|
||||
<p>
|
||||
<a href="/categories/list"><i class="fa fa-list.ul"></i> @Translate.ListAll</a>
|
||||
|
||||
<a href="/category/new/edit"><i class="fa fa-plus"></i> @Translate.AddNew</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@EndSection
|
69
src/myWebLog/views/default/single-content.html
Normal file
69
src/myWebLog/views/default/single-content.html
Normal file
@ -0,0 +1,69 @@
|
||||
<article>
|
||||
<div class="row">
|
||||
<div class="col-xs-12"><h1>@Model.post.title</h1></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h4>
|
||||
<i class="fa fa-calendar" title="@Translate.Date"></i> @Model.publishedDate
|
||||
<i class="fa fa-clock-o" title="@Translate.Time"></i> @Model.publishedTime
|
||||
@Each.post.categories
|
||||
<i class="fa fa-folder-open-o" title="@Translate.Category"></i>
|
||||
<!-- <a href="/category/@Current.slug" title=__("Categorized under %s", category.name)) -->
|
||||
@Current.name
|
||||
@EndEach
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">@Model.post.text</div>
|
||||
</div>
|
||||
@If.hasTags
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
@Each.tags
|
||||
<a href="/tag/@Current.Item2" title="@Translate.PostsTagged "@Current.Item1"">
|
||||
<i class="fa fa-tag"></i> @Current.Item1
|
||||
</a>
|
||||
@EndEach
|
||||
</div>
|
||||
</div>
|
||||
@EndIf
|
||||
</article>
|
||||
<div class="row">
|
||||
<div class="col-xs-12"><hr /></div>
|
||||
</div>
|
||||
<!-- // TODO: format comments -->
|
||||
<!-- .row
|
||||
.col-xs-12
|
||||
each comment in post.comments
|
||||
if 'Approved' == comment.status
|
||||
h4
|
||||
if comment.url
|
||||
a(href=comment.url)= comment.name
|
||||
else
|
||||
= comment.name
|
||||
|
|
||||
small
|
||||
=moment(comment.postedDate).format('MMMM Do, YYYY / h:mma')
|
||||
!= comment.text -->
|
||||
<div class="row">
|
||||
<div class="col-xs-12"><hr /></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
@If.newerPost.IsSome
|
||||
<a href="/@Model.newerPost.Value.permalink" title="@Translate.NextPost - "@Model.newerPost.Value.title"">
|
||||
« @Model.newerPost.Value.title
|
||||
</a>
|
||||
@EndIf
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
@If.olderPost.IsSome
|
||||
<a href="/@Model.olderPost.Value.permalink"
|
||||
title="@Translate.PreviousPost - "@Model.olderPost.Value.title"">
|
||||
@Model.olderPost.Value.title »
|
||||
</a>
|
||||
@EndIf
|
||||
</div>
|
||||
</div>
|
5
src/myWebLog/views/default/single.html
Normal file
5
src/myWebLog/views/default/single.html
Normal file
@ -0,0 +1,5 @@
|
||||
@Master['default/layout']
|
||||
|
||||
@Section['Content']
|
||||
@Partial['default/single-content', Model]
|
||||
@EndSection
|
Loading…
Reference in New Issue
Block a user