From c3d615d10a5555cc18e35a51a943abae617aa43d Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sat, 16 Dec 2023 14:05:45 -0500 Subject: [PATCH] WIP on module/member conversion Data types complete --- src/MyWebLog.Data/MyWebLog.Data.fsproj | 1 - .../Postgres/PostgresCategoryData.fs | 6 +- .../Postgres/PostgresPageData.fs | 10 +- .../Postgres/PostgresPostData.fs | 20 +- .../Postgres/PostgresTagMapData.fs | 2 +- .../Postgres/PostgresWebLogData.fs | 2 +- .../Postgres/PostgresWebLogUserData.fs | 4 +- src/MyWebLog.Data/PostgresData.fs | 22 +- src/MyWebLog.Data/RethinkDbData.fs | 254 ++++++++-------- src/MyWebLog.Data/SQLite/Helpers.fs | 6 +- .../SQLite/SQLiteWebLogUserData.fs | 3 +- src/MyWebLog.Domain/DataTypes.fs | 284 ++++++++---------- src/MyWebLog.Domain/MyWebLog.Domain.fsproj | 1 + src/MyWebLog.Domain/SupportTypes.fs | 10 +- src/MyWebLog.Domain/ViewModels.fs | 144 +++++---- src/MyWebLog/Caches.fs | 10 +- src/MyWebLog/DotLiquidBespoke.fs | 76 ++--- src/MyWebLog/Handlers/Admin.fs | 10 +- src/MyWebLog/Handlers/Feed.fs | 73 ++--- src/MyWebLog/Handlers/Helpers.fs | 2 +- src/MyWebLog/Handlers/Page.fs | 7 +- src/MyWebLog/Handlers/Post.fs | 13 +- src/MyWebLog/Handlers/Routes.fs | 18 +- src/MyWebLog/Handlers/Upload.fs | 2 +- src/MyWebLog/Handlers/User.fs | 16 +- src/MyWebLog/Maintenance.fs | 6 +- 26 files changed, 481 insertions(+), 521 deletions(-) diff --git a/src/MyWebLog.Data/MyWebLog.Data.fsproj b/src/MyWebLog.Data/MyWebLog.Data.fsproj index 707825c..442d62f 100644 --- a/src/MyWebLog.Data/MyWebLog.Data.fsproj +++ b/src/MyWebLog.Data/MyWebLog.Data.fsproj @@ -10,7 +10,6 @@ - diff --git a/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs b/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs index b78be64..a740ea8 100644 --- a/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs +++ b/src/MyWebLog.Data/Postgres/PostgresCategoryData.fs @@ -23,7 +23,7 @@ type PostgresCategoryData(log: ILogger) = let findAllForView webLogId = backgroundTask { log.LogTrace "Category.findAllForView" let! cats = - Custom.list $"{selectWithCriteria Table.Category} ORDER BY LOWER(data ->> '{nameof Category.empty.Name}')" + Custom.list $"{selectWithCriteria Table.Category} ORDER BY LOWER(data ->> '{nameof Category.Empty.Name}')" [ webLogContains webLogId ] fromData let ordered = Utils.orderByHierarchy cats None None [] let counts = @@ -36,7 +36,7 @@ type PostgresCategoryData(log: ILogger) = |> Seq.map _.Id |> Seq.append (Seq.singleton it.Id) |> List.ofSeq - |> arrayContains (nameof Post.empty.CategoryIds) id + |> arrayContains (nameof Post.Empty.CategoryIds) id let postCount = Custom.scalar $"""SELECT COUNT(DISTINCT id) AS {countName} @@ -97,7 +97,7 @@ type PostgresCategoryData(log: ILogger) = () // Delete the category off all posts where it is assigned let! posts = - Custom.list $"SELECT data FROM {Table.Post} WHERE data -> '{nameof Post.empty.CategoryIds}' @> @id" + Custom.list $"SELECT data FROM {Table.Post} WHERE data -> '{nameof Post.Empty.CategoryIds}' @> @id" [ "@id", Query.jsonbDocParam [| string catId |] ] fromData if not (List.isEmpty posts) then let! _ = diff --git a/src/MyWebLog.Data/Postgres/PostgresPageData.fs b/src/MyWebLog.Data/Postgres/PostgresPageData.fs index 7bf8c80..766fd14 100644 --- a/src/MyWebLog.Data/Postgres/PostgresPageData.fs +++ b/src/MyWebLog.Data/Postgres/PostgresPageData.fs @@ -37,7 +37,7 @@ type PostgresPageData (log: ILogger) = /// Get all pages for a web log (without text or revisions) let all webLogId = log.LogTrace "Page.all" - Custom.list $"{selectWithCriteria Table.Page} ORDER BY LOWER(data ->> '{nameof Page.empty.Title}')" + Custom.list $"{selectWithCriteria Table.Page} ORDER BY LOWER(data ->> '{nameof Page.Empty.Title}')" [ webLogContains webLogId ] fromData /// Count all pages for the given web log @@ -86,10 +86,10 @@ type PostgresPageData (log: ILogger) = log.LogTrace "Page.findCurrentPermalink" if List.isEmpty permalinks then return None else - let linkSql, linkParam = arrayContains (nameof Page.empty.PriorPermalinks) string permalinks + let linkSql, linkParam = arrayContains (nameof Page.Empty.PriorPermalinks) string permalinks return! Custom.single - $"""SELECT data ->> '{nameof Page.empty.Permalink}' AS permalink + $"""SELECT data ->> '{nameof Page.Empty.Permalink}' AS permalink FROM page WHERE {Query.whereDataContains "@criteria"} AND {linkSql}""" [ webLogContains webLogId; linkParam ] Map.toPermalink @@ -109,7 +109,7 @@ type PostgresPageData (log: ILogger) = /// Get all listed pages for the given web log (without revisions or text) let findListed webLogId = log.LogTrace "Page.findListed" - Custom.list $"{selectWithCriteria Table.Page} ORDER BY LOWER(data ->> '{nameof Page.empty.Title}')" + Custom.list $"{selectWithCriteria Table.Page} ORDER BY LOWER(data ->> '{nameof Page.Empty.Title}')" [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with IsInPageList = true |} ] pageWithoutText @@ -118,7 +118,7 @@ type PostgresPageData (log: ILogger) = log.LogTrace "Page.findPageOfPages" Custom.list $"{selectWithCriteria Table.Page} - ORDER BY LOWER(data->>'{nameof Page.empty.Title}') + ORDER BY LOWER(data->>'{nameof Page.Empty.Title}') LIMIT @pageSize OFFSET @toSkip" [ webLogContains webLogId; "@pageSize", Sql.int 26; "@toSkip", Sql.int ((pageNbr - 1) * 25) ] fromData diff --git a/src/MyWebLog.Data/Postgres/PostgresPostData.fs b/src/MyWebLog.Data/Postgres/PostgresPostData.fs index 7984d35..3ccef17 100644 --- a/src/MyWebLog.Data/Postgres/PostgresPostData.fs +++ b/src/MyWebLog.Data/Postgres/PostgresPostData.fs @@ -80,10 +80,10 @@ type PostgresPostData(log: ILogger) = log.LogTrace "Post.findCurrentPermalink" if List.isEmpty permalinks then return None else - let linkSql, linkParam = arrayContains (nameof Post.empty.PriorPermalinks) string permalinks + let linkSql, linkParam = arrayContains (nameof Post.Empty.PriorPermalinks) string permalinks return! Custom.single - $"""SELECT data ->> '{nameof Post.empty.Permalink}' AS permalink + $"""SELECT data ->> '{nameof Post.Empty.Permalink}' AS permalink FROM {Table.Post} WHERE {Query.whereDataContains "@criteria"} AND {linkSql}""" [ webLogContains webLogId; linkParam ] Map.toPermalink @@ -103,11 +103,11 @@ type PostgresPostData(log: ILogger) = /// Get a page of categorized posts for the given web log (excludes revisions) let findPageOfCategorizedPosts webLogId (categoryIds: CategoryId list) pageNbr postsPerPage = log.LogTrace "Post.findPageOfCategorizedPosts" - let catSql, catParam = arrayContains (nameof Post.empty.CategoryIds) string categoryIds + let catSql, catParam = arrayContains (nameof Post.Empty.CategoryIds) string categoryIds Custom.list $"{selectWithCriteria Table.Post} AND {catSql} - ORDER BY data ->> '{nameof Post.empty.PublishedOn}' DESC + ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |} catParam @@ -118,8 +118,8 @@ type PostgresPostData(log: ILogger) = log.LogTrace "Post.findPageOfPosts" Custom.list $"{selectWithCriteria Table.Post} - ORDER BY data ->> '{nameof Post.empty.PublishedOn}' DESC NULLS FIRST, - data ->> '{nameof Post.empty.UpdatedOn}' + ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC NULLS FIRST, + data ->> '{nameof Post.Empty.UpdatedOn}' LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" [ webLogContains webLogId ] postWithoutText @@ -128,7 +128,7 @@ type PostgresPostData(log: ILogger) = log.LogTrace "Post.findPageOfPublishedPosts" Custom.list $"{selectWithCriteria Table.Post} - ORDER BY data ->> '{nameof Post.empty.PublishedOn}' DESC + ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |} ] fromData @@ -138,8 +138,8 @@ type PostgresPostData(log: ILogger) = log.LogTrace "Post.findPageOfTaggedPosts" Custom.list $"{selectWithCriteria Table.Post} - AND data['{nameof Post.empty.Tags}'] @> @tag - ORDER BY data ->> '{nameof Post.empty.PublishedOn}' DESC + AND data['{nameof Post.Empty.Tags}'] @> @tag + ORDER BY data ->> '{nameof Post.Empty.PublishedOn}' DESC LIMIT {postsPerPage + 1} OFFSET {(pageNbr - 1) * postsPerPage}" [ "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |} "@tag", Query.jsonbDocParam [| tag |] @@ -152,7 +152,7 @@ type PostgresPostData(log: ILogger) = "@criteria", Query.jsonbDocParam {| webLogDoc webLogId with Status = Published |} "@publishedOn", Sql.string ((InstantPattern.General.Format publishedOn)[..19]) ] - let pubField = nameof Post.empty.PublishedOn + let pubField = nameof Post.Empty.PublishedOn let! older = Custom.list $"{selectWithCriteria Table.Post} diff --git a/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs b/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs index 100523a..c252f7b 100644 --- a/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs +++ b/src/MyWebLog.Data/Postgres/PostgresTagMapData.fs @@ -40,7 +40,7 @@ type PostgresTagMapData (log : ILogger) = /// Find any tag mappings in a list of tags for the given web log let findMappingForTags tags webLogId = log.LogTrace "TagMap.findMappingForTags" - let tagSql, tagParam = arrayContains (nameof TagMap.empty.Tag) id tags + let tagSql, tagParam = arrayContains (nameof TagMap.Empty.Tag) id tags Custom.list $"{selectWithCriteria Table.TagMap} AND {tagSql}" [ webLogContains webLogId; tagParam ] fromData diff --git a/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs b/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs index 0efc85d..7015724 100644 --- a/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs +++ b/src/MyWebLog.Data/Postgres/PostgresWebLogData.fs @@ -23,7 +23,7 @@ type PostgresWebLogData (log : ILogger) = log.LogTrace "WebLog.delete" Custom.nonQuery $"""DELETE FROM {Table.PostComment} - WHERE data ->> '{nameof Comment.empty.PostId}' IN + WHERE data ->> '{nameof Comment.Empty.PostId}' IN (SELECT id FROM {Table.Post} WHERE {Query.whereDataContains "@criteria"}); {Query.Delete.byContains Table.Post}; {Query.Delete.byContains Table.Page}; diff --git a/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs b/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs index dba0985..22090ce 100644 --- a/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs +++ b/src/MyWebLog.Data/Postgres/PostgresWebLogUserData.fs @@ -45,7 +45,7 @@ type PostgresWebLogUserData (log : ILogger) = let findByWebLog webLogId = log.LogTrace "WebLogUser.findByWebLog" Custom.list - $"{selectWithCriteria Table.WebLogUser} ORDER BY LOWER(data->>'{nameof WebLogUser.empty.PreferredName}')" + $"{selectWithCriteria Table.WebLogUser} ORDER BY LOWER(data->>'{nameof WebLogUser.Empty.PreferredName}')" [ webLogContains webLogId ] fromData /// Find the names of users by their IDs for the given web log @@ -55,7 +55,7 @@ type PostgresWebLogUserData (log : ILogger) = let! users = Custom.list $"{selectWithCriteria Table.WebLogUser} {idSql}" (webLogContains webLogId :: idParams) fromData - return users |> List.map (fun u -> { Name = string u.Id; Value = WebLogUser.displayName u }) + return users |> List.map (fun u -> { Name = string u.Id; Value = u.DisplayName }) } /// Restore users from a backup diff --git a/src/MyWebLog.Data/PostgresData.fs b/src/MyWebLog.Data/PostgresData.fs index 0b788b0..1c01195 100644 --- a/src/MyWebLog.Data/PostgresData.fs +++ b/src/MyWebLog.Data/PostgresData.fs @@ -58,10 +58,10 @@ type PostgresData (log : ILogger, ser : JsonSerializer) = // Page tables if needsTable Table.Page then Definition.createTable Table.Page - $"CREATE INDEX page_web_log_idx ON {Table.Page} ((data ->> '{nameof Page.empty.WebLogId}'))" - $"CREATE INDEX page_author_idx ON {Table.Page} ((data ->> '{nameof Page.empty.AuthorId}'))" + $"CREATE INDEX page_web_log_idx ON {Table.Page} ((data ->> '{nameof Page.Empty.WebLogId}'))" + $"CREATE INDEX page_author_idx ON {Table.Page} ((data ->> '{nameof Page.Empty.AuthorId}'))" $"CREATE INDEX page_permalink_idx ON {Table.Page} - ((data ->> '{nameof Page.empty.WebLogId}'), (data ->> '{nameof Page.empty.Permalink}'))" + ((data ->> '{nameof Page.Empty.WebLogId}'), (data ->> '{nameof Page.Empty.Permalink}'))" if needsTable Table.PageRevision then $"CREATE TABLE {Table.PageRevision} ( page_id TEXT NOT NULL REFERENCES {Table.Page} (id) ON DELETE CASCADE, @@ -72,15 +72,15 @@ type PostgresData (log : ILogger, ser : JsonSerializer) = // Post tables if needsTable Table.Post then Definition.createTable Table.Post - $"CREATE INDEX post_web_log_idx ON {Table.Post} ((data ->> '{nameof Post.empty.WebLogId}'))" - $"CREATE INDEX post_author_idx ON {Table.Post} ((data ->> '{nameof Post.empty.AuthorId}'))" + $"CREATE INDEX post_web_log_idx ON {Table.Post} ((data ->> '{nameof Post.Empty.WebLogId}'))" + $"CREATE INDEX post_author_idx ON {Table.Post} ((data ->> '{nameof Post.Empty.AuthorId}'))" $"CREATE INDEX post_status_idx ON {Table.Post} - ((data ->> '{nameof Post.empty.WebLogId}'), (data ->> '{nameof Post.empty.Status}'), - (data ->> '{nameof Post.empty.UpdatedOn}'))" + ((data ->> '{nameof Post.Empty.WebLogId}'), (data ->> '{nameof Post.Empty.Status}'), + (data ->> '{nameof Post.Empty.UpdatedOn}'))" $"CREATE INDEX post_permalink_idx ON {Table.Post} - ((data ->> '{nameof Post.empty.WebLogId}'), (data ->> '{nameof Post.empty.Permalink}'))" - $"CREATE INDEX post_category_idx ON {Table.Post} USING GIN ((data['{nameof Post.empty.CategoryIds}']))" - $"CREATE INDEX post_tag_idx ON {Table.Post} USING GIN ((data['{nameof Post.empty.Tags}']))" + ((data ->> '{nameof Post.Empty.WebLogId}'), (data ->> '{nameof Post.Empty.Permalink}'))" + $"CREATE INDEX post_category_idx ON {Table.Post} USING GIN ((data['{nameof Post.Empty.CategoryIds}']))" + $"CREATE INDEX post_tag_idx ON {Table.Post} USING GIN ((data['{nameof Post.Empty.Tags}']))" if needsTable Table.PostRevision then $"CREATE TABLE {Table.PostRevision} ( post_id TEXT NOT NULL REFERENCES {Table.Post} (id) ON DELETE CASCADE, @@ -90,7 +90,7 @@ type PostgresData (log : ILogger, ser : JsonSerializer) = if needsTable Table.PostComment then Definition.createTable Table.PostComment $"CREATE INDEX post_comment_post_idx ON {Table.PostComment} - ((data ->> '{nameof Comment.empty.PostId}'))" + ((data ->> '{nameof Comment.Empty.PostId}'))" // Tag map table if needsTable Table.TagMap then diff --git a/src/MyWebLog.Data/RethinkDbData.fs b/src/MyWebLog.Data/RethinkDbData.fs index acda3a6..068b2b1 100644 --- a/src/MyWebLog.Data/RethinkDbData.fs +++ b/src/MyWebLog.Data/RethinkDbData.fs @@ -97,11 +97,11 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger row[nameof ThemeAsset.empty.Id].Match keyPrefix :> obj + fun (row : Ast.ReqlExpr) -> row[nameof ThemeAsset.Empty.Id].Match keyPrefix :> obj /// Function to exclude template text from themes let withoutTemplateText (row : Ast.ReqlExpr) : obj = - {| Templates = row[nameof Theme.empty.Templates].Without [| nameof ThemeTemplate.Empty.Text |] |} + {| Templates = row[nameof Theme.Empty.Templates].Without [| nameof ThemeTemplate.Empty.Text |] |} /// Ensure field indexes exist, as well as special indexes for selected tables let ensureIndexes table fields = backgroundTask { @@ -112,27 +112,27 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger List.contains table then - let permalinkIdx = nameof Page.empty.Permalink + let permalinkIdx = nameof Page.Empty.Permalink if not (indexes |> List.contains permalinkIdx) then log.LogInformation $"Creating index {table}.{permalinkIdx}..." do! rethink { withTable table indexCreate permalinkIdx - (fun row -> r.Array (row[nameof Page.empty.WebLogId], row[permalinkIdx].Downcase ()) :> obj) + (fun row -> r.Array(row[nameof Page.Empty.WebLogId], row[permalinkIdx].Downcase()) :> obj) write; withRetryOnce; ignoreResult conn } // Prior permalinks are searched when a post or page permalink do not match the current URL - let priorIdx = nameof Post.empty.PriorPermalinks + let priorIdx = nameof Post.Empty.PriorPermalinks if not (indexes |> List.contains priorIdx) then log.LogInformation $"Creating index {table}.{priorIdx}..." do! rethink { withTable table - indexCreate priorIdx (fun row -> row[priorIdx].Downcase () :> obj) [ Multi ] + indexCreate priorIdx (fun row -> row[priorIdx].Downcase() :> obj) [ Multi ] write; withRetryOnce; ignoreResult conn } // Post needs indexes by category and tag (used for counting and retrieving posts) if Table.Post = table then - for idx in [ nameof Post.empty.CategoryIds; nameof Post.empty.Tags ] do + for idx in [ nameof Post.Empty.CategoryIds; nameof Post.Empty.Tags ] do if not (List.contains idx indexes) then log.LogInformation $"Creating index {table}.{idx}..." do! rethink { @@ -147,7 +147,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger - [| row[nameof TagMap.empty.WebLogId]; row[nameof TagMap.empty.Tag] |] :> obj) + [| row[nameof TagMap.Empty.WebLogId]; row[nameof TagMap.Empty.Tag] |] :> obj) write; withRetryOnce; ignoreResult conn } if not (indexes |> List.contains Index.WebLogAndUrl) then @@ -155,7 +155,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger - [| row[nameof TagMap.empty.WebLogId]; row[nameof TagMap.empty.UrlValue] |] :> obj) + [| row[nameof TagMap.Empty.WebLogId]; row[nameof TagMap.Empty.UrlValue] |] :> obj) write; withRetryOnce; ignoreResult conn } // Uploaded files need an index by web log ID and path, as that is how they are retrieved @@ -165,7 +165,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger - [| row[nameof Upload.empty.WebLogId]; row[nameof Upload.empty.Path] |] :> obj) + [| row[nameof Upload.Empty.WebLogId]; row[nameof Upload.Empty.Path] |] :> obj) write; withRetryOnce; ignoreResult conn } // Users log on with e-mail @@ -175,7 +175,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger - [| row[nameof WebLogUser.empty.WebLogId]; row[nameof WebLogUser.empty.Email] |] :> obj) + [| row[nameof WebLogUser.Empty.WebLogId]; row[nameof WebLogUser.Empty.Email] |] :> obj) write; withRetryOnce; ignoreResult conn } } @@ -226,7 +226,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger obj ] + update [ nameof WebLog.Empty.RedirectRules, [] :> obj ] write; withRetryOnce; ignoreResult conn } @@ -271,15 +271,15 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Category - getAll [ webLogId ] (nameof Category.empty.WebLogId) + getAll [ webLogId ] (nameof Category.Empty.WebLogId) count result; withRetryDefault conn } member _.CountTopLevel webLogId = rethink { withTable Table.Category - getAll [ webLogId ] (nameof Category.empty.WebLogId) - filter (nameof Category.empty.ParentId) None + getAll [ webLogId ] (nameof Category.Empty.WebLogId) + filter (nameof Category.Empty.ParentId) None count result; withRetryDefault conn } @@ -287,8 +287,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Category - getAll [ webLogId ] (nameof Category.empty.WebLogId) - orderByFunc (fun it -> it[nameof Category.empty.Name].Downcase () :> obj) + getAll [ webLogId ] (nameof Category.Empty.WebLogId) + orderByFunc (fun it -> it[nameof Category.Empty.Name].Downcase() :> obj) result; withRetryDefault conn } let ordered = Utils.orderByHierarchy cats None None [] @@ -304,8 +304,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger List.ofSeq let! count = rethink { withTable Table.Post - getAll catIds (nameof Post.empty.CategoryIds) - filter (nameof Post.empty.Status) Published + getAll catIds (nameof Post.Empty.CategoryIds) + filter (nameof Post.Empty.Status) Published distinct count result; withRetryDefault conn @@ -335,7 +335,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Category - getAll [ webLogId ] (nameof Category.empty.WebLogId) + getAll [ webLogId ] (nameof Category.Empty.WebLogId) result; withRetryDefault conn } @@ -345,24 +345,24 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Category - filter (nameof Category.empty.ParentId) catId + filter (nameof Category.Empty.ParentId) catId count result; withRetryDefault conn } if children > 0 then do! rethink { withTable Table.Category - filter (nameof Category.empty.ParentId) catId - update [ nameof Category.empty.ParentId, cat.ParentId :> obj ] + filter (nameof Category.Empty.ParentId) catId + update [ nameof Category.Empty.ParentId, cat.ParentId :> obj ] write; withRetryDefault; ignoreResult conn } // Delete the category off all posts where it is assigned do! rethink { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - filter (fun row -> row[nameof Post.empty.CategoryIds].Contains catId :> obj) + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + filter (fun row -> row[nameof Post.Empty.CategoryIds].Contains catId :> obj) update (fun row -> - {| CategoryIds = r.Array(row[nameof Post.empty.CategoryIds]).Remove catId |} :> obj) + {| CategoryIds = r.Array(row[nameof Post.Empty.CategoryIds]).Remove catId |} :> obj) write; withRetryDefault; ignoreResult conn } // Delete the category itself @@ -408,26 +408,26 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Page - getAll [ webLogId ] (nameof Page.empty.WebLogId) - without [ nameof Page.empty.Text - nameof Page.empty.Metadata - nameof Page.empty.Revisions - nameof Page.empty.PriorPermalinks ] - orderByFunc (fun row -> row[nameof Page.empty.Title].Downcase () :> obj) + getAll [ webLogId ] (nameof Page.Empty.WebLogId) + without [ nameof Page.Empty.Text + nameof Page.Empty.Metadata + nameof Page.Empty.Revisions + nameof Page.Empty.PriorPermalinks ] + orderByFunc (fun row -> row[nameof Page.Empty.Title].Downcase() :> obj) result; withRetryDefault conn } member _.CountAll webLogId = rethink { withTable Table.Page - getAll [ webLogId ] (nameof Page.empty.WebLogId) + getAll [ webLogId ] (nameof Page.Empty.WebLogId) count result; withRetryDefault conn } member _.CountListed webLogId = rethink { withTable Table.Page - getAll [ webLogId ] (nameof Page.empty.WebLogId) - filter (nameof Page.empty.IsInPageList) true + getAll [ webLogId ] (nameof Page.Empty.WebLogId) + filter (nameof Page.Empty.IsInPageList) true count result; withRetryDefault conn } @@ -436,7 +436,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Page getAll [ pageId ] - filter (fun row -> row[nameof Page.empty.WebLogId].Eq webLogId :> obj) + filter (fun row -> row[nameof Page.Empty.WebLogId].Eq webLogId :> obj) delete write; withRetryDefault conn } @@ -447,7 +447,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Page get pageId - without [ nameof Page.empty.PriorPermalinks; nameof Page.empty.Revisions ] + without [ nameof Page.Empty.PriorPermalinks; nameof Page.Empty.Revisions ] resultOption; withRetryOptionDefault } |> verifyWebLog webLogId (fun it -> it.WebLogId) <| conn @@ -455,8 +455,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Page - getAll [ [| webLogId :> obj; permalink |] ] (nameof Page.empty.Permalink) - without [ nameof Page.empty.PriorPermalinks; nameof Page.empty.Revisions ] + getAll [ [| webLogId :> obj; permalink |] ] (nameof Page.Empty.Permalink) + without [ nameof Page.Empty.PriorPermalinks; nameof Page.Empty.Revisions ] limit 1 result; withRetryDefault } @@ -466,9 +466,9 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Page - getAll (objList permalinks) (nameof Page.empty.PriorPermalinks) - filter (nameof Page.empty.WebLogId) webLogId - without [ nameof Page.empty.Revisions; nameof Page.empty.Text ] + getAll (objList permalinks) (nameof Page.Empty.PriorPermalinks) + filter (nameof Page.Empty.WebLogId) webLogId + without [ nameof Page.Empty.Revisions; nameof Page.Empty.Text ] limit 1 result; withRetryDefault } @@ -486,26 +486,26 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Page - getAll [ webLogId ] (nameof Page.empty.WebLogId) + getAll [ webLogId ] (nameof Page.Empty.WebLogId) resultCursor; withRetryCursorDefault; toList conn } member _.FindListed webLogId = rethink { withTable Table.Page - getAll [ webLogId ] (nameof Page.empty.WebLogId) - filter [ nameof Page.empty.IsInPageList, true :> obj ] - without [ nameof Page.empty.Text; nameof Page.empty.PriorPermalinks; nameof Page.empty.Revisions ] - orderBy (nameof Page.empty.Title) + getAll [ webLogId ] (nameof Page.Empty.WebLogId) + filter [ nameof Page.Empty.IsInPageList, true :> obj ] + without [ nameof Page.Empty.Text; nameof Page.Empty.PriorPermalinks; nameof Page.Empty.Revisions ] + orderBy (nameof Page.Empty.Title) result; withRetryDefault conn } member _.FindPageOfPages webLogId pageNbr = rethink { withTable Table.Page - getAll [ webLogId ] (nameof Page.empty.WebLogId) - without [ nameof Page.empty.Metadata - nameof Page.empty.PriorPermalinks - nameof Page.empty.Revisions ] - orderByFunc (fun row -> row[nameof Page.empty.Title].Downcase ()) + getAll [ webLogId ] (nameof Page.Empty.WebLogId) + without [ nameof Page.Empty.Metadata + nameof Page.Empty.PriorPermalinks + nameof Page.Empty.Revisions ] + orderByFunc (fun row -> row[nameof Page.Empty.Title].Downcase()) skip ((pageNbr - 1) * 25) limit 25 result; withRetryDefault conn @@ -543,7 +543,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger obj ] + update [ nameof Page.Empty.PriorPermalinks, permalinks :> obj ] write; withRetryDefault; ignoreResult conn } return true @@ -562,8 +562,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - filter (nameof Post.empty.Status) status + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + filter (nameof Post.Empty.Status) status count result; withRetryDefault conn } @@ -572,7 +572,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post getAll [ postId ] - filter (fun row -> row[nameof Post.empty.WebLogId].Eq webLogId :> obj) + filter (fun row -> row[nameof Post.Empty.WebLogId].Eq webLogId :> obj) delete write; withRetryDefault conn } @@ -583,7 +583,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post get postId - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] resultOption; withRetryOptionDefault } |> verifyWebLog webLogId (fun p -> p.WebLogId) <| conn @@ -591,8 +591,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ [| webLogId :> obj; permalink |] ] (nameof Post.empty.Permalink) - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] + getAll [ [| webLogId :> obj; permalink |] ] (nameof Post.Empty.Permalink) + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] limit 1 result; withRetryDefault } @@ -610,9 +610,9 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll (objList permalinks) (nameof Post.empty.PriorPermalinks) - filter (nameof Post.empty.WebLogId) webLogId - without [ nameof Post.empty.Revisions; nameof Post.empty.Text ] + getAll (objList permalinks) (nameof Post.Empty.PriorPermalinks) + filter (nameof Post.Empty.WebLogId) webLogId + without [ nameof Post.Empty.Revisions; nameof Post.Empty.Text ] limit 1 result; withRetryDefault } @@ -622,18 +622,18 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) + getAll [ webLogId ] (nameof Post.Empty.WebLogId) resultCursor; withRetryCursorDefault; toList conn } member _.FindPageOfCategorizedPosts webLogId categoryIds pageNbr postsPerPage = rethink { withTable Table.Post - getAll (objList categoryIds) (nameof Post.empty.CategoryIds) - filter [ nameof Post.empty.WebLogId, webLogId :> obj - nameof Post.empty.Status, Published ] - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] + getAll (objList categoryIds) (nameof Post.Empty.CategoryIds) + filter [ nameof Post.Empty.WebLogId, webLogId :> obj + nameof Post.Empty.Status, Published ] + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] distinct - orderByDescending (nameof Post.empty.PublishedOn) + orderByDescending (nameof Post.Empty.PublishedOn) skip ((pageNbr - 1) * postsPerPage) limit (postsPerPage + 1) result; withRetryDefault conn @@ -641,10 +641,10 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] orderByFuncDescending (fun row -> - row[nameof Post.empty.PublishedOn].Default_ (nameof Post.empty.UpdatedOn) :> obj) + row[nameof Post.Empty.PublishedOn].Default_(nameof Post.Empty.UpdatedOn) :> obj) skip ((pageNbr - 1) * postsPerPage) limit (postsPerPage + 1) result; withRetryDefault conn @@ -652,10 +652,10 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - filter (nameof Post.empty.Status) Published - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] - orderByDescending (nameof Post.empty.PublishedOn) + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + filter (nameof Post.Empty.Status) Published + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] + orderByDescending (nameof Post.Empty.PublishedOn) skip ((pageNbr - 1) * postsPerPage) limit (postsPerPage + 1) result; withRetryDefault conn @@ -663,11 +663,11 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ tag ] (nameof Post.empty.Tags) - filter [ nameof Post.empty.WebLogId, webLogId :> obj - nameof Post.empty.Status, Published ] - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] - orderByDescending (nameof Post.empty.PublishedOn) + getAll [ tag ] (nameof Post.Empty.Tags) + filter [ nameof Post.Empty.WebLogId, webLogId :> obj + nameof Post.Empty.Status, Published ] + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] + orderByDescending (nameof Post.Empty.PublishedOn) skip ((pageNbr - 1) * postsPerPage) limit (postsPerPage + 1) result; withRetryDefault conn @@ -677,10 +677,10 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - filter (fun row -> row[nameof Post.empty.PublishedOn].Lt publishedOn :> obj) - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] - orderByDescending (nameof Post.empty.PublishedOn) + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + filter (fun row -> row[nameof Post.Empty.PublishedOn].Lt publishedOn :> obj) + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] + orderByDescending (nameof Post.Empty.PublishedOn) limit 1 result; withRetryDefault } @@ -688,10 +688,10 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - filter (fun row -> row[nameof Post.empty.PublishedOn].Gt publishedOn :> obj) - without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ] - orderBy (nameof Post.empty.PublishedOn) + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + filter (fun row -> row[nameof Post.Empty.PublishedOn].Gt publishedOn :> obj) + without [ nameof Post.Empty.PriorPermalinks; nameof Post.Empty.Revisions ] + orderBy (nameof Post.Empty.PublishedOn) limit 1 result; withRetryDefault } @@ -720,15 +720,15 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post get postId - without [ nameof Post.empty.Revisions; nameof Post.empty.PriorPermalinks ] + without [ nameof Post.Empty.Revisions; nameof Post.Empty.PriorPermalinks ] resultOption; withRetryOptionDefault } - |> verifyWebLog webLogId (fun p -> p.WebLogId)) conn with + |> verifyWebLog webLogId (_.WebLogId)) conn with | Some _ -> do! rethink { withTable Table.Post get postId - update [ nameof Post.empty.PriorPermalinks, permalinks :> obj ] + update [ nameof Post.Empty.PriorPermalinks, permalinks :> obj ] write; withRetryDefault; ignoreResult conn } return true @@ -743,7 +743,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.TagMap getAll [ tagMapId ] - filter (fun row -> row[nameof TagMap.empty.WebLogId].Eq webLogId :> obj) + filter (fun row -> row[nameof TagMap.Empty.WebLogId].Eq webLogId :> obj) delete write; withRetryDefault conn } @@ -756,7 +756,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger verifyWebLog webLogId (fun tm -> tm.WebLogId) <| conn + |> verifyWebLog webLogId (_.WebLogId) <| conn member _.FindByUrlValue urlValue webLogId = rethink { @@ -769,9 +769,9 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.TagMap - between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |] + between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |] [ Index Index.WebLogAndTag ] - orderBy (nameof TagMap.empty.Tag) + orderBy (nameof TagMap.Empty.Tag) result; withRetryDefault conn } @@ -803,16 +803,16 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Theme - filter (fun row -> row[nameof Theme.empty.Id].Ne "admin" :> obj) + filter (fun row -> row[nameof Theme.Empty.Id].Ne "admin" :> obj) merge withoutTemplateText - orderBy (nameof Theme.empty.Id) + orderBy (nameof Theme.Empty.Id) result; withRetryDefault conn } member _.Exists themeId = backgroundTask { let! count = rethink { withTable Table.Theme - filter (nameof Theme.empty.Id) themeId + filter (nameof Theme.Empty.Id) themeId count result; withRetryDefault conn } @@ -859,7 +859,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.ThemeAsset - without [ nameof ThemeAsset.empty.Data ] + without [ nameof ThemeAsset.Empty.Data ] result; withRetryDefault conn } @@ -874,7 +874,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.ThemeAsset filter (matchAssetByThemeId themeId) - without [ nameof ThemeAsset.empty.Data ] + without [ nameof ThemeAsset.Empty.Data ] result; withRetryDefault conn } @@ -931,9 +931,9 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Upload - between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |] + between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |] [ Index Index.WebLogAndPath ] - without [ nameof Upload.empty.Data ] + without [ nameof Upload.Empty.Data ] resultCursor; withRetryCursorDefault; toList conn } @@ -973,22 +973,22 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - pluck [ nameof Post.empty.Id ] + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + pluck [ nameof Post.Empty.Id ] result; withRetryOnce conn } if not (List.isEmpty thePostIds) then let postIds = thePostIds |> List.map (fun it -> it.Id :> obj) do! rethink { withTable Table.Comment - getAll postIds (nameof Comment.empty.PostId) + getAll postIds (nameof Comment.Empty.PostId) delete write; withRetryOnce; ignoreResult conn } // Tag mappings do not have a straightforward webLogId index do! rethink { withTable Table.TagMap - between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |] + between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |] [ Index Index.WebLogAndTag ] delete write; withRetryOnce; ignoreResult conn @@ -996,7 +996,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |] + between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |] [ Index Index.WebLogAndPath ] delete write; withRetryOnce; ignoreResult conn @@ -1004,7 +1004,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.WebLog - getAll [ url ] (nameof WebLog.empty.UrlBase) + getAll [ url ] (nameof WebLog.Empty.UrlBase) limit 1 result; withRetryDefault } @@ -1034,14 +1034,14 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger obj ] + update [ nameof WebLog.Empty.RedirectRules, webLog.RedirectRules :> obj ] write; withRetryDefault; ignoreResult conn } member _.UpdateRssOptions webLog = rethink { withTable Table.WebLog get webLog.Id - update [ nameof WebLog.empty.Rss, webLog.Rss :> obj ] + update [ nameof WebLog.Empty.Rss, webLog.Rss :> obj ] write; withRetryDefault; ignoreResult conn } @@ -1085,15 +1085,15 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger let! pageCount = rethink { withTable Table.Page - getAll [ webLogId ] (nameof Page.empty.WebLogId) - filter (nameof Page.empty.AuthorId) userId + getAll [ webLogId ] (nameof Page.Empty.WebLogId) + filter (nameof Page.Empty.AuthorId) userId count result; withRetryDefault conn } let! postCount = rethink { withTable Table.Post - getAll [ webLogId ] (nameof Post.empty.WebLogId) - filter (nameof Post.empty.AuthorId) userId + getAll [ webLogId ] (nameof Post.Empty.WebLogId) + filter (nameof Post.Empty.AuthorId) userId count result; withRetryDefault conn } @@ -1121,8 +1121,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.WebLogUser - getAll [ webLogId ] (nameof WebLogUser.empty.WebLogId) - orderByFunc (fun row -> row[nameof WebLogUser.empty.PreferredName].Downcase ()) + getAll [ webLogId ] (nameof WebLogUser.Empty.WebLogId) + orderByFunc (fun row -> row[nameof WebLogUser.Empty.PreferredName].Downcase()) result; withRetryDefault conn } @@ -1130,10 +1130,10 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.WebLogUser getAll (objList userIds) - filter (nameof WebLogUser.empty.WebLogId) webLogId + filter (nameof WebLogUser.Empty.WebLogId) webLogId result; withRetryDefault conn } - return users |> List.map (fun u -> { Name = string u.Id; Value = WebLogUser.displayName u }) + return users |> List.map (fun u -> { Name = string u.Id; Value = u.DisplayName }) } member _.Restore users = backgroundTask { @@ -1151,7 +1151,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger obj ] + update [ nameof WebLogUser.Empty.LastSeenOn, Noda.now () :> obj ] write; withRetryOnce; ignoreResult conn } | None -> () @@ -1196,19 +1196,19 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger { withTable Table.DbVersion limit 1 result; withRetryOnce conn } - do! migrate (List.tryHead version |> Option.map (fun x -> x.Id)) + do! migrate (List.tryHead version |> Option.map _.Id) } diff --git a/src/MyWebLog.Data/SQLite/Helpers.fs b/src/MyWebLog.Data/SQLite/Helpers.fs index b37c7bc..d7031fb 100644 --- a/src/MyWebLog.Data/SQLite/Helpers.fs +++ b/src/MyWebLog.Data/SQLite/Helpers.fs @@ -232,7 +232,7 @@ module Map = /// Create a page from the current row in the given data reader let toPage ser rdr : Page = - { Page.empty with + { Page.Empty with Id = getString "id" rdr |> PageId WebLogId = getString "web_log_id" rdr |> WebLogId AuthorId = getString "author_id" rdr |> WebLogUserId @@ -250,7 +250,7 @@ module Map = /// Create a post from the current row in the given data reader let toPost ser rdr : Post = - { Post.empty with + { Post.Empty with Id = getString "id" rdr |> PostId WebLogId = getString "web_log_id" rdr |> WebLogId AuthorId = getString "author_id" rdr |> WebLogUserId @@ -283,7 +283,7 @@ module Map = /// Create a theme from the current row in the given data reader (excludes templates) let toTheme rdr : Theme = - { Theme.empty with + { Theme.Empty with Id = getString "id" rdr |> ThemeId Name = getString "name" rdr Version = getString "version" rdr diff --git a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs index 20a6056..7c0f242 100644 --- a/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs +++ b/src/MyWebLog.Data/SQLite/SQLiteWebLogUserData.fs @@ -96,8 +96,7 @@ type SQLiteWebLogUserData(conn: SqliteConnection) = addWebLogId cmd webLogId cmd.Parameters.AddRange nameParams use! rdr = cmd.ExecuteReaderAsync () - return - toList Map.toWebLogUser rdr |> List.map (fun u -> { Name = string u.Id; Value = WebLogUser.displayName u }) + return toList Map.toWebLogUser rdr |> List.map (fun u -> { Name = string u.Id; Value = u.DisplayName }) } /// Restore users from a backup diff --git a/src/MyWebLog.Domain/DataTypes.fs b/src/MyWebLog.Domain/DataTypes.fs index 01c6a39..413702a 100644 --- a/src/MyWebLog.Domain/DataTypes.fs +++ b/src/MyWebLog.Domain/DataTypes.fs @@ -8,29 +8,26 @@ open NodaTime [] type Category = { /// The ID of the category - Id : CategoryId + Id: CategoryId /// The ID of the web log to which the category belongs - WebLogId : WebLogId + WebLogId: WebLogId /// The displayed name - Name : string + Name: string /// The slug (used in category URLs) - Slug : string + Slug: string /// A longer description of the category - Description : string option + Description: string option /// The parent ID of this category (if a subcategory) - ParentId : CategoryId option -} - -/// Functions to support categories -module Category = + ParentId: CategoryId option +} with /// An empty category - let empty = { + static member Empty = { Id = CategoryId.Empty WebLogId = WebLogId.Empty Name = "" @@ -44,38 +41,35 @@ module Category = [] type Comment = { /// The ID of the comment - Id : CommentId + Id: CommentId /// The ID of the post to which this comment applies - PostId : PostId + PostId: PostId /// The ID of the comment to which this comment is a reply - InReplyToId : CommentId option + InReplyToId: CommentId option /// The name of the commentor - Name : string + Name: string /// The e-mail address of the commentor - Email : string + Email: string /// The URL of the commentor's personal website - Url : string option + Url: string option /// The status of the comment - Status : CommentStatus + Status: CommentStatus /// When the comment was posted - PostedOn : Instant + PostedOn: Instant /// The text of the comment - Text : string -} - -/// Functions to support comments -module Comment = + Text: string +} with /// An empty comment - let empty = { + static member Empty = { Id = CommentId.Empty PostId = PostId.Empty InReplyToId = None @@ -92,50 +86,47 @@ module Comment = [] type Page = { /// The ID of this page - Id : PageId + Id: PageId /// The ID of the web log to which this page belongs - WebLogId : WebLogId + WebLogId: WebLogId /// The ID of the author of this page - AuthorId : WebLogUserId + AuthorId: WebLogUserId /// The title of the page - Title : string + Title: string /// The link at which this page is displayed - Permalink : Permalink + Permalink: Permalink /// When this page was published - PublishedOn : Instant + PublishedOn: Instant /// When this page was last updated - UpdatedOn : Instant + UpdatedOn: Instant /// Whether this page shows as part of the web log's navigation - IsInPageList : bool + IsInPageList: bool /// The template to use when rendering this page - Template : string option + Template: string option /// The current text of the page - Text : string + Text: string /// Metadata for this page - Metadata : MetaItem list + Metadata: MetaItem list /// Permalinks at which this page may have been previously served (useful for migrated content) - PriorPermalinks : Permalink list + PriorPermalinks: Permalink list /// Revisions of this page - Revisions : Revision list -} - -/// Functions to support pages -module Page = + Revisions: Revision list +} with /// An empty page - let empty = { + static member Empty = { Id = PageId.Empty WebLogId = WebLogId.Empty AuthorId = WebLogUserId.Empty @@ -156,59 +147,56 @@ module Page = [] type Post = { /// The ID of this post - Id : PostId + Id: PostId /// The ID of the web log to which this post belongs - WebLogId : WebLogId + WebLogId: WebLogId /// The ID of the author of this post - AuthorId : WebLogUserId + AuthorId: WebLogUserId /// The status - Status : PostStatus + Status: PostStatus /// The title - Title : string + Title: string /// The link at which the post resides - Permalink : Permalink + Permalink: Permalink /// The instant on which the post was originally published - PublishedOn : Instant option + PublishedOn: Instant option /// The instant on which the post was last updated - UpdatedOn : Instant + UpdatedOn: Instant /// The template to use in displaying the post - Template : string option + Template: string option /// The text of the post in HTML (ready to display) format - Text : string + Text: string /// The Ids of the categories to which this is assigned - CategoryIds : CategoryId list + CategoryIds: CategoryId list /// The tags for the post - Tags : string list + Tags: string list /// Podcast episode information for this post - Episode : Episode option + Episode: Episode option /// Metadata for the post - Metadata : MetaItem list + Metadata: MetaItem list /// Permalinks at which this post may have been previously served (useful for migrated content) - PriorPermalinks : Permalink list + PriorPermalinks: Permalink list /// The revisions for this post - Revisions : Revision list -} - -/// Functions to support posts -module Post = + Revisions: Revision list +} with /// An empty post - let empty = { + static member Empty = { Id = PostId.Empty WebLogId = WebLogId.Empty AuthorId = WebLogUserId.Empty @@ -229,25 +217,23 @@ module Post = /// A mapping between a tag and its URL value, used to translate restricted characters (ex. "#1" -> "number-1") +[] type TagMap = { /// The ID of this tag mapping - Id : TagMapId + Id: TagMapId /// The ID of the web log to which this tag mapping belongs - WebLogId : WebLogId + WebLogId: WebLogId /// The tag which should be mapped to a different value in links - Tag : string + Tag: string /// The value by which the tag should be linked - UrlValue : string -} - -/// Functions to support tag mappings -module TagMap = + UrlValue: string +} with /// An empty tag mapping - let empty = { + static member Empty = { Id = TagMapId.Empty WebLogId = WebLogId.Empty Tag = "" @@ -256,26 +242,24 @@ module TagMap = /// A theme +[] type Theme = { /// The ID / path of the theme - Id : ThemeId + Id: ThemeId /// A long name of the theme - Name : string + Name: string /// The version of the theme - Version : string + Version: string /// The templates for this theme Templates: ThemeTemplate list -} - -/// Functions to support themes -module Theme = +} with /// An empty theme - let empty = { - Id = ThemeId "" + static member Empty = { + Id = ThemeId.Empty Name = "" Version = "" Templates = [] @@ -283,51 +267,47 @@ module Theme = /// A theme asset (a file served as part of a theme, at /themes/[theme]/[asset-path]) +[] type ThemeAsset = { /// The ID of the asset (consists of theme and path) - Id : ThemeAssetId + Id: ThemeAssetId /// The updated date (set from the file date from the ZIP archive) - UpdatedOn : Instant + UpdatedOn: Instant /// The data for the asset - Data : byte[] -} - -/// Functions to support theme assets -module ThemeAsset = + Data: byte array +} with /// An empty theme asset - let empty = { - Id = ThemeAssetId (ThemeId "", "") + static member Empty = { + Id = ThemeAssetId.Empty UpdatedOn = Noda.epoch Data = [||] } /// An uploaded file +[] type Upload = { /// The ID of the upload - Id : UploadId + Id: UploadId /// The ID of the web log to which this upload belongs - WebLogId : WebLogId + WebLogId: WebLogId /// The link at which this upload is served - Path : Permalink + Path: Permalink /// The updated date/time for this upload - UpdatedOn : Instant + UpdatedOn: Instant /// The data for the upload - Data : byte[] -} - -/// Functions to support uploaded files -module Upload = + Data: byte array +} with /// An empty upload - let empty = { + static member Empty = { Id = UploadId.Empty WebLogId = WebLogId.Empty Path = Permalink.Empty @@ -336,54 +316,53 @@ module Upload = } +open Newtonsoft.Json + /// A web log [] type WebLog = { /// The ID of the web log - Id : WebLogId + Id: WebLogId /// The name of the web log - Name : string + Name: string /// The slug of the web log - Slug : string + Slug: string /// A subtitle for the web log - Subtitle : string option + Subtitle: string option /// The default page ("posts" or a page Id) - DefaultPage : string + DefaultPage: string /// The number of posts to display on pages of posts - PostsPerPage : int + PostsPerPage: int /// The ID of the theme (also the path within /themes) - ThemeId : ThemeId + ThemeId: ThemeId /// The URL base - UrlBase : string + UrlBase: string /// The time zone in which dates/times should be displayed - TimeZone : string + TimeZone: string /// The RSS options for this web log - Rss : RssOptions + Rss: RssOptions /// Whether to automatically load htmx - AutoHtmx : bool + AutoHtmx: bool /// Where uploads are placed - Uploads : UploadDestination + Uploads: UploadDestination /// Redirect rules for this weblog - RedirectRules : RedirectRule list -} - -/// Functions to support web logs -module WebLog = + RedirectRules: RedirectRule list +} with /// An empty web log - let empty = { + static member Empty = { Id = WebLogId.Empty Name = "" Slug = "" @@ -399,24 +378,23 @@ module WebLog = RedirectRules = [] } - /// Get the host (including scheme) and extra path from the URL base - let hostAndPath webLog = - let scheme = webLog.UrlBase.Split "://" - let host = scheme[1].Split "/" - $"{scheme[0]}://{host[0]}", if host.Length > 1 then $"""/{String.Join("/", host |> Array.skip 1)}""" else "" + /// Any extra path where this web log is hosted (blank if web log is hosted at the root of the domain) + [] + member this.ExtraPath = + let path = this.UrlBase.Split("://").[1].Split "/" + if path.Length > 1 then $"""/{String.Join("/", path |> Array.skip 1)}""" else "" /// Generate an absolute URL for the given link - let absoluteUrl webLog (permalink: Permalink) = - $"{webLog.UrlBase}/{permalink}" - + member this.AbsoluteUrl(permalink: Permalink) = + $"{this.UrlBase}/{permalink}" + /// Generate a relative URL for the given link - let relativeUrl webLog (permalink: Permalink) = - let _, leadPath = hostAndPath webLog - $"{leadPath}/{permalink}" + member this.RelativeUrl(permalink: Permalink) = + $"{this.ExtraPath}/{permalink}" /// Convert an Instant (UTC reference) to the web log's local date/time - let localTime webLog (date: Instant) = - match DateTimeZoneProviders.Tzdb[webLog.TimeZone] with + member this.LocalTime(date: Instant) = + match DateTimeZoneProviders.Tzdb[this.TimeZone] with | null -> date.ToDateTimeUtc() | tz -> date.InZone(tz).ToDateTimeUnspecified() @@ -425,44 +403,41 @@ module WebLog = [] type WebLogUser = { /// The ID of the user - Id : WebLogUserId + Id: WebLogUserId /// The ID of the web log to which this user belongs - WebLogId : WebLogId + WebLogId: WebLogId /// The user name (e-mail address) - Email : string + Email: string /// The user's first name - FirstName : string + FirstName: string /// The user's last name - LastName : string + LastName: string /// The user's preferred name - PreferredName : string + PreferredName: string /// The hash of the user's password - PasswordHash : string + PasswordHash: string /// The URL of the user's personal site - Url : string option + Url: string option /// The user's access level - AccessLevel : AccessLevel + AccessLevel: AccessLevel /// When the user was created - CreatedOn : Instant + CreatedOn: Instant /// When the user last logged on - LastSeenOn : Instant option -} - -/// Functions to support web log users -module WebLogUser = + LastSeenOn: Instant option +} with /// An empty web log user - let empty = { + static member Empty = { Id = WebLogUserId.Empty WebLogId = WebLogId.Empty Email = "" @@ -477,12 +452,7 @@ module WebLogUser = } /// Get the user's displayed name - let displayName user = - let name = - seq { match user.PreferredName with "" -> user.FirstName | n -> n; " "; user.LastName } - |> Seq.reduce (+) - name.Trim() - - /// Does a user have the required access level? - let hasAccess level user = - user.AccessLevel.HasAccess level + [] + member this.DisplayName = + (seq { match this.PreferredName with "" -> this.FirstName | n -> n; " "; this.LastName } + |> Seq.reduce (+)).Trim() diff --git a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj index 048dc6c..9460006 100644 --- a/src/MyWebLog.Domain/MyWebLog.Domain.fsproj +++ b/src/MyWebLog.Domain/MyWebLog.Domain.fsproj @@ -9,6 +9,7 @@ + diff --git a/src/MyWebLog.Domain/SupportTypes.fs b/src/MyWebLog.Domain/SupportTypes.fs index ee3c01c..8a9c98b 100644 --- a/src/MyWebLog.Domain/SupportTypes.fs +++ b/src/MyWebLog.Domain/SupportTypes.fs @@ -72,13 +72,11 @@ type AccessLevel = /// Does a given access level allow an action that requires a certain access level? member this.HasAccess(needed: AccessLevel) = - // TODO: Move this to user where it seems to belong better... let weights = [ Author, 10 Editor, 20 WebLogAdmin, 30 - Administrator, 40 - ] + Administrator, 40 ] |> Map.ofList weights[needed] <= weights[this] @@ -639,6 +637,9 @@ type TagMapId = type ThemeId = | ThemeId of string + /// An empty theme ID + static member Empty = ThemeId "" + /// The string representation of a theme ID override this.ToString() = match this with ThemeId it -> it @@ -649,6 +650,9 @@ type ThemeId = type ThemeAssetId = | ThemeAssetId of ThemeId * string + /// An empty theme asset ID + static member Empty = ThemeAssetId(ThemeId.Empty, "") + /// Convert a string into a theme asset ID static member Parse(it : string) = let themeIdx = it.IndexOf "/" diff --git a/src/MyWebLog.Domain/ViewModels.fs b/src/MyWebLog.Domain/ViewModels.fs index 2005de8..d8ec0b4 100644 --- a/src/MyWebLog.Domain/ViewModels.fs +++ b/src/MyWebLog.Domain/ViewModels.fs @@ -103,46 +103,46 @@ module DisplayCustomFeed = /// Details about a page used to display page lists [] -type DisplayPage = - { /// The ID of this page - Id : string +type DisplayPage = { + /// The ID of this page + Id: string - /// The ID of the author of this page - AuthorId : string - - /// The title of the page - Title : string + /// The ID of the author of this page + AuthorId: string + + /// The title of the page + Title: string - /// The link at which this page is displayed - Permalink : string + /// The link at which this page is displayed + Permalink: string - /// When this page was published - PublishedOn : DateTime + /// When this page was published + PublishedOn: DateTime - /// When this page was last updated - UpdatedOn : DateTime + /// When this page was last updated + UpdatedOn: DateTime - /// Whether this page shows as part of the web log's navigation - IsInPageList : bool - - /// Is this the default page? - IsDefault : bool - - /// The text of the page - Text : string - - /// The metadata for the page - Metadata : MetaItem list - } + /// Whether this page shows as part of the web log's navigation + IsInPageList: bool + + /// Is this the default page? + IsDefault: bool + + /// The text of the page + Text: string + + /// The metadata for the page + Metadata: MetaItem list +} with /// Create a minimal display page (no text or metadata) from a database page - static member FromPageMinimal webLog (page: Page) = { + static member FromPageMinimal (webLog: WebLog) (page: Page) = { Id = string page.Id AuthorId = string page.AuthorId Title = page.Title Permalink = string page.Permalink - PublishedOn = WebLog.localTime webLog page.PublishedOn - UpdatedOn = WebLog.localTime webLog page.UpdatedOn + PublishedOn = webLog.LocalTime page.PublishedOn + UpdatedOn = webLog.LocalTime page.UpdatedOn IsInPageList = page.IsInPageList IsDefault = string page.Id = webLog.DefaultPage Text = "" @@ -150,18 +150,10 @@ type DisplayPage = } /// Create a display page from a database page - static member FromPage webLog (page : Page) = - let _, extra = WebLog.hostAndPath webLog - { Id = string page.Id - AuthorId = string page.AuthorId - Title = page.Title - Permalink = string page.Permalink - PublishedOn = WebLog.localTime webLog page.PublishedOn - UpdatedOn = WebLog.localTime webLog page.UpdatedOn - IsInPageList = page.IsInPageList - IsDefault = string page.Id = webLog.DefaultPage - Text = addBaseToRelativeUrls extra page.Text - Metadata = page.Metadata + static member FromPage webLog page = + { DisplayPage.FromPageMinimal webLog page with + Text = addBaseToRelativeUrls webLog.ExtraPath page.Text + Metadata = page.Metadata } @@ -169,22 +161,22 @@ type DisplayPage = [] type DisplayRevision = { /// The as-of date/time for the revision - AsOf : DateTime + AsOf: DateTime /// The as-of date/time for the revision in the web log's local time zone - AsOfLocal : DateTime + AsOfLocal: DateTime /// The format of the text of the revision - Format : string + Format: string } /// Functions to support displaying revisions module DisplayRevision = /// Create a display revision from an actual revision - let fromRevision webLog (rev : Revision) = + let fromRevision (webLog: WebLog) (rev : Revision) = { AsOf = rev.AsOf.ToDateTimeUtc () - AsOfLocal = WebLog.localTime webLog rev.AsOf + AsOfLocal = webLog.LocalTime rev.AsOf Format = rev.Text.SourceType } @@ -250,13 +242,13 @@ type DisplayUpload = { module DisplayUpload = /// Create a display uploaded file - let fromUpload webLog (source: UploadDestination) (upload: Upload) = + let fromUpload (webLog: WebLog) (source: UploadDestination) (upload: Upload) = let path = string upload.Path let name = Path.GetFileName path { Id = string upload.Id Name = name Path = path.Replace(name, "") - UpdatedOn = Some (WebLog.localTime webLog upload.UpdatedOn) + UpdatedOn = Some (webLog.LocalTime upload.UpdatedOn) Source = string source } @@ -296,17 +288,17 @@ type DisplayUser = { module DisplayUser = /// Construct a displayed user from a web log user - let fromUser webLog (user: WebLogUser) = - { Id = string user.Id - Email = user.Email - FirstName = user.FirstName - LastName = user.LastName - PreferredName = user.PreferredName - Url = defaultArg user.Url "" - AccessLevel = string user.AccessLevel - CreatedOn = WebLog.localTime webLog user.CreatedOn - LastSeenOn = user.LastSeenOn |> Option.map (WebLog.localTime webLog) |> Option.toNullable - } + let fromUser (webLog: WebLog) (user: WebLogUser) = { + Id = string user.Id + Email = user.Email + FirstName = user.FirstName + LastName = user.LastName + PreferredName = user.PreferredName + Url = defaultArg user.Url "" + AccessLevel = string user.AccessLevel + CreatedOn = webLog.LocalTime user.CreatedOn + LastSeenOn = user.LastSeenOn |> Option.map webLog.LocalTime |> Option.toNullable + } /// View model for editing categories @@ -708,7 +700,7 @@ type EditPostModel = { } with /// Create an edit model from an existing past - static member fromPost webLog (post: Post) = + static member fromPost (webLog: WebLog) (post: Post) = let latest = match post.Revisions |> List.sortByDescending _.AsOf |> List.tryHead with | Some rev -> rev @@ -728,7 +720,7 @@ type EditPostModel = { MetaNames = post.Metadata |> List.map _.Name |> Array.ofList MetaValues = post.Metadata |> List.map _.Value |> Array.ofList SetPublished = false - PubOverride = post.PublishedOn |> Option.map (WebLog.localTime webLog) |> Option.toNullable + PubOverride = post.PublishedOn |> Option.map webLog.LocalTime |> Option.toNullable SetUpdated = false IsEpisode = Option.isSome post.Episode Media = episode.Media @@ -1111,22 +1103,20 @@ type PostListItem = { } with /// Create a post list item from a post - static member fromPost (webLog: WebLog) (post: Post) = - let _, extra = WebLog.hostAndPath webLog - let inTZ = WebLog.localTime webLog - { Id = string post.Id - AuthorId = string post.AuthorId - Status = string post.Status - Title = post.Title - Permalink = string post.Permalink - PublishedOn = post.PublishedOn |> Option.map inTZ |> Option.toNullable - UpdatedOn = inTZ post.UpdatedOn - Text = addBaseToRelativeUrls extra post.Text - CategoryIds = post.CategoryIds |> List.map string - Tags = post.Tags - Episode = post.Episode - Metadata = post.Metadata - } + static member fromPost (webLog: WebLog) (post: Post) = { + Id = string post.Id + AuthorId = string post.AuthorId + Status = string post.Status + Title = post.Title + Permalink = string post.Permalink + PublishedOn = post.PublishedOn |> Option.map webLog.LocalTime |> Option.toNullable + UpdatedOn = webLog.LocalTime post.UpdatedOn + Text = addBaseToRelativeUrls webLog.ExtraPath post.Text + CategoryIds = post.CategoryIds |> List.map string + Tags = post.Tags + Episode = post.Episode + Metadata = post.Metadata + } /// View model for displaying posts diff --git a/src/MyWebLog/Caches.fs b/src/MyWebLog/Caches.fs index 74b09d9..9230cae 100644 --- a/src/MyWebLog/Caches.fs +++ b/src/MyWebLog/Caches.fs @@ -53,7 +53,7 @@ module Extensions = /// Does the current user have the requested level of access? member this.HasAccessLevel level = - defaultArg (this.UserAccessLevel |> Option.map (fun it -> it.HasAccess level)) false + defaultArg (this.UserAccessLevel |> Option.map _.HasAccess(level)) false open System.Collections.Concurrent @@ -93,13 +93,13 @@ module WebLogCache = _redirectCache[webLog.Id] <- webLog.RedirectRules |> List.map (fun it -> - let relUrl = Permalink >> WebLog.relativeUrl webLog + let relUrl = Permalink >> webLog.RelativeUrl let urlTo = if it.To.Contains "://" then it.To else relUrl it.To if it.IsRegex then - let pattern = if it.From.StartsWith "^" then $"^{relUrl (it.From.Substring 1)}" else it.From - RegEx (new Regex (pattern, RegexOptions.Compiled ||| RegexOptions.IgnoreCase), urlTo) + let pattern = if it.From.StartsWith "^" then $"^{relUrl it.From[1..]}" else it.From + RegEx(Regex(pattern, RegexOptions.Compiled ||| RegexOptions.IgnoreCase), urlTo) else - Text (relUrl it.From, urlTo)) + Text(relUrl it.From, urlTo)) /// Get all cached web logs let all () = diff --git a/src/MyWebLog/DotLiquidBespoke.fs b/src/MyWebLog/DotLiquidBespoke.fs index 2718d43..8cfdc9d 100644 --- a/src/MyWebLog/DotLiquidBespoke.fs +++ b/src/MyWebLog/DotLiquidBespoke.fs @@ -21,7 +21,7 @@ let assetExists fileName (webLog : WebLog) = ThemeAssetCache.get webLog.ThemeId |> List.exists (fun it -> it = fileName) /// Obtain the link from known types -let permalink (ctx : Context) (item : obj) (linkFunc : WebLog -> Permalink -> string) = +let permalink (item: obj) (linkFunc: Permalink -> string) = match item with | :? String as link -> Some link | :? DisplayPage as page -> Some page.Permalink @@ -29,64 +29,64 @@ let permalink (ctx : Context) (item : obj) (linkFunc : WebLog -> Permalink -> st | :? DropProxy as proxy -> Option.ofObj proxy["Permalink"] |> Option.map string | _ -> None |> function - | Some link -> linkFunc ctx.WebLog (Permalink link) + | Some link -> linkFunc (Permalink link) | None -> $"alert('unknown item type {item.GetType().Name}')" /// A filter to generate an absolute link -type AbsoluteLinkFilter () = - static member AbsoluteLink (ctx : Context, item : obj) = - permalink ctx item WebLog.absoluteUrl +type AbsoluteLinkFilter() = + static member AbsoluteLink(ctx: Context, item: obj) = + permalink item ctx.WebLog.AbsoluteUrl /// A filter to generate a link with posts categorized under the given category -type CategoryLinkFilter () = - static member CategoryLink (ctx : Context, catObj : obj) = +type CategoryLinkFilter() = + static member CategoryLink(ctx: Context, catObj: obj) = match catObj with | :? DisplayCategory as cat -> Some cat.Slug | :? DropProxy as proxy -> Option.ofObj proxy["Slug"] |> Option.map string | _ -> None |> function - | Some slug -> WebLog.relativeUrl ctx.WebLog (Permalink $"category/{slug}/") + | Some slug -> ctx.WebLog.RelativeUrl(Permalink $"category/{slug}/") | None -> $"alert('unknown category object type {catObj.GetType().Name}')" - + /// A filter to generate a link that will edit a page -type EditPageLinkFilter () = - static member EditPageLink (ctx : Context, pageObj : obj) = +type EditPageLinkFilter() = + static member EditPageLink(ctx: Context, pageObj: obj) = match pageObj with | :? DisplayPage as page -> Some page.Id | :? DropProxy as proxy -> Option.ofObj proxy["Id"] |> Option.map string | :? String as theId -> Some theId | _ -> None |> function - | Some pageId -> WebLog.relativeUrl ctx.WebLog (Permalink $"admin/page/{pageId}/edit") + | Some pageId -> ctx.WebLog.RelativeUrl(Permalink $"admin/page/{pageId}/edit") | None -> $"alert('unknown page object type {pageObj.GetType().Name}')" - - + + /// A filter to generate a link that will edit a post -type EditPostLinkFilter () = - static member EditPostLink (ctx : Context, postObj : obj) = +type EditPostLinkFilter() = + static member EditPostLink(ctx: Context, postObj: obj) = match postObj with | :? PostListItem as post -> Some post.Id | :? DropProxy as proxy -> Option.ofObj proxy["Id"] |> Option.map string | :? String as theId -> Some theId | _ -> None |> function - | Some postId -> WebLog.relativeUrl ctx.WebLog (Permalink $"admin/post/{postId}/edit") + | Some postId -> ctx.WebLog.RelativeUrl(Permalink $"admin/post/{postId}/edit") | None -> $"alert('unknown post object type {postObj.GetType().Name}')" /// A filter to generate nav links, highlighting the active link (exact match) -type NavLinkFilter () = - static member NavLink (ctx : Context, url : string, text : string) = - let _, path = WebLog.hostAndPath ctx.WebLog - let path = if path = "" then path else $"{path.Substring 1}/" +type NavLinkFilter() = + static member NavLink(ctx: Context, url: string, text: string) = + let extraPath = ctx.WebLog.ExtraPath + let path = if extraPath = "" then "" else $"{extraPath[1..]}/" seq { "
  • " text "
  • " @@ -97,7 +97,7 @@ type NavLinkFilter () = /// A filter to generate a link for theme asset (image, stylesheet, script, etc.) type ThemeAssetFilter() = static member ThemeAsset(ctx: Context, asset: string) = - WebLog.relativeUrl ctx.WebLog (Permalink $"themes/{ctx.WebLog.ThemeId}/{asset}") + ctx.WebLog.RelativeUrl(Permalink $"themes/{ctx.WebLog.ThemeId}/{asset}") /// Create various items in the page header based on the state of the page being generated @@ -122,12 +122,12 @@ type PageHeadTag() = // RSS feeds and canonical URLs let feedLink title url = let escTitle = HttpUtility.HtmlAttributeEncode title - let relUrl = WebLog.relativeUrl webLog (Permalink url) + let relUrl = webLog.RelativeUrl(Permalink url) $"""{s}""" if webLog.Rss.IsFeedEnabled && getBool "is_home" then result.WriteLine(feedLink webLog.Name webLog.Rss.FeedName) - result.WriteLine $"""{s}""" + result.WriteLine $"""{s}""" if webLog.Rss.IsCategoryEnabled && getBool "is_category_home" then let slug = context.Environments[0].["slug"] :?> string @@ -139,12 +139,12 @@ type PageHeadTag() = if getBool "is_post" then let post = context.Environments[0].["model"] :?> PostDisplay - let url = WebLog.absoluteUrl webLog (Permalink post.Posts[0].Permalink) + let url = webLog.AbsoluteUrl (Permalink post.Posts[0].Permalink) result.WriteLine $"""{s}""" if getBool "is_page" then let page = context.Environments[0].["page"] :?> DisplayPage - let url = WebLog.absoluteUrl webLog (Permalink page.Permalink) + let url = webLog.AbsoluteUrl (Permalink page.Permalink) result.WriteLine $"""{s}""" @@ -167,26 +167,26 @@ type PageFootTag () = /// A filter to generate a relative link type RelativeLinkFilter () = static member RelativeLink (ctx : Context, item : obj) = - permalink ctx item WebLog.relativeUrl + permalink item ctx.WebLog.RelativeUrl /// A filter to generate a link with posts tagged with the given tag -type TagLinkFilter () = - static member TagLink (ctx : Context, tag : string) = +type TagLinkFilter() = + static member TagLink(ctx: Context, tag: string) = ctx.Environments[0].["tag_mappings"] :?> TagMap list |> List.tryFind (fun it -> it.Tag = tag) |> function | Some tagMap -> tagMap.UrlValue - | None -> tag.Replace (" ", "+") - |> function tagUrl -> WebLog.relativeUrl ctx.WebLog (Permalink $"tag/{tagUrl}/") + | None -> tag.Replace(" ", "+") + |> function tagUrl -> ctx.WebLog.RelativeUrl(Permalink $"tag/{tagUrl}/") /// Create links for a user to log on or off, and a dashboard link if they are logged off -type UserLinksTag () = - inherit Tag () +type UserLinksTag() = + inherit Tag() - override this.Render (context : Context, result : TextWriter) = - let link it = WebLog.relativeUrl context.WebLog (Permalink it) + override this.Render(context: Context, result: TextWriter) = + let link it = context.WebLog.RelativeUrl(Permalink it) seq { """