Admin tweaks plus
- Version now reports the correct version - Post edit properly renders existing selected categories as checked, and uses the description in the title attribute if it is present - Created light/dark transparent logos Ready to test the functionality of the admin area next...
This commit is contained in:
parent
ed9b8adc1c
commit
0d54fc2ec3
@ -130,7 +130,7 @@ type MyWebLogBootstrapper() =
|
|||||||
|
|
||||||
|
|
||||||
let version =
|
let version =
|
||||||
let v = typeof<AppConfig>.GetType().GetTypeInfo().Assembly.GetName().Version
|
let v = typeof<AppConfig>.GetTypeInfo().Assembly.GetName().Version
|
||||||
match v.Build with
|
match v.Build with
|
||||||
| 0 -> match v.Minor with 0 -> string v.Major | _ -> sprintf "%d.%d" v.Major v.Minor
|
| 0 -> match v.Minor with 0 -> string v.Major | _ -> sprintf "%d.%d" v.Major v.Minor
|
||||||
| _ -> sprintf "%d.%d.%d" v.Major v.Minor v.Build
|
| _ -> sprintf "%d.%d.%d" v.Major v.Minor v.Build
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
namespace myWebLog.Web.AssemblyInfo
|
namespace MyWebLog.AssemblyInfo
|
||||||
|
|
||||||
open System.Reflection
|
open System.Reflection
|
||||||
open System.Runtime.CompilerServices
|
open System.Runtime.CompilerServices
|
||||||
@ -14,7 +14,7 @@ open System.Runtime.InteropServices
|
|||||||
[<assembly: AssemblyCulture("")>]
|
[<assembly: AssemblyCulture("")>]
|
||||||
[<assembly: ComVisible(false)>]
|
[<assembly: ComVisible(false)>]
|
||||||
[<assembly: Guid("e6ee110a-27a6-4a19-b0cb-d24f48f71b53")>]
|
[<assembly: Guid("e6ee110a-27a6-4a19-b0cb-d24f48f71b53")>]
|
||||||
[<assembly: AssemblyVersion("0.9.1.0")>]
|
[<assembly: AssemblyVersion("0.9.2.0")>]
|
||||||
[<assembly: AssemblyFileVersion("1.0.0.0")>]
|
[<assembly: AssemblyFileVersion("1.0.0.0")>]
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -103,18 +103,18 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
upcast this.Response.FromStream(stream, sprintf "application/%s+xml" format) *)
|
upcast this.Response.FromStream(stream, sprintf "application/%s+xml" format) *)
|
||||||
|
|
||||||
do
|
do
|
||||||
this.Get ("/", fun _ -> this.HomePage ())
|
this.Get ("/", fun _ -> this.HomePage ())
|
||||||
this.Get ("/{permalink*}", fun parms -> this.CatchAll (downcast parms))
|
this.Get ("/{permalink*}", fun p -> this.CatchAll (downcast p))
|
||||||
this.Get ("/posts/page/{page:int}", fun parms -> this.PublishedPostsPage (getPage <| downcast parms))
|
this.Get ("/posts/page/{page:int}", fun p -> this.PublishedPostsPage (getPage <| downcast p))
|
||||||
this.Get ("/category/{slug}", fun parms -> this.CategorizedPosts (downcast parms))
|
this.Get ("/category/{slug}", fun p -> this.CategorizedPosts (downcast p))
|
||||||
this.Get ("/category/{slug}/page/{page:int}", fun parms -> this.CategorizedPosts (downcast parms))
|
this.Get ("/category/{slug}/page/{page:int}", fun p -> this.CategorizedPosts (downcast p))
|
||||||
this.Get ("/tag/{tag}", fun parms -> this.TaggedPosts (downcast parms))
|
this.Get ("/tag/{tag}", fun p -> this.TaggedPosts (downcast p))
|
||||||
this.Get ("/tag/{tag}/page/{page:int}", fun parms -> this.TaggedPosts (downcast parms))
|
this.Get ("/tag/{tag}/page/{page:int}", fun p -> this.TaggedPosts (downcast p))
|
||||||
this.Get ("/feed", fun _ -> this.Feed ())
|
this.Get ("/feed", fun _ -> this.Feed ())
|
||||||
this.Get ("/posts/list", fun _ -> this.PostList 1)
|
this.Get ("/posts/list", fun _ -> this.PostList 1)
|
||||||
this.Get ("/posts/list/page/{page:int}", fun parms -> this.PostList (getPage <| downcast parms))
|
this.Get ("/posts/list/page/{page:int}", fun p -> this.PostList (getPage <| downcast p))
|
||||||
this.Get ("/post/{postId}/edit", fun parms -> this.EditPost (downcast parms))
|
this.Get ("/post/{postId}/edit", fun p -> this.EditPost (downcast p))
|
||||||
this.Post ("/post/{postId}/edit", fun parms -> this.SavePost (downcast parms))
|
this.Post ("/post/{postId}/edit", fun p -> this.SavePost (downcast p))
|
||||||
|
|
||||||
// ---- Display posts to users ----
|
// ---- Display posts to users ----
|
||||||
|
|
||||||
@ -253,11 +253,10 @@ type PostModule(data : IMyWebLogData, clock : IClock) as this =
|
|||||||
| None -> Revision.Empty
|
| None -> Revision.Empty
|
||||||
let model = EditPostModel (this.Context, this.WebLog, post, rev)
|
let model = EditPostModel (this.Context, this.WebLog, post, rev)
|
||||||
model.Categories <- findAllCategories data this.WebLog.Id
|
model.Categories <- findAllCategories data this.WebLog.Id
|
||||||
|> List.map (fun cat -> string (fst cat).Id,
|
|> List.map (fun cat ->
|
||||||
sprintf "%s%s" (String.replicate (snd cat) " ")
|
DisplayCategory.Create cat (post.CategoryIds |> List.contains (fst cat).Id))
|
||||||
(fst cat).Name)
|
|
||||||
model.PageTitle <- Strings.get <| match post.Id with "new" -> "AddNewPost" | _ -> "EditPost"
|
model.PageTitle <- Strings.get <| match post.Id with "new" -> "AddNewPost" | _ -> "EditPost"
|
||||||
upcast this.View.["admin/post/edit"]
|
upcast this.View.["admin/post/edit", model]
|
||||||
| _ -> this.NotFound ()
|
| _ -> this.NotFound ()
|
||||||
|
|
||||||
/// Save a post
|
/// Save a post
|
||||||
|
@ -9,7 +9,7 @@ open Newtonsoft.Json
|
|||||||
open NodaTime
|
open NodaTime
|
||||||
open NodaTime.Text
|
open NodaTime.Text
|
||||||
open System
|
open System
|
||||||
|
open System.Net
|
||||||
|
|
||||||
/// Levels for a user message
|
/// Levels for a user message
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
@ -90,7 +90,7 @@ module FormatDateTime =
|
|||||||
|
|
||||||
|
|
||||||
/// Parent view model for all myWebLog views
|
/// Parent view model for all myWebLog views
|
||||||
type MyWebLogModel (ctx : NancyContext, webLog : WebLog) =
|
type MyWebLogModel (ctx : NancyContext, webLog : WebLog) as this =
|
||||||
|
|
||||||
/// Get the messages from the session
|
/// Get the messages from the session
|
||||||
let getMessages () =
|
let getMessages () =
|
||||||
@ -100,6 +100,20 @@ type MyWebLogModel (ctx : NancyContext, webLog : WebLog) =
|
|||||||
| _ -> ctx.Request.Session.Delete Keys.Messages
|
| _ -> ctx.Request.Session.Delete Keys.Messages
|
||||||
msg
|
msg
|
||||||
|
|
||||||
|
/// Generate a footer logo with the given scheme
|
||||||
|
let footerLogo scheme =
|
||||||
|
seq {
|
||||||
|
yield sprintf "<img src=\"/content/logo-%s.png\" alt=\"myWebLog\" title=\"" scheme
|
||||||
|
yield sprintf "%s %s • " (Strings.get "PoweredBy") this.Generator
|
||||||
|
yield Strings.get "LoadedIn"
|
||||||
|
yield " "
|
||||||
|
yield TimeSpan(System.DateTime.Now.Ticks - this.RequestStart).TotalSeconds.ToString "f3"
|
||||||
|
yield " "
|
||||||
|
yield (Strings.get "Seconds").ToLower ()
|
||||||
|
yield "\" height=\"30\" />"
|
||||||
|
}
|
||||||
|
|> Seq.reduce (+)
|
||||||
|
|
||||||
/// The web log for this request
|
/// The web log for this request
|
||||||
member this.WebLog = webLog
|
member this.WebLog = webLog
|
||||||
/// The subtitle for the webLog (SSVE can't do IsSome that deep)
|
/// The subtitle for the webLog (SSVE can't do IsSome that deep)
|
||||||
@ -134,19 +148,11 @@ type MyWebLogModel (ctx : NancyContext, webLog : WebLog) =
|
|||||||
| None -> this.WebLog.Name
|
| None -> this.WebLog.Name
|
||||||
| pt -> sprintf "%s | %s" pt this.WebLog.Name
|
| pt -> sprintf "%s | %s" pt this.WebLog.Name
|
||||||
|
|
||||||
/// An image with the version and load time in the tool tip
|
/// An image with the version and load time in the tool tip (using light text)
|
||||||
member this.FooterLogo =
|
member this.FooterLogoLight = footerLogo "light"
|
||||||
seq {
|
|
||||||
yield "<img src=\"/default/footer-logo.png\" alt=\"myWebLog\" title=\""
|
/// An image with the version and load time in the tool tip (using dark text)
|
||||||
yield sprintf "%s %s • " (Strings.get "PoweredBy") this.Generator
|
member this.FooterLogoDark = footerLogo "dark"
|
||||||
yield Strings.get "LoadedIn"
|
|
||||||
yield " "
|
|
||||||
yield TimeSpan(System.DateTime.Now.Ticks - this.RequestStart).TotalSeconds.ToString "f3"
|
|
||||||
yield " "
|
|
||||||
yield (Strings.get "Seconds").ToLower ()
|
|
||||||
yield "\" />"
|
|
||||||
}
|
|
||||||
|> Seq.reduce (+)
|
|
||||||
|
|
||||||
|
|
||||||
// ---- Admin models ----
|
// ---- Admin models ----
|
||||||
@ -399,6 +405,27 @@ type EditPostForm () =
|
|||||||
this.Text <- rev.Text
|
this.Text <- rev.Text
|
||||||
this
|
this
|
||||||
|
|
||||||
|
/// Category information for display
|
||||||
|
type DisplayCategory = {
|
||||||
|
Id : string
|
||||||
|
Indent : string
|
||||||
|
Name : string
|
||||||
|
Description : string
|
||||||
|
IsChecked : bool
|
||||||
|
}
|
||||||
|
with
|
||||||
|
/// Create a display category
|
||||||
|
static member Create (cat : Category, indent) isChecked =
|
||||||
|
{ Id = cat.Id
|
||||||
|
Indent = String.replicate indent " "
|
||||||
|
Name = WebUtility.HtmlEncode cat.Name
|
||||||
|
IsChecked = isChecked
|
||||||
|
Description = WebUtility.HtmlEncode (match cat.Description with Some d -> d | _ -> cat.Name)
|
||||||
|
}
|
||||||
|
/// The "checked" attribute for this category
|
||||||
|
member this.CheckedAttr
|
||||||
|
with get() = match this.IsChecked with true -> "checked=\"checked\"" | _ -> ""
|
||||||
|
|
||||||
/// View model for the edit post page
|
/// View model for the edit post page
|
||||||
type EditPostModel (ctx, webLog, post, revision) =
|
type EditPostModel (ctx, webLog, post, revision) =
|
||||||
inherit MyWebLogModel (ctx, webLog)
|
inherit MyWebLogModel (ctx, webLog)
|
||||||
@ -408,7 +435,7 @@ type EditPostModel (ctx, webLog, post, revision) =
|
|||||||
/// The post being edited
|
/// The post being edited
|
||||||
member val Post = post with get, set
|
member val Post = post with get, set
|
||||||
/// The categories to which the post may be assigned
|
/// The categories to which the post may be assigned
|
||||||
member val Categories : (string * string) list = [] with get, set
|
member val Categories : DisplayCategory list = [] with get, set
|
||||||
/// Whether the post is currently published
|
/// Whether the post is currently published
|
||||||
member this.IsPublished = PostStatus.Published = this.Post.Status
|
member this.IsPublished = PostStatus.Published = this.Post.Status
|
||||||
/// The published date
|
/// The published date
|
||||||
|
@ -100,9 +100,13 @@ let tryFindPost conn webLogId postId : Post option =
|
|||||||
let! p =
|
let! p =
|
||||||
r.Table(Table.Post)
|
r.Table(Table.Post)
|
||||||
.Get(postId)
|
.Get(postId)
|
||||||
.Filter(ReqlFunction1 (fun p -> upcast p.["WebLogId"].Eq webLogId))
|
|
||||||
.RunAtomAsync<Post> conn
|
.RunAtomAsync<Post> conn
|
||||||
return match box p with null -> None | post -> Some <| unbox post
|
return
|
||||||
|
match box p with
|
||||||
|
| null -> None
|
||||||
|
| pst ->
|
||||||
|
let post : Post = unbox pst
|
||||||
|
match post.WebLogId = webLogId with true -> Some post | _ -> None
|
||||||
}
|
}
|
||||||
|> Async.RunSynchronously
|
|> Async.RunSynchronously
|
||||||
|
|
||||||
|
BIN
src/MyWebLog/content/logo-dark.png
Normal file
BIN
src/MyWebLog/content/logo-dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
src/MyWebLog/content/logo-light.png
Normal file
BIN
src/MyWebLog/content/logo-light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
@ -2,7 +2,7 @@
|
|||||||
"buildOptions": {
|
"buildOptions": {
|
||||||
"emitEntryPoint": true,
|
"emitEntryPoint": true,
|
||||||
"copyToOutput": {
|
"copyToOutput": {
|
||||||
"include": "views"
|
"include": [ "views", "content" ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
footer {
|
|
||||||
background-color: #808080;
|
|
||||||
border-top: solid 1px black;
|
|
||||||
color: white;
|
|
||||||
}
|
|
@ -40,7 +40,7 @@
|
|||||||
<footer>
|
<footer>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 text-right">@Model.Generator</div>
|
<div class="col-xs-12 text-right">@Model.FooterLogoLight </div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB |
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
@Section['Content']
|
@Section['Content']
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-6">
|
<div class="col-xs-4 text-center">
|
||||||
<h3>@Translate.Posts <span class="badge">@Model.Posts</span></h3>
|
<h3>@Translate.Posts <span class="badge">@Model.Posts</span></h3>
|
||||||
<p>
|
<p>
|
||||||
<a href="/posts/list"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
<a href="/posts/list"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<a href="/post/new/edit"><i class="fa fa-plus"></i> @Translate.AddNew</a>
|
<a href="/post/new/edit"><i class="fa fa-plus"></i> @Translate.AddNew</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6">
|
<div class="col-xs-4 text-center">
|
||||||
<h3>@Translate.Pages <span class="badge">@Model.Pages</span></h3>
|
<h3>@Translate.Pages <span class="badge">@Model.Pages</span></h3>
|
||||||
<p>
|
<p>
|
||||||
<a href="/pages"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
<a href="/pages"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
||||||
@ -18,9 +18,7 @@
|
|||||||
<a href="/page/new/edit"><i class="fa fa-plus"></i> @Translate.AddNew</a>
|
<a href="/page/new/edit"><i class="fa fa-plus"></i> @Translate.AddNew</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-xs-4 text-center">
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-6">
|
|
||||||
<h3>@Translate.Categories <span class="badge">@Model.Categories</span></h3>
|
<h3>@Translate.Categories <span class="badge">@Model.Categories</span></h3>
|
||||||
<p>
|
<p>
|
||||||
<a href="/categories"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
<a href="/categories"><i class="fa fa-list-ul"></i> @Translate.ListAll</a>
|
||||||
@ -29,4 +27,5 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br />
|
||||||
@EndSection
|
@EndSection
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label" for="Permalink">@Translate.Permalink</label>
|
<label class="control-label" for="Permalink">@Translate.Permalink</label>
|
||||||
<input type="text" name="Permalink" id="Permalink" class="form-control" value="@Model.Form.Permalink" />
|
<input type="text" name="Permalink" id="Permalink" class="form-control" value="@Model.Form.Permalink" />
|
||||||
<p class="form-hint"><em>@Translate.startingWith</em> http://@Model.webLog.urlBase/ </p>
|
<p class="form-hint"><em>@Translate.startingWith</em> http://@Model.WebLog.UrlBase/ </p>
|
||||||
</div>
|
</div>
|
||||||
<!-- // TODO: Markdown / HTML choice -->
|
<!-- // TODO: Markdown / HTML choice -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -48,7 +48,7 @@
|
|||||||
@EndSection
|
@EndSection
|
||||||
|
|
||||||
@Section['Scripts']
|
@Section['Scripts']
|
||||||
<script type="text/javascript" src="/content/scripts/tinymce-init.js"></script>
|
<script type="text/javascript" src="/admin/content/tinymce-init.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
/* <![CDATA[ */
|
/* <![CDATA[ */
|
||||||
$(document).ready(function () { $("#Title").focus() })
|
$(document).ready(function () { $("#Title").focus() })
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<label class="control-label" for="Permalink">@Translate.Permalink</label>
|
<label class="control-label" for="Permalink">@Translate.Permalink</label>
|
||||||
<input type="text" name="Permalink" id="Permalink" class="form-control" value="@Model.Form.Permalink" />
|
<input type="text" name="Permalink" id="Permalink" class="form-control" value="@Model.Form.Permalink" />
|
||||||
<!-- // FIXME: hard-coded "http" -->
|
<!-- // FIXME: hard-coded "http" -->
|
||||||
<p class="form-hint"><em>@Translate.startingWith</em> http://@Model.webLog.urlBase/ </p>
|
<p class="form-hint"><em>@Translate.startingWith</em> http://@Model.WebLog.UrlBase/ </p>
|
||||||
</div>
|
</div>
|
||||||
<!-- // TODO: Markdown / HTML choice -->
|
<!-- // TODO: Markdown / HTML choice -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -47,19 +47,11 @@
|
|||||||
<h4 class="panel-title">@Translate.Categories</h4>
|
<h4 class="panel-title">@Translate.Categories</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body" style="max-height:350px;overflow:scroll;">
|
<div class="panel-body" style="max-height:350px;overflow:scroll;">
|
||||||
<!-- // TODO: how to check the ones that are already selected? -->
|
|
||||||
@Each.Categories
|
@Each.Categories
|
||||||
<!-- - var tab = 0
|
@Current.Indent
|
||||||
while tab < item.indent
|
<input type="checkbox" id="Category-@Current.Id" name="Category" value="@Current.Id" @Current.CheckedAttr />
|
||||||
|
|
|
||||||
- tab++
|
|
||||||
- var attributes = {}
|
|
||||||
if -1 < currentCategories.indexOf(item.category.id)
|
|
||||||
- attributes.checked = 'checked' -->
|
|
||||||
<input type="checkbox" id="Category-@Current.Item1" name="Category", value="@Current.Item1" />
|
|
||||||
|
|
||||||
<!-- // FIXME: the title should be the category description -->
|
<label for="Category-@Current.Id" title="@Current.Description">@Current.Name</label>
|
||||||
<label for="Category-@Current.Item1" title="@Current.Item2">@Current.Item2</label>
|
|
||||||
<br/>
|
<br/>
|
||||||
@EndEach
|
@EndEach
|
||||||
</div>
|
</div>
|
||||||
@ -86,7 +78,7 @@
|
|||||||
@EndSection
|
@EndSection
|
||||||
|
|
||||||
@Section['Scripts']
|
@Section['Scripts']
|
||||||
<script type="text/javascript" src="/content/scripts/tinymce-init.js"></script>
|
<script type="text/javascript" src="/admin/content/tinymce-init.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
/** <![CDATA[ */
|
/** <![CDATA[ */
|
||||||
$(document).ready(function () { $("#Title").focus() })
|
$(document).ready(function () { $("#Title").focus() })
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB |
@ -3,7 +3,7 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 text-right">
|
<div class="col-xs-12 text-right">
|
||||||
@Model.FooterLogo
|
@Model.FooterLogoDark
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user