diff --git a/src/MyWebLog/Handlers/Post.fs b/src/MyWebLog/Handlers/Post.fs index 279ca22..0555999 100644 --- a/src/MyWebLog/Handlers/Post.fs +++ b/src/MyWebLog/Handlers/Post.fs @@ -254,10 +254,7 @@ let all pageNbr : HttpHandler = requireAccess Author >=> fun next ctx -> task { let data = ctx.Data let! posts = data.Post.FindPageOfPosts ctx.WebLog.Id pageNbr 25 let! hash = preparePostList ctx.WebLog posts AdminList "" pageNbr 25 data - return! - addToHash ViewContext.PageTitle "Posts" hash - |> withAntiCsrf ctx - |> adminView "post-list" next ctx + return! adminPage "Posts" true (Views.Post.list (hash[ViewContext.Model] :?> PostDisplay)) next ctx } // GET /admin/post/{id}/edit @@ -294,12 +291,13 @@ let edit postId : HttpHandler = requireAccess Author >=> fun next ctx -> task { | None -> return! Error.notFound next ctx } -// POST /admin/post/{id}/delete +// DELETE /admin/post/{id} let delete postId : HttpHandler = requireAccess WebLogAdmin >=> fun next ctx -> task { match! ctx.Data.Post.Delete (PostId postId) ctx.WebLog.Id with | true -> do! addMessage ctx { UserMessage.Success with Message = "Post deleted successfully" } | false -> do! addMessage ctx { UserMessage.Error with Message = "Post not found; nothing deleted" } - return! redirectToGet "admin/posts" next ctx + //return! redirectToGet "admin/posts" next ctx + return! all 1 next ctx } // GET /admin/post/{id}/permalinks diff --git a/src/MyWebLog/Handlers/Routes.fs b/src/MyWebLog/Handlers/Routes.fs index 7f6429c..835a171 100644 --- a/src/MyWebLog/Handlers/Routes.fs +++ b/src/MyWebLog/Handlers/Routes.fs @@ -184,7 +184,6 @@ let router : HttpHandler = choose [ route "/save" >=> Post.save route "/permalinks" >=> Post.savePermalinks routef "/%s/chapter/%i" Post.saveChapter - routef "/%s/delete" Post.delete routef "/%s/revision/%s/delete" Post.deleteRevision routef "/%s/revision/%s/restore" Post.restoreRevision routef "/%s/revisions/purge" Post.purgeRevisions @@ -220,6 +219,7 @@ let router : HttpHandler = choose [ ] DELETE >=> validateCsrf >=> choose [ subRoute "/post" (choose [ + routef "/%s" Post.delete routef "/%s/chapter/%i" Post.deleteChapter ]) subRoute "/settings" (requireAccess WebLogAdmin >=> choose [ diff --git a/src/MyWebLog/Views/Post.fs b/src/MyWebLog/Views/Post.fs index 9878310..2da63c4 100644 --- a/src/MyWebLog/Views/Post.fs +++ b/src/MyWebLog/Views/Post.fs @@ -218,3 +218,110 @@ let chapters withNew (model: ManageChaptersModel) app = [ yield! chapterList withNew model app ] ] + +/// Display a list of posts +let list (model: PostDisplay) app = [ + let dateCol = "col-xs-12 col-md-3 col-lg-2" + let titleCol = "col-xs-12 col-md-7 col-lg-6 col-xl-5 col-xxl-4" + let authorCol = "col-xs-12 col-md-2 col-lg-1" + let tagCol = "col-lg-3 col-xl-4 col-xxl-5 d-none d-lg-inline-block" + h2 [ _class "my-3" ] [ txt app.PageTitle ] + article [] [ + a [ _href (relUrl app "admin/post/new/edit"); _class "btn btn-primary btn-sm mb-3" ] [ raw "Write a New Post" ] + if model.Posts.Length > 0 then + form [ _method "post"; _class "container mb-3"; _hxTarget "body" ] [ + antiCsrf app + div [ _class "row mwl-table-heading" ] [ + div [ _class dateCol ] [ + span [ _class "d-md-none" ] [ raw "Post" ]; span [ _class "d-none d-md-inline" ] [ raw "Date" ] + ] + div [ _class $"{titleCol} d-none d-md-inline-block" ] [ raw "Title" ] + div [ _class $"{authorCol} d-none d-md-inline-block" ] [ raw "Author" ] + div [ _class tagCol ] [ raw "Tags" ] + ] + for post in model.Posts do + div [ _class "row mwl-table-detail" ] [ + div [ _class $"{dateCol} no-wrap" ] [ + small [ _class "d-md-none" ] [ + if post.PublishedOn.HasValue then + raw "Published "; txt (post.PublishedOn.Value.ToString "MMMM d, yyyy") + else raw "Not Published" + if post.PublishedOn.HasValue && post.PublishedOn.Value <> post.UpdatedOn then + em [ _class "text-muted" ] [ + raw " (Updated "; txt (post.UpdatedOn.ToString "MMMM d, yyyy"); raw ")" + ] + ] + span [ _class "d-none d-md-inline" ] [ + if post.PublishedOn.HasValue then txt (post.PublishedOn.Value.ToString "MMMM d, yyyy") + else raw "Not Published" + if not post.PublishedOn.HasValue || post.PublishedOn.Value <> post.UpdatedOn then + br [] + small [ _class "text-muted" ] [ + em [] [ txt (post.UpdatedOn.ToString "MMMM d, yyyy") ] + ] + ] + ] + div [ _class titleCol ] [ + if Option.isSome post.Episode then + span [ _class "badge bg-success float-end text-uppercase mt-1" ] [ raw "Episode" ] + raw post.Title; br [] + small [] [ + let postUrl = relUrl app $"admin/post/{post.Id}" + a [ _href (relUrl app post.Permalink); _target "_blank" ] [ raw "View Post" ] + if app.IsEditor || (app.IsAuthor && app.UserId.Value = WebLogUserId post.AuthorId) then + span [ _class "text-muted" ] [ raw " • " ] + a [ _href $"{postUrl}/edit" ] [ raw "Edit" ] + if app.IsWebLogAdmin then + span [ _class "text-muted" ] [ raw " • " ] + a [ _href postUrl; _hxDelete postUrl; _class "text-danger" + _hxConfirm $"Are you sure you want to delete the post “{post.Title}”? This action cannot be undone." ] [ + raw "Delete" + ] + ] + ] + div [ _class authorCol ] [ + let author = + model.Authors + |> List.tryFind (fun a -> a.Name = post.AuthorId) + |> Option.map _.Value + |> Option.defaultValue "--" + |> txt + small [ _class "d-md-none" ] [ + raw "Authored by "; author; raw " | " + raw (if post.Tags.Length = 0 then "No" else string post.Tags.Length) + raw " Tag"; if post.Tags.Length <> 0 then raw "s" + ] + span [ _class "d-none d-md-inline" ] [ author ] + ] + div [ _class tagCol ] [ + let tags = + post.Tags |> List.mapi (fun idx tag -> idx, span [ _class "no-wrap" ] [ txt tag ]) + for tag in tags do + snd tag + if fst tag < tags.Length - 1 then raw ", " + ] + ] + ] + if Option.isSome model.NewerLink || Option.isSome model.OlderLink then + div [ _class "d-flex justify-content-evenly mb-3" ] [ + div [] [ + if Option.isSome model.NewerLink then + p [] [ + a [ _href model.NewerLink.Value; _class "btn btn-secondary"; ] [ + raw "« Newer Posts" + ] + ] + ] + div [ _class "text-right" ] [ + if Option.isSome model.OlderLink then + p [] [ + a [ _href model.OlderLink.Value; _class "btn btn-secondary" ] [ + raw "Older Posts »" + ] + ] + ] + ] + else + p [ _class "text-muted fst-italic text-center" ] [ raw "This web log has no posts" ] + ] +] diff --git a/src/admin-theme/post-list.liquid b/src/admin-theme/post-list.liquid deleted file mode 100644 index 010ef56..0000000 --- a/src/admin-theme/post-list.liquid +++ /dev/null @@ -1,98 +0,0 @@ -

{{ page_title }}

-
- Write a New Post - {%- assign post_count = model.posts | size -%} - {%- if post_count > 0 %} -
- - {%- assign date_col = "col-xs-12 col-md-3 col-lg-2" -%} - {%- assign title_col = "col-xs-12 col-md-7 col-lg-6 col-xl-5 col-xxl-4" -%} - {%- assign author_col = "col-xs-12 col-md-2 col-lg-1" -%} - {%- assign tag_col = "col-lg-3 col-xl-4 col-xxl-5 d-none d-lg-inline-block" -%} -
-
- PostDate -
-
Title
-
Author
-
Tags
-
- {% for post in model.posts -%} -
-
- - {%- if post.published_on -%} - Published {{ post.published_on | date: "MMMM d, yyyy" }} - {%- else -%} - Not Published - {%- endif -%} - {%- if post.published_on != post.updated_on -%} - (Updated {{ post.updated_on | date: "MMMM d, yyyy" }}) - {%- endif %} - - - {%- if post.published_on -%} - {{ post.published_on | date: "MMMM d, yyyy" }} - {%- else -%} - Not Published - {%- endif -%} - {%- if post.published_on != post.updated_on %}
- {{ post.updated_on | date: "MMMM d, yyyy" }} - {%- endif %} -
-
-
- {%- if post.episode %}Episode{% endif -%} - {{ post.title }}
- - View Post - {% if is_editor or is_author and user_id == post.author_id %} - - Edit - {% endif %} - {% if is_web_log_admin %} - - {%- assign post_del_link = "admin/post/" | append: post.id | append: "/delete" | relative_link -%} - - Delete - - {% endif %} - -
-
- {%- assign tag_count = post.tags | size -%} - - Authored by {{ model.authors | value: post.author_id }} | - {% if tag_count == 0 -%} - No - {%- else -%} - {{ tag_count }} - {%- endif %} Tag{% unless tag_count == 1 %}s{% endunless %} - - {{ model.authors | value: post.author_id }} -
-
- {{ post.tags | join: ", " }} -
-
- {%- endfor %} -
- {% if model.newer_link or model.older_link %} -
-
- {% if model.newer_link %} -

« Newer Posts - {% endif %} -

-
- {% if model.older_link %} -

Older Posts » - {% endif %} -

-
- {% endif %} - {% else %} -

This web log has no posts - {% endif %} -