WIP on revision mgt template (#13)
This commit is contained in:
parent
2906c20efa
commit
d667d09372
|
@ -147,6 +147,28 @@ type DisplayPage =
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Information about a revision used for display
|
||||||
|
[<CLIMutable; NoComparison; NoEquality>]
|
||||||
|
type DisplayRevision =
|
||||||
|
{ /// The as-of date/time for the revision
|
||||||
|
asOf : DateTime
|
||||||
|
|
||||||
|
/// The as-of date/time for the revision in the web log's local time zone
|
||||||
|
asOfLocal : DateTime
|
||||||
|
|
||||||
|
/// The format of the text of the revision
|
||||||
|
format : string
|
||||||
|
}
|
||||||
|
with
|
||||||
|
|
||||||
|
/// Create a display revision from an actual revision
|
||||||
|
static member fromRevision webLog (rev : Revision) =
|
||||||
|
{ asOf = rev.asOf
|
||||||
|
asOfLocal = WebLog.localTime webLog rev.asOf
|
||||||
|
format = MarkupText.sourceType rev.text
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
open System.IO
|
open System.IO
|
||||||
|
|
||||||
/// Information about an uploaded file used for display
|
/// Information about an uploaded file used for display
|
||||||
|
@ -766,6 +788,39 @@ type ManagePermalinksModel =
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// View model to manage revisions
|
||||||
|
[<CLIMutable; NoComparison; NoEquality>]
|
||||||
|
type ManageRevisionsModel =
|
||||||
|
{ /// The ID for the entity being edited
|
||||||
|
id : string
|
||||||
|
|
||||||
|
/// The type of entity being edited ("page" or "post")
|
||||||
|
entity : string
|
||||||
|
|
||||||
|
/// The current title of the page or post
|
||||||
|
currentTitle : string
|
||||||
|
|
||||||
|
/// The revisions for the page or post
|
||||||
|
revisions : DisplayRevision[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a revision model from a page
|
||||||
|
static member fromPage webLog (pg : Page) =
|
||||||
|
{ id = PageId.toString pg.id
|
||||||
|
entity = "page"
|
||||||
|
currentTitle = pg.title
|
||||||
|
revisions = pg.revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a revision model from a post
|
||||||
|
static member fromPost webLog (post : Post) =
|
||||||
|
{ id = PostId.toString post.id
|
||||||
|
entity = "post"
|
||||||
|
currentTitle = post.title
|
||||||
|
revisions = post.revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// View model for posts in a list
|
/// View model for posts in a list
|
||||||
[<NoComparison; NoEquality>]
|
[<NoComparison; NoEquality>]
|
||||||
type PostListItem =
|
type PostListItem =
|
||||||
|
|
|
@ -227,10 +227,10 @@ let register () =
|
||||||
typeof<RssOptions>; typeof<TagMap>; typeof<UploadDestination>; typeof<WebLog>
|
typeof<RssOptions>; typeof<TagMap>; typeof<UploadDestination>; typeof<WebLog>
|
||||||
// View models
|
// View models
|
||||||
typeof<DashboardModel>; typeof<DisplayCategory>; typeof<DisplayCustomFeed>; typeof<DisplayPage>
|
typeof<DashboardModel>; typeof<DisplayCategory>; typeof<DisplayCustomFeed>; typeof<DisplayPage>
|
||||||
typeof<DisplayUpload>; typeof<EditCategoryModel>; typeof<EditCustomFeedModel>; typeof<EditPageModel>
|
typeof<DisplayRevision>; typeof<DisplayUpload>; typeof<EditCategoryModel>; typeof<EditCustomFeedModel>
|
||||||
typeof<EditPostModel>; typeof<EditRssModel>; typeof<EditTagMapModel>; typeof<EditUserModel>
|
typeof<EditPageModel>; typeof<EditPostModel>; typeof<EditRssModel>; typeof<EditTagMapModel>
|
||||||
typeof<LogOnModel>; typeof<ManagePermalinksModel>; typeof<PostDisplay>; typeof<PostListItem>
|
typeof<EditUserModel>; typeof<LogOnModel>; typeof<ManagePermalinksModel>; typeof<ManageRevisionsModel>
|
||||||
typeof<SettingsModel>; typeof<UserMessage>
|
typeof<PostDisplay>; typeof<PostListItem>; typeof<SettingsModel>; typeof<UserMessage>
|
||||||
// Framework types
|
// Framework types
|
||||||
typeof<AntiforgeryTokenSet>; typeof<DateTime option>; typeof<int option>; typeof<KeyValuePair>
|
typeof<AntiforgeryTokenSet>; typeof<DateTime option>; typeof<int option>; typeof<KeyValuePair>
|
||||||
typeof<MetaItem list>; typeof<string list>; typeof<string option>; typeof<TagMap list>
|
typeof<MetaItem list>; typeof<string list>; typeof<string option>; typeof<TagMap list>
|
||||||
|
|
|
@ -190,6 +190,21 @@ let savePagePermalinks : HttpHandler = fun next ctx -> task {
|
||||||
| false -> return! Error.notFound next ctx
|
| false -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET /admin/page/{id}/revisions
|
||||||
|
let editPageRevisions pgId : HttpHandler = fun next ctx -> task {
|
||||||
|
let webLog = ctx.WebLog
|
||||||
|
match! ctx.Data.Page.findFullById (PageId pgId) webLog.id with
|
||||||
|
| Some pg ->
|
||||||
|
return!
|
||||||
|
Hash.FromAnonymousObject {|
|
||||||
|
csrf = csrfToken ctx
|
||||||
|
model = ManageRevisionsModel.fromPage webLog pg
|
||||||
|
page_title = $"Manage Page Permalinks"
|
||||||
|
|}
|
||||||
|
|> viewForTheme "admin" "revisions" next ctx
|
||||||
|
| None -> return! Error.notFound next ctx
|
||||||
|
}
|
||||||
|
|
||||||
// POST /admin/page/{id}/delete
|
// POST /admin/page/{id}/delete
|
||||||
let deletePage pgId : HttpHandler = fun next ctx -> task {
|
let deletePage pgId : HttpHandler = fun next ctx -> task {
|
||||||
let webLog = ctx.WebLog
|
let webLog = ctx.WebLog
|
||||||
|
|
58
src/admin-theme/revisions.liquid
Normal file
58
src/admin-theme/revisions.liquid
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<h2 class="my-3">{{ page_title }}</h2>
|
||||||
|
<article>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="{{ csrf.form_field_name }}" value="{{ csrf.request_token }}">
|
||||||
|
<input type="hidden" name="id" value="{{ model.id }}">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<p style="line-height:1.2rem;">
|
||||||
|
<strong>{{ model.current_title }}</strong><br>
|
||||||
|
<small class="text-muted">
|
||||||
|
{%- capture back_link %}admin/{{ model.entity }}/{{ model.id }}/edit{% endcapture -%}
|
||||||
|
<a href="{{ back_link | relative_link }}">« Back to Edit {{ model.entity | capitalize }}</a>
|
||||||
|
</small>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- assign revision_count = model.revisions | size -%}
|
||||||
|
{%- capture rev_url_base %}admin/{{ model.entity }}/{{ model.id }}/revision{% endcapture -%}
|
||||||
|
{%- if revision_count > 1 %}
|
||||||
|
{% capture delete_all %}{{ rev_url_base }}s/purge{% endcapture %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
<button type="button" class="btn btn-sm btn-danger" hx-post="{{ delete_all | relative_link }}"
|
||||||
|
hx-confirm="This will remove all revisions but the current one; are you sure this is what you wish to do?">
|
||||||
|
Delete All Prior Revisions
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endif %}
|
||||||
|
{% for rev in model.revisions %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col">
|
||||||
|
{{ rev.as_of_local | date: "MMMM d, yyyy" }} at {{ rev.as_of_local | date: "h:mmaa" | downcase }}
|
||||||
|
<span class="badge bg-secondary text-uppercase">{{ ref.format }}</span>
|
||||||
|
{%- if forloop.first %}
|
||||||
|
<span class="badge bg-primary text-uppercase ms-2">Current Revision</span>
|
||||||
|
{%- endif %}<br>
|
||||||
|
{% unless forloop.first %}
|
||||||
|
{%- capture rev_url_prefix %}{{ rev_url_base }}/{{ rev.as_of | date: "o" }}{% endcapture -%}
|
||||||
|
<small>
|
||||||
|
<a href="TODO">Preview</a>
|
||||||
|
<span class="text-muted"> • </span>
|
||||||
|
{%- capture rev_restore %}{{ rev_url_prefix }}/restore{% endcapture -%}
|
||||||
|
{%- capture rev_restore_link %}{{ rev_restore | relative_link }}{% endcapture -%}
|
||||||
|
<a href="{{ rev_restore_link }}" hx-post="{{ rev_restore_link }}">Restore as Current</a>
|
||||||
|
<span class="text-muted"> • </span>
|
||||||
|
{%- capture rev_del %}{{ rev_url_prefix }}/delete{% endcapture -%}
|
||||||
|
{%- capture rev_del_link %}{{ rev_del | relative_link }}{% endcapture -%}
|
||||||
|
<a href="{{ rev_del_link }}" hx-post="{{ rev_del_link }}" class="text-danger">Delete</a>
|
||||||
|
</small>
|
||||||
|
{% endunless %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</article>
|
Loading…
Reference in New Issue
Block a user