From 197a19d339144ee675ff76f01109d4142c1f9401 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Thu, 21 Jul 2016 08:05:07 -0500 Subject: [PATCH] page list The page list is now populated --- src/myWebLog.Data/Entities.fs | 10 ++++- src/myWebLog.Data/SetUp.fs | 42 +++++++++++-------- src/myWebLog.Data/WebLog.fs | 28 +++++++------ src/myWebLog.Web/ViewModels.fs | 2 + src/myWebLog/views/themes/default/layout.html | 1 + 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/myWebLog.Data/Entities.fs b/src/myWebLog.Data/Entities.fs index db87b7c..bde0a9b 100644 --- a/src/myWebLog.Data/Entities.fs +++ b/src/myWebLog.Data/Entities.fs @@ -90,6 +90,12 @@ with } +/// An entry in the list of pages displayed as part of the web log (derived via query) +type PageListEntry = { + permalink : string + title : string + } + /// A web log type WebLog = { /// The Id @@ -100,7 +106,7 @@ type WebLog = { subtitle : string option /// The default page ("posts" or a page Id) defaultPage : string - /// The path of the theme (within /views) + /// The path of the theme (within /views/themes) themePath : string /// The URL base urlBase : string @@ -108,7 +114,7 @@ type WebLog = { timeZone : string /// A list of pages to be rendered as part of the site navigation [] - pageList : Page list + pageList : PageListEntry list } with /// An empty web log diff --git a/src/myWebLog.Data/SetUp.fs b/src/myWebLog.Data/SetUp.fs index 8c6d8b5..c61c347 100644 --- a/src/myWebLog.Data/SetUp.fs +++ b/src/myWebLog.Data/SetUp.fs @@ -37,46 +37,52 @@ let checkTables cfg = let tbl cfg table = r.Db(cfg.database).Table(table) /// Create the given index -let createIndex cfg table (index : string * obj) = - logStepStart (sprintf """ Creating index "%s" on table %s""" (fst index) table) - (tbl cfg table).IndexCreate(fst index, snd index).RunResultAsync(cfg.conn) |> await |> ignore - (tbl cfg table).IndexWait(fst index).RunAtomAsync(cfg.conn) |> await |> ignore +let createIndex cfg table (index : string * (ReqlExpr -> obj) option) = + let idxName, idxFunc = index + logStepStart (sprintf """ Creating index "%s" on table %s""" idxName table) + match idxFunc with + | Some f -> (tbl cfg table).IndexCreate(idxName, f).RunResultAsync(cfg.conn) + | None -> (tbl cfg table).IndexCreate(idxName ).RunResultAsync(cfg.conn) + |> await |> ignore + (tbl cfg table).IndexWait(idxName).RunAtomAsync(cfg.conn) |> await |> ignore logStepDone () /// Ensure that the given indexes exist, and create them if required -let ensureIndexes cfg (indexes : (string * (string * obj) list) list) = +let ensureIndexes cfg (indexes : (string * (string * (ReqlExpr -> obj) option) list) list) = + let ensureForTable tabl = + let idx = (tbl cfg (fst tabl)).IndexList().RunListAsync(cfg.conn) |> await + snd tabl + |> List.iter (fun index -> match idx.Contains (fst index) with + | true -> () + | _ -> createIndex cfg (fst tabl) index) indexes - |> List.iter (fun tabl -> let idx = (tbl cfg (fst tabl)).IndexList().RunListAsync(cfg.conn) |> await - snd tabl - |> List.iter (fun index -> match idx.Contains (fst index) with - | true -> () - | _ -> createIndex cfg (fst tabl) index)) + |> List.iter ensureForTable /// Create an index on a single field let singleField (name : string) : obj = upcast (fun row -> (row :> ReqlExpr).[name]) /// Create an index on web log Id and the given field -let webLogField (name : string) : obj = upcast (fun row -> r.Array((row :> ReqlExpr).["webLogId"], row.[name])) +let webLogField (name : string) : (ReqlExpr -> obj) option = + Some <| fun row -> upcast r.Array(row.["webLogId"], row.[name]) /// Ensure all the required indexes exist let checkIndexes cfg = logStep "|> Checking indexes" - [ Table.Category, [ "webLogId", singleField "webLogId" + [ Table.Category, [ "webLogId", None "slug", webLogField "slug" ] - Table.Comment, [ "postId", singleField "postId" + Table.Comment, [ "postId", None ] - Table.Page, [ "webLogId", singleField "webLogId" + Table.Page, [ "webLogId", None "permalink", webLogField "permalink" - "pageList", webLogField "showInPageList" ] - Table.Post, [ "webLogId", singleField "webLogId" + Table.Post, [ "webLogId", None "webLogAndStatus", webLogField "status" "permalink", webLogField "permalink" ] - Table.User, [ "logOn", upcast (fun row -> r.Array((row :> ReqlExpr).["userName"], row.["passwordHash"])) + Table.User, [ "logOn", Some <| fun row -> upcast r.Array(row.["userName"], row.["passwordHash"]) ] - Table.WebLog, [ "urlBase", singleField "urlBase" + Table.WebLog, [ "urlBase", None ] ] |> ensureIndexes cfg diff --git a/src/myWebLog.Data/WebLog.fs b/src/myWebLog.Data/WebLog.fs index 57d8c35..62a5992 100644 --- a/src/myWebLog.Data/WebLog.fs +++ b/src/myWebLog.Data/WebLog.fs @@ -7,18 +7,20 @@ open System.Dynamic let private r = RethinkDb.Driver.RethinkDB.R -type PageList = { pageList : obj } - /// Detemine the web log by the URL base +// TODO: see if we can make .Merge work for page list even though the attribute is ignored +// (needs to be ignored for serialization, but included for deserialization) let tryFindWebLogByUrlBase conn (urlBase : string) = - r.Table(Table.WebLog) - .GetAll(urlBase).OptArg("index", "urlBase") - .Merge(fun webLog -> { pageList = - r.Table(Table.Page) - .GetAll(webLog.["id"], true).OptArg("index", "pageList") - .OrderBy("title") - .Pluck("title", "permalink") - .CoerceTo("array") }) - .RunCursorAsync(conn) - |> await - |> Seq.tryHead + let webLog = r.Table(Table.WebLog) + .GetAll(urlBase).OptArg("index", "urlBase") + .RunCursorAsync(conn) + |> await + |> Seq.tryHead + match webLog with + | Some w -> Some { w with pageList = r.Table(Table.Page) + .GetAll(w.id).OptArg("index", "webLogId") + .Filter(fun pg -> pg.["showInPageList"].Eq(true)) + .OrderBy("title") + .Pluck("title", "permalink") + .RunListAsync(conn) |> await |> Seq.toList } + | None -> None diff --git a/src/myWebLog.Web/ViewModels.fs b/src/myWebLog.Web/ViewModels.fs index 5c92df6..4c2c7b3 100644 --- a/src/myWebLog.Web/ViewModels.fs +++ b/src/myWebLog.Web/ViewModels.fs @@ -55,6 +55,8 @@ type MyWebLogModel(ctx : NancyContext, webLog : WebLog) = member this.user = ctx.Request.PersistableSession.GetOrDefault(Keys.User, User.empty) /// The title of the page member val pageTitle = "" with get, set + /// The name and version of the application + member this.generator = sprintf "myWebLog %s" (ctx.Items.[Keys.Version].ToString ()) /// The request start time member this.requestStart = ctx.Items.[Keys.RequestStart] :?> int64 /// Is a user authenticated for this request? diff --git a/src/myWebLog/views/themes/default/layout.html b/src/myWebLog/views/themes/default/layout.html index f670fbe..8ec9c05 100644 --- a/src/myWebLog/views/themes/default/layout.html +++ b/src/myWebLog/views/themes/default/layout.html @@ -1,6 +1,7 @@  + @Model.pageTitle | @Model.webLog.name