V2 #1

Merged
danieljsummers merged 102 commits from v2 into main 2022-06-23 00:35:12 +00:00
6 changed files with 31 additions and 16 deletions
Showing only changes of commit c198d33ec0 - Show all commits

View File

@ -14,7 +14,7 @@
<PackageReference Include="Microsoft.FSharpLu.Json" Version="0.11.7" /> <PackageReference Include="Microsoft.FSharpLu.Json" Version="0.11.7" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="RethinkDb.Driver" Version="2.3.150" /> <PackageReference Include="RethinkDb.Driver" Version="2.3.150" />
<PackageReference Include="RethinkDb.Driver.FSharp" Version="0.8.0-alpha-0003" /> <PackageReference Include="RethinkDb.Driver.FSharp" Version="0.8.0-alpha-0004" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -98,6 +98,8 @@ module private Helpers =
hash.Add ("current_page", ctx.Request.Path.Value.Substring 1) hash.Add ("current_page", ctx.Request.Path.Value.Substring 1)
hash.Add ("messages", messages) hash.Add ("messages", messages)
do! ctx.Session.CommitAsync ()
// NOTE: DotLiquid does not support {% render %} or {% include %} in its templates, so we will do a two-pass // NOTE: DotLiquid does not support {% render %} or {% include %} in its templates, so we will do a two-pass
// render; the net effect is a "layout" capability similar to Razor or Pug // render; the net effect is a "layout" capability similar to Razor or Pug
@ -107,6 +109,7 @@ module private Helpers =
// ...then render that content with its layout // ...then render that content with its layout
let! layoutTemplate = TemplateCache.get theme "layout" let! layoutTemplate = TemplateCache.get theme "layout"
return! htmlString (layoutTemplate.Render hash) next ctx return! htmlString (layoutTemplate.Render hash) next ctx
} }
@ -115,6 +118,12 @@ module private Helpers =
return! viewForTheme (deriveWebLogFromHash hash ctx).themePath template next ctx hash return! viewForTheme (deriveWebLogFromHash hash ctx).themePath template next ctx hash
} }
/// Redirect after doing some action; commits session and issues a temporary redirect
let redirectToGet url : HttpHandler = fun next ctx -> task {
do! ctx.Session.CommitAsync ()
return! redirectTo false url next ctx
}
/// Get the web log ID for the current request /// Get the web log ID for the current request
let webLogId ctx = (WebLogCache.get ctx).id let webLogId ctx = (WebLogCache.get ctx).id
@ -233,7 +242,7 @@ module Admin =
WebLogCache.set ctx updated WebLogCache.set ctx updated
do! addMessage ctx { UserMessage.success with message = "Web log settings saved successfully" } do! addMessage ctx { UserMessage.success with message = "Web log settings saved successfully" }
return! redirectTo false "/admin" next ctx return! redirectToGet "/admin" next ctx
| None -> return! Error.notFound next ctx | None -> return! Error.notFound next ctx
} }
@ -318,7 +327,7 @@ module Page =
do! (match model.pageId with "new" -> Data.Page.add | _ -> Data.Page.update) page conn do! (match model.pageId with "new" -> Data.Page.add | _ -> Data.Page.update) page conn
if updateList then do! PageListCache.update ctx if updateList then do! PageListCache.update ctx
do! addMessage ctx { UserMessage.success with message = "Page saved successfully" } do! addMessage ctx { UserMessage.success with message = "Page saved successfully" }
return! redirectTo false $"/page/{PageId.toString page.id}/edit" next ctx return! redirectToGet $"/page/{PageId.toString page.id}/edit" next ctx
| None -> return! Error.notFound next ctx | None -> return! Error.notFound next ctx
} }
@ -428,7 +437,7 @@ module User =
message = "Logged on successfully" message = "Logged on successfully"
detail = Some $"Welcome to {webLog.name}!" detail = Some $"Welcome to {webLog.name}!"
} }
return! redirectTo false "/admin" next ctx return! redirectToGet "/admin" next ctx
| _ -> | _ ->
do! addMessage ctx { UserMessage.error with message = "Log on attempt unsuccessful" } do! addMessage ctx { UserMessage.error with message = "Log on attempt unsuccessful" }
return! logOn next ctx return! logOn next ctx
@ -438,7 +447,7 @@ module User =
let logOff : HttpHandler = fun next ctx -> task { let logOff : HttpHandler = fun next ctx -> task {
do! ctx.SignOutAsync CookieAuthenticationDefaults.AuthenticationScheme do! ctx.SignOutAsync CookieAuthenticationDefaults.AuthenticationScheme
do! addMessage ctx { UserMessage.info with message = "Log off successful" } do! addMessage ctx { UserMessage.info with message = "Log off successful" }
return! redirectTo false "/" next ctx return! redirectToGet "/" next ctx
} }

View File

@ -16,7 +16,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DotLiquid" Version="2.2.610" /> <PackageReference Include="DotLiquid" Version="2.2.610" />
<PackageReference Include="Giraffe" Version="6.0.0" /> <PackageReference Include="Giraffe" Version="6.0.0" />
<PackageReference Include="RethinkDB.DistributedCache" Version="0.9.0-alpha02" /> <PackageReference Include="RethinkDB.DistributedCache" Version="0.9.0-alpha03" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -164,7 +164,6 @@ let main args =
let _ = builder.Services.AddLogging () let _ = builder.Services.AddLogging ()
let _ = builder.Services.AddAuthorization () let _ = builder.Services.AddAuthorization ()
let _ = builder.Services.AddAntiforgery () let _ = builder.Services.AddAntiforgery ()
let _ = builder.Services.AddGiraffe ()
// Configure RethinkDB's connection // Configure RethinkDB's connection
JsonConverters.all () |> Seq.iter Converter.Serializer.Converters.Add JsonConverters.all () |> Seq.iter Converter.Serializer.Converters.Add
@ -180,14 +179,17 @@ let main args =
} |> Async.AwaitTask |> Async.RunSynchronously } |> Async.AwaitTask |> Async.RunSynchronously
let _ = builder.Services.AddSingleton<IConnection> conn let _ = builder.Services.AddSingleton<IConnection> conn
let _ = builder.Services.AddDistributedRethinkDBCache (fun opts -> // let _ = builder.Services.AddDistributedRethinkDBCache (fun opts ->
opts.Database <- rethinkCfg.Database // opts.Connection <- conn)
opts.Connection <- conn) let _ = builder.Services.AddDistributedMemoryCache ()
let _ = builder.Services.AddSession(fun opts -> let _ = builder.Services.AddSession(fun opts ->
opts.IdleTimeout <- TimeSpan.FromMinutes 30 opts.IdleTimeout <- TimeSpan.FromMinutes 30
opts.Cookie.HttpOnly <- true opts.Cookie.HttpOnly <- true
opts.Cookie.IsEssential <- true) opts.Cookie.IsEssential <- true)
// this needs to be after the session... maybe?
let _ = builder.Services.AddGiraffe ()
// Set up DotLiquid // Set up DotLiquid
Template.RegisterFilter typeof<DotLiquidBespoke.NavLinkFilter> Template.RegisterFilter typeof<DotLiquidBespoke.NavLinkFilter>
Template.RegisterTag<DotLiquidBespoke.UserLinksTag> "user_links" Template.RegisterTag<DotLiquidBespoke.UserLinksTag> "user_links"

View File

@ -1,24 +1,28 @@
<h2 class="my-3">{{ page_title }}</h2> <h2 class="my-3">{{ page_title }}</h2>
<article class="container"> <article class="container">
<a href="/page/new/edit" class="btn btn-primary btn-sm my-3">Create a New Page</a> <a href="/page/new/edit" class="btn btn-primary btn-sm mb-3">Create a New Page</a>
<table class="table table-sm table-striped table-hover"> <table class="table table-sm table-hover">
<thead> <thead>
<tr> <tr>
<th scope="col">Actions</th>
<th scope="col">Title</th> <th scope="col">Title</th>
<th scope="col">In List?</th>
<th scope="col">Last Updated</th> <th scope="col">Last Updated</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for pg in pages -%} {% for pg in pages -%}
<tr> <tr>
<td><a href="/page/{{ pg.id }}/edit">Edit</a></td>
<td> <td>
{{ pg.title }} {{ pg.title }}
{%- if pg.is_default %} &nbsp; <span class="badge bg-success">HOME PAGE</span>{% endif -%} {%- if pg.is_default %} &nbsp; <span class="badge bg-success">HOME PAGE</span>{% endif -%}
{%- if pg.show_in_page_list %} &nbsp; <span class="badge bg-primary">IN PAGE LIST</span> {% endif -%}<br>
<small>
<a href="/{% unless pg.is_default %}{{ pg.permalink }}{% endunless %}" target="_blank">View Page</a>
<span class="text-muted"> &bull; </span>
<a href="/page/{{ pg.id }}/edit">Edit Page</a>
<span class="text-muted"> &bull; </span>
<a href="#" class="text-danger">Delete Page</a>
</small>
</td> </td>
<td>{% if pg.show_in_page_list %} Yes {% else %} No {% endif %}</td>
<td>{{ pg.updated_on | date: "MMMM d, yyyy" }}</td> <td>{{ pg.updated_on | date: "MMMM d, yyyy" }}</td>
</tr> </tr>
{%- endfor %} {%- endfor %}