First cut of user admin page (#19)
This commit is contained in:
parent
1e987fdf72
commit
41ae1d8dad
|
@ -105,47 +105,47 @@ module Map =
|
||||||
|
|
||||||
/// Create a category from the current row in the given data reader
|
/// Create a category from the current row in the given data reader
|
||||||
let toCategory rdr : Category =
|
let toCategory rdr : Category =
|
||||||
{ Id = toCategoryId rdr
|
{ Id = toCategoryId rdr
|
||||||
WebLogId = getString "web_log_id" rdr |> WebLogId
|
WebLogId = getString "web_log_id" rdr |> WebLogId
|
||||||
Name = getString "name" rdr
|
Name = getString "name" rdr
|
||||||
Slug = getString "slug" rdr
|
Slug = getString "slug" rdr
|
||||||
Description = tryString "description" rdr
|
Description = tryString "description" rdr
|
||||||
ParentId = tryString "parent_id" rdr |> Option.map CategoryId
|
ParentId = tryString "parent_id" rdr |> Option.map CategoryId
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a custom feed from the current row in the given data reader
|
/// Create a custom feed from the current row in the given data reader
|
||||||
let toCustomFeed rdr : CustomFeed =
|
let toCustomFeed rdr : CustomFeed =
|
||||||
{ Id = getString "id" rdr |> CustomFeedId
|
{ Id = getString "id" rdr |> CustomFeedId
|
||||||
Source = getString "source" rdr |> CustomFeedSource.parse
|
Source = getString "source" rdr |> CustomFeedSource.parse
|
||||||
Path = getString "path" rdr |> Permalink
|
Path = getString "path" rdr |> Permalink
|
||||||
Podcast =
|
Podcast =
|
||||||
if rdr.IsDBNull (rdr.GetOrdinal "title") then
|
if rdr.IsDBNull (rdr.GetOrdinal "title") then
|
||||||
None
|
None
|
||||||
else
|
else
|
||||||
Some {
|
Some {
|
||||||
Title = getString "title" rdr
|
Title = getString "title" rdr
|
||||||
Subtitle = tryString "subtitle" rdr
|
Subtitle = tryString "subtitle" rdr
|
||||||
ItemsInFeed = getInt "items_in_feed" rdr
|
ItemsInFeed = getInt "items_in_feed" rdr
|
||||||
Summary = getString "summary" rdr
|
Summary = getString "summary" rdr
|
||||||
DisplayedAuthor = getString "displayed_author" rdr
|
DisplayedAuthor = getString "displayed_author" rdr
|
||||||
Email = getString "email" rdr
|
Email = getString "email" rdr
|
||||||
ImageUrl = getString "image_url" rdr |> Permalink
|
ImageUrl = getString "image_url" rdr |> Permalink
|
||||||
AppleCategory = getString "apple_category" rdr
|
AppleCategory = getString "apple_category" rdr
|
||||||
AppleSubcategory = tryString "apple_subcategory" rdr
|
AppleSubcategory = tryString "apple_subcategory" rdr
|
||||||
Explicit = getString "explicit" rdr |> ExplicitRating.parse
|
Explicit = getString "explicit" rdr |> ExplicitRating.parse
|
||||||
DefaultMediaType = tryString "default_media_type" rdr
|
DefaultMediaType = tryString "default_media_type" rdr
|
||||||
MediaBaseUrl = tryString "media_base_url" rdr
|
MediaBaseUrl = tryString "media_base_url" rdr
|
||||||
PodcastGuid = tryGuid "podcast_guid" rdr
|
PodcastGuid = tryGuid "podcast_guid" rdr
|
||||||
FundingUrl = tryString "funding_url" rdr
|
FundingUrl = tryString "funding_url" rdr
|
||||||
FundingText = tryString "funding_text" rdr
|
FundingText = tryString "funding_text" rdr
|
||||||
Medium = tryString "medium" rdr |> Option.map PodcastMedium.parse
|
Medium = tryString "medium" rdr |> Option.map PodcastMedium.parse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a meta item from the current row in the given data reader
|
/// Create a meta item from the current row in the given data reader
|
||||||
let toMetaItem rdr : MetaItem =
|
let toMetaItem rdr : MetaItem =
|
||||||
{ Name = getString "name" rdr
|
{ Name = getString "name" rdr
|
||||||
Value = getString "value" rdr
|
Value = getString "value" rdr
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a permalink from the current row in the given data reader
|
/// Create a permalink from the current row in the given data reader
|
||||||
|
@ -206,16 +206,16 @@ module Map =
|
||||||
|
|
||||||
/// Create a revision from the current row in the given data reader
|
/// Create a revision from the current row in the given data reader
|
||||||
let toRevision rdr : Revision =
|
let toRevision rdr : Revision =
|
||||||
{ AsOf = getDateTime "as_of" rdr
|
{ AsOf = getDateTime "as_of" rdr
|
||||||
Text = getString "revision_text" rdr |> MarkupText.parse
|
Text = getString "revision_text" rdr |> MarkupText.parse
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a tag mapping from the current row in the given data reader
|
/// Create a tag mapping from the current row in the given data reader
|
||||||
let toTagMap rdr : TagMap =
|
let toTagMap rdr : TagMap =
|
||||||
{ Id = getString "id" rdr |> TagMapId
|
{ Id = getString "id" rdr |> TagMapId
|
||||||
WebLogId = getString "web_log_id" rdr |> WebLogId
|
WebLogId = getString "web_log_id" rdr |> WebLogId
|
||||||
Tag = getString "tag" rdr
|
Tag = getString "tag" rdr
|
||||||
UrlValue = getString "url_value" rdr
|
UrlValue = getString "url_value" rdr
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a theme from the current row in the given data reader (excludes templates)
|
/// Create a theme from the current row in the given data reader (excludes templates)
|
||||||
|
@ -236,15 +236,15 @@ module Map =
|
||||||
dataStream.ToArray ()
|
dataStream.ToArray ()
|
||||||
else
|
else
|
||||||
[||]
|
[||]
|
||||||
{ Id = ThemeAssetId (ThemeId (getString "theme_id" rdr), getString "path" rdr)
|
{ Id = ThemeAssetId (ThemeId (getString "theme_id" rdr), getString "path" rdr)
|
||||||
UpdatedOn = getDateTime "updated_on" rdr
|
UpdatedOn = getDateTime "updated_on" rdr
|
||||||
Data = assetData
|
Data = assetData
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a theme template from the current row in the given data reader
|
/// Create a theme template from the current row in the given data reader
|
||||||
let toThemeTemplate rdr : ThemeTemplate =
|
let toThemeTemplate rdr : ThemeTemplate =
|
||||||
{ Name = getString "name" rdr
|
{ Name = getString "name" rdr
|
||||||
Text = getString "template" rdr
|
Text = getString "template" rdr
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an uploaded file from the current row in the given data reader
|
/// Create an uploaded file from the current row in the given data reader
|
||||||
|
@ -257,51 +257,51 @@ module Map =
|
||||||
dataStream.ToArray ()
|
dataStream.ToArray ()
|
||||||
else
|
else
|
||||||
[||]
|
[||]
|
||||||
{ Id = getString "id" rdr |> UploadId
|
{ Id = getString "id" rdr |> UploadId
|
||||||
WebLogId = getString "web_log_id" rdr |> WebLogId
|
WebLogId = getString "web_log_id" rdr |> WebLogId
|
||||||
Path = getString "path" rdr |> Permalink
|
Path = getString "path" rdr |> Permalink
|
||||||
UpdatedOn = getDateTime "updated_on" rdr
|
UpdatedOn = getDateTime "updated_on" rdr
|
||||||
Data = data
|
Data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a web log from the current row in the given data reader
|
/// Create a web log from the current row in the given data reader
|
||||||
let toWebLog rdr : WebLog =
|
let toWebLog rdr : WebLog =
|
||||||
{ Id = getString "id" rdr |> WebLogId
|
{ Id = getString "id" rdr |> WebLogId
|
||||||
Name = getString "name" rdr
|
Name = getString "name" rdr
|
||||||
Slug = getString "slug" rdr
|
Slug = getString "slug" rdr
|
||||||
Subtitle = tryString "subtitle" rdr
|
Subtitle = tryString "subtitle" rdr
|
||||||
DefaultPage = getString "default_page" rdr
|
DefaultPage = getString "default_page" rdr
|
||||||
PostsPerPage = getInt "posts_per_page" rdr
|
PostsPerPage = getInt "posts_per_page" rdr
|
||||||
ThemeId = getString "theme_id" rdr |> ThemeId
|
ThemeId = getString "theme_id" rdr |> ThemeId
|
||||||
UrlBase = getString "url_base" rdr
|
UrlBase = getString "url_base" rdr
|
||||||
TimeZone = getString "time_zone" rdr
|
TimeZone = getString "time_zone" rdr
|
||||||
AutoHtmx = getBoolean "auto_htmx" rdr
|
AutoHtmx = getBoolean "auto_htmx" rdr
|
||||||
Uploads = getString "uploads" rdr |> UploadDestination.parse
|
Uploads = getString "uploads" rdr |> UploadDestination.parse
|
||||||
Rss = {
|
Rss = {
|
||||||
IsFeedEnabled = getBoolean "is_feed_enabled" rdr
|
IsFeedEnabled = getBoolean "is_feed_enabled" rdr
|
||||||
FeedName = getString "feed_name" rdr
|
FeedName = getString "feed_name" rdr
|
||||||
ItemsInFeed = tryInt "items_in_feed" rdr
|
ItemsInFeed = tryInt "items_in_feed" rdr
|
||||||
IsCategoryEnabled = getBoolean "is_category_enabled" rdr
|
IsCategoryEnabled = getBoolean "is_category_enabled" rdr
|
||||||
IsTagEnabled = getBoolean "is_tag_enabled" rdr
|
IsTagEnabled = getBoolean "is_tag_enabled" rdr
|
||||||
Copyright = tryString "copyright" rdr
|
Copyright = tryString "copyright" rdr
|
||||||
CustomFeeds = []
|
CustomFeeds = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a web log user from the current row in the given data reader
|
/// Create a web log user from the current row in the given data reader
|
||||||
let toWebLogUser rdr : WebLogUser =
|
let toWebLogUser rdr : WebLogUser =
|
||||||
{ Id = getString "id" rdr |> WebLogUserId
|
{ Id = getString "id" rdr |> WebLogUserId
|
||||||
WebLogId = getString "web_log_id" rdr |> WebLogId
|
WebLogId = getString "web_log_id" rdr |> WebLogId
|
||||||
Email = getString "email" rdr
|
Email = getString "email" rdr
|
||||||
FirstName = getString "first_name" rdr
|
FirstName = getString "first_name" rdr
|
||||||
LastName = getString "last_name" rdr
|
LastName = getString "last_name" rdr
|
||||||
PreferredName = getString "preferred_name" rdr
|
PreferredName = getString "preferred_name" rdr
|
||||||
PasswordHash = getString "password_hash" rdr
|
PasswordHash = getString "password_hash" rdr
|
||||||
Salt = getGuid "salt" rdr
|
Salt = getGuid "salt" rdr
|
||||||
Url = tryString "url" rdr
|
Url = tryString "url" rdr
|
||||||
AccessLevel = getString "access_level" rdr |> AccessLevel.parse
|
AccessLevel = getString "access_level" rdr |> AccessLevel.parse
|
||||||
CreatedOn = getDateTime "created_on" rdr
|
CreatedOn = getDateTime "created_on" rdr
|
||||||
LastSeenOn = tryDateTime "last_seen_on" rdr
|
LastSeenOn = tryDateTime "last_seen_on" rdr
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a possibly-missing parameter, substituting null for None
|
/// Add a possibly-missing parameter, substituting null for None
|
||||||
|
|
|
@ -10,12 +10,12 @@ type SQLiteCategoryData (conn : SqliteConnection) =
|
||||||
|
|
||||||
/// Add parameters for category INSERT or UPDATE statements
|
/// Add parameters for category INSERT or UPDATE statements
|
||||||
let addCategoryParameters (cmd : SqliteCommand) (cat : Category) =
|
let addCategoryParameters (cmd : SqliteCommand) (cat : Category) =
|
||||||
[ cmd.Parameters.AddWithValue ("@id", CategoryId.toString cat.Id)
|
[ cmd.Parameters.AddWithValue ("@id", CategoryId.toString cat.Id)
|
||||||
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString cat.WebLogId)
|
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString cat.WebLogId)
|
||||||
cmd.Parameters.AddWithValue ("@name", cat.Name)
|
cmd.Parameters.AddWithValue ("@name", cat.Name)
|
||||||
cmd.Parameters.AddWithValue ("@slug", cat.Slug)
|
cmd.Parameters.AddWithValue ("@slug", cat.Slug)
|
||||||
cmd.Parameters.AddWithValue ("@description", maybe cat.Description)
|
cmd.Parameters.AddWithValue ("@description", maybe cat.Description)
|
||||||
cmd.Parameters.AddWithValue ("@parentId", maybe (cat.ParentId |> Option.map CategoryId.toString))
|
cmd.Parameters.AddWithValue ("@parentId", maybe (cat.ParentId |> Option.map CategoryId.toString))
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Add a category
|
/// Add a category
|
||||||
|
|
|
@ -12,16 +12,16 @@ type SQLitePageData (conn : SqliteConnection) =
|
||||||
|
|
||||||
/// Add parameters for page INSERT or UPDATE statements
|
/// Add parameters for page INSERT or UPDATE statements
|
||||||
let addPageParameters (cmd : SqliteCommand) (page : Page) =
|
let addPageParameters (cmd : SqliteCommand) (page : Page) =
|
||||||
[ cmd.Parameters.AddWithValue ("@id", PageId.toString page.Id)
|
[ cmd.Parameters.AddWithValue ("@id", PageId.toString page.Id)
|
||||||
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString page.WebLogId)
|
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString page.WebLogId)
|
||||||
cmd.Parameters.AddWithValue ("@authorId", WebLogUserId.toString page.AuthorId)
|
cmd.Parameters.AddWithValue ("@authorId", WebLogUserId.toString page.AuthorId)
|
||||||
cmd.Parameters.AddWithValue ("@title", page.Title)
|
cmd.Parameters.AddWithValue ("@title", page.Title)
|
||||||
cmd.Parameters.AddWithValue ("@permalink", Permalink.toString page.Permalink)
|
cmd.Parameters.AddWithValue ("@permalink", Permalink.toString page.Permalink)
|
||||||
cmd.Parameters.AddWithValue ("@publishedOn", page.PublishedOn)
|
cmd.Parameters.AddWithValue ("@publishedOn", page.PublishedOn)
|
||||||
cmd.Parameters.AddWithValue ("@updatedOn", page.UpdatedOn)
|
cmd.Parameters.AddWithValue ("@updatedOn", page.UpdatedOn)
|
||||||
cmd.Parameters.AddWithValue ("@isInPageList", page.IsInPageList)
|
cmd.Parameters.AddWithValue ("@isInPageList", page.IsInPageList)
|
||||||
cmd.Parameters.AddWithValue ("@template", maybe page.Template)
|
cmd.Parameters.AddWithValue ("@template", maybe page.Template)
|
||||||
cmd.Parameters.AddWithValue ("@text", page.Text)
|
cmd.Parameters.AddWithValue ("@text", page.Text)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Append meta items to a page
|
/// Append meta items to a page
|
||||||
|
|
|
@ -13,37 +13,37 @@ type SQLitePostData (conn : SqliteConnection) =
|
||||||
|
|
||||||
/// Add parameters for post INSERT or UPDATE statements
|
/// Add parameters for post INSERT or UPDATE statements
|
||||||
let addPostParameters (cmd : SqliteCommand) (post : Post) =
|
let addPostParameters (cmd : SqliteCommand) (post : Post) =
|
||||||
[ cmd.Parameters.AddWithValue ("@id", PostId.toString post.Id)
|
[ cmd.Parameters.AddWithValue ("@id", PostId.toString post.Id)
|
||||||
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString post.WebLogId)
|
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString post.WebLogId)
|
||||||
cmd.Parameters.AddWithValue ("@authorId", WebLogUserId.toString post.AuthorId)
|
cmd.Parameters.AddWithValue ("@authorId", WebLogUserId.toString post.AuthorId)
|
||||||
cmd.Parameters.AddWithValue ("@status", PostStatus.toString post.Status)
|
cmd.Parameters.AddWithValue ("@status", PostStatus.toString post.Status)
|
||||||
cmd.Parameters.AddWithValue ("@title", post.Title)
|
cmd.Parameters.AddWithValue ("@title", post.Title)
|
||||||
cmd.Parameters.AddWithValue ("@permalink", Permalink.toString post.Permalink)
|
cmd.Parameters.AddWithValue ("@permalink", Permalink.toString post.Permalink)
|
||||||
cmd.Parameters.AddWithValue ("@publishedOn", maybe post.PublishedOn)
|
cmd.Parameters.AddWithValue ("@publishedOn", maybe post.PublishedOn)
|
||||||
cmd.Parameters.AddWithValue ("@updatedOn", post.UpdatedOn)
|
cmd.Parameters.AddWithValue ("@updatedOn", post.UpdatedOn)
|
||||||
cmd.Parameters.AddWithValue ("@template", maybe post.Template)
|
cmd.Parameters.AddWithValue ("@template", maybe post.Template)
|
||||||
cmd.Parameters.AddWithValue ("@text", post.Text)
|
cmd.Parameters.AddWithValue ("@text", post.Text)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Add parameters for episode INSERT or UPDATE statements
|
/// Add parameters for episode INSERT or UPDATE statements
|
||||||
let addEpisodeParameters (cmd : SqliteCommand) (ep : Episode) =
|
let addEpisodeParameters (cmd : SqliteCommand) (ep : Episode) =
|
||||||
[ cmd.Parameters.AddWithValue ("@media", ep.Media)
|
[ cmd.Parameters.AddWithValue ("@media", ep.Media)
|
||||||
cmd.Parameters.AddWithValue ("@length", ep.Length)
|
cmd.Parameters.AddWithValue ("@length", ep.Length)
|
||||||
cmd.Parameters.AddWithValue ("@duration", maybe ep.Duration)
|
cmd.Parameters.AddWithValue ("@duration", maybe ep.Duration)
|
||||||
cmd.Parameters.AddWithValue ("@mediaType", maybe ep.MediaType)
|
cmd.Parameters.AddWithValue ("@mediaType", maybe ep.MediaType)
|
||||||
cmd.Parameters.AddWithValue ("@imageUrl", maybe ep.ImageUrl)
|
cmd.Parameters.AddWithValue ("@imageUrl", maybe ep.ImageUrl)
|
||||||
cmd.Parameters.AddWithValue ("@subtitle", maybe ep.Subtitle)
|
cmd.Parameters.AddWithValue ("@subtitle", maybe ep.Subtitle)
|
||||||
cmd.Parameters.AddWithValue ("@explicit", maybe (ep.Explicit |> Option.map ExplicitRating.toString))
|
cmd.Parameters.AddWithValue ("@explicit", maybe (ep.Explicit |> Option.map ExplicitRating.toString))
|
||||||
cmd.Parameters.AddWithValue ("@chapterFile", maybe ep.ChapterFile)
|
cmd.Parameters.AddWithValue ("@chapterFile", maybe ep.ChapterFile)
|
||||||
cmd.Parameters.AddWithValue ("@chapterType", maybe ep.ChapterType)
|
cmd.Parameters.AddWithValue ("@chapterType", maybe ep.ChapterType)
|
||||||
cmd.Parameters.AddWithValue ("@transcriptUrl", maybe ep.TranscriptUrl)
|
cmd.Parameters.AddWithValue ("@transcriptUrl", maybe ep.TranscriptUrl)
|
||||||
cmd.Parameters.AddWithValue ("@transcriptType", maybe ep.TranscriptType)
|
cmd.Parameters.AddWithValue ("@transcriptType", maybe ep.TranscriptType)
|
||||||
cmd.Parameters.AddWithValue ("@transcriptLang", maybe ep.TranscriptLang)
|
cmd.Parameters.AddWithValue ("@transcriptLang", maybe ep.TranscriptLang)
|
||||||
cmd.Parameters.AddWithValue ("@transcriptCaptions", maybe ep.TranscriptCaptions)
|
cmd.Parameters.AddWithValue ("@transcriptCaptions", maybe ep.TranscriptCaptions)
|
||||||
cmd.Parameters.AddWithValue ("@seasonNumber", maybe ep.SeasonNumber)
|
cmd.Parameters.AddWithValue ("@seasonNumber", maybe ep.SeasonNumber)
|
||||||
cmd.Parameters.AddWithValue ("@seasonDescription", maybe ep.SeasonDescription)
|
cmd.Parameters.AddWithValue ("@seasonDescription", maybe ep.SeasonDescription)
|
||||||
cmd.Parameters.AddWithValue ("@episodeNumber", maybe (ep.EpisodeNumber |> Option.map string))
|
cmd.Parameters.AddWithValue ("@episodeNumber", maybe (ep.EpisodeNumber |> Option.map string))
|
||||||
cmd.Parameters.AddWithValue ("@episodeDescription", maybe ep.EpisodeDescription)
|
cmd.Parameters.AddWithValue ("@episodeDescription", maybe ep.EpisodeDescription)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Append category IDs, tags, and meta items to a post
|
/// Append category IDs, tags, and meta items to a post
|
||||||
|
|
|
@ -10,11 +10,11 @@ type SQLiteUploadData (conn : SqliteConnection) =
|
||||||
|
|
||||||
/// Add parameters for uploaded file INSERT and UPDATE statements
|
/// Add parameters for uploaded file INSERT and UPDATE statements
|
||||||
let addUploadParameters (cmd : SqliteCommand) (upload : Upload) =
|
let addUploadParameters (cmd : SqliteCommand) (upload : Upload) =
|
||||||
[ cmd.Parameters.AddWithValue ("@id", UploadId.toString upload.Id)
|
[ cmd.Parameters.AddWithValue ("@id", UploadId.toString upload.Id)
|
||||||
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString upload.WebLogId)
|
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString upload.WebLogId)
|
||||||
cmd.Parameters.AddWithValue ("@path", Permalink.toString upload.Path)
|
cmd.Parameters.AddWithValue ("@path", Permalink.toString upload.Path)
|
||||||
cmd.Parameters.AddWithValue ("@updatedOn", upload.UpdatedOn)
|
cmd.Parameters.AddWithValue ("@updatedOn", upload.UpdatedOn)
|
||||||
cmd.Parameters.AddWithValue ("@dataLength", upload.Data.Length)
|
cmd.Parameters.AddWithValue ("@dataLength", upload.Data.Length)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Save an uploaded file
|
/// Save an uploaded file
|
||||||
|
|
|
@ -15,57 +15,57 @@ type SQLiteWebLogData (conn : SqliteConnection) =
|
||||||
|
|
||||||
/// Add parameters for web log INSERT or web log/RSS options UPDATE statements
|
/// Add parameters for web log INSERT or web log/RSS options UPDATE statements
|
||||||
let addWebLogRssParameters (cmd : SqliteCommand) (webLog : WebLog) =
|
let addWebLogRssParameters (cmd : SqliteCommand) (webLog : WebLog) =
|
||||||
[ cmd.Parameters.AddWithValue ("@isFeedEnabled", webLog.Rss.IsFeedEnabled)
|
[ cmd.Parameters.AddWithValue ("@isFeedEnabled", webLog.Rss.IsFeedEnabled)
|
||||||
cmd.Parameters.AddWithValue ("@feedName", webLog.Rss.FeedName)
|
cmd.Parameters.AddWithValue ("@feedName", webLog.Rss.FeedName)
|
||||||
cmd.Parameters.AddWithValue ("@itemsInFeed", maybe webLog.Rss.ItemsInFeed)
|
cmd.Parameters.AddWithValue ("@itemsInFeed", maybe webLog.Rss.ItemsInFeed)
|
||||||
cmd.Parameters.AddWithValue ("@isCategoryEnabled", webLog.Rss.IsCategoryEnabled)
|
cmd.Parameters.AddWithValue ("@isCategoryEnabled", webLog.Rss.IsCategoryEnabled)
|
||||||
cmd.Parameters.AddWithValue ("@isTagEnabled", webLog.Rss.IsTagEnabled)
|
cmd.Parameters.AddWithValue ("@isTagEnabled", webLog.Rss.IsTagEnabled)
|
||||||
cmd.Parameters.AddWithValue ("@copyright", maybe webLog.Rss.Copyright)
|
cmd.Parameters.AddWithValue ("@copyright", maybe webLog.Rss.Copyright)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Add parameters for web log INSERT or UPDATE statements
|
/// Add parameters for web log INSERT or UPDATE statements
|
||||||
let addWebLogParameters (cmd : SqliteCommand) (webLog : WebLog) =
|
let addWebLogParameters (cmd : SqliteCommand) (webLog : WebLog) =
|
||||||
[ cmd.Parameters.AddWithValue ("@id", WebLogId.toString webLog.Id)
|
[ cmd.Parameters.AddWithValue ("@id", WebLogId.toString webLog.Id)
|
||||||
cmd.Parameters.AddWithValue ("@name", webLog.Name)
|
cmd.Parameters.AddWithValue ("@name", webLog.Name)
|
||||||
cmd.Parameters.AddWithValue ("@slug", webLog.Slug)
|
cmd.Parameters.AddWithValue ("@slug", webLog.Slug)
|
||||||
cmd.Parameters.AddWithValue ("@subtitle", maybe webLog.Subtitle)
|
cmd.Parameters.AddWithValue ("@subtitle", maybe webLog.Subtitle)
|
||||||
cmd.Parameters.AddWithValue ("@defaultPage", webLog.DefaultPage)
|
cmd.Parameters.AddWithValue ("@defaultPage", webLog.DefaultPage)
|
||||||
cmd.Parameters.AddWithValue ("@postsPerPage", webLog.PostsPerPage)
|
cmd.Parameters.AddWithValue ("@postsPerPage", webLog.PostsPerPage)
|
||||||
cmd.Parameters.AddWithValue ("@themeId", ThemeId.toString webLog.ThemeId)
|
cmd.Parameters.AddWithValue ("@themeId", ThemeId.toString webLog.ThemeId)
|
||||||
cmd.Parameters.AddWithValue ("@urlBase", webLog.UrlBase)
|
cmd.Parameters.AddWithValue ("@urlBase", webLog.UrlBase)
|
||||||
cmd.Parameters.AddWithValue ("@timeZone", webLog.TimeZone)
|
cmd.Parameters.AddWithValue ("@timeZone", webLog.TimeZone)
|
||||||
cmd.Parameters.AddWithValue ("@autoHtmx", webLog.AutoHtmx)
|
cmd.Parameters.AddWithValue ("@autoHtmx", webLog.AutoHtmx)
|
||||||
cmd.Parameters.AddWithValue ("@uploads", UploadDestination.toString webLog.Uploads)
|
cmd.Parameters.AddWithValue ("@uploads", UploadDestination.toString webLog.Uploads)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
addWebLogRssParameters cmd webLog
|
addWebLogRssParameters cmd webLog
|
||||||
|
|
||||||
/// Add parameters for custom feed INSERT or UPDATE statements
|
/// Add parameters for custom feed INSERT or UPDATE statements
|
||||||
let addCustomFeedParameters (cmd : SqliteCommand) webLogId (feed : CustomFeed) =
|
let addCustomFeedParameters (cmd : SqliteCommand) webLogId (feed : CustomFeed) =
|
||||||
[ cmd.Parameters.AddWithValue ("@id", CustomFeedId.toString feed.Id)
|
[ cmd.Parameters.AddWithValue ("@id", CustomFeedId.toString feed.Id)
|
||||||
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString webLogId)
|
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString webLogId)
|
||||||
cmd.Parameters.AddWithValue ("@source", CustomFeedSource.toString feed.Source)
|
cmd.Parameters.AddWithValue ("@source", CustomFeedSource.toString feed.Source)
|
||||||
cmd.Parameters.AddWithValue ("@path", Permalink.toString feed.Path)
|
cmd.Parameters.AddWithValue ("@path", Permalink.toString feed.Path)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Add parameters for podcast INSERT or UPDATE statements
|
/// Add parameters for podcast INSERT or UPDATE statements
|
||||||
let addPodcastParameters (cmd : SqliteCommand) feedId (podcast : PodcastOptions) =
|
let addPodcastParameters (cmd : SqliteCommand) feedId (podcast : PodcastOptions) =
|
||||||
[ cmd.Parameters.AddWithValue ("@feedId", CustomFeedId.toString feedId)
|
[ cmd.Parameters.AddWithValue ("@feedId", CustomFeedId.toString feedId)
|
||||||
cmd.Parameters.AddWithValue ("@title", podcast.Title)
|
cmd.Parameters.AddWithValue ("@title", podcast.Title)
|
||||||
cmd.Parameters.AddWithValue ("@subtitle", maybe podcast.Subtitle)
|
cmd.Parameters.AddWithValue ("@subtitle", maybe podcast.Subtitle)
|
||||||
cmd.Parameters.AddWithValue ("@itemsInFeed", podcast.ItemsInFeed)
|
cmd.Parameters.AddWithValue ("@itemsInFeed", podcast.ItemsInFeed)
|
||||||
cmd.Parameters.AddWithValue ("@summary", podcast.Summary)
|
cmd.Parameters.AddWithValue ("@summary", podcast.Summary)
|
||||||
cmd.Parameters.AddWithValue ("@displayedAuthor", podcast.DisplayedAuthor)
|
cmd.Parameters.AddWithValue ("@displayedAuthor", podcast.DisplayedAuthor)
|
||||||
cmd.Parameters.AddWithValue ("@email", podcast.Email)
|
cmd.Parameters.AddWithValue ("@email", podcast.Email)
|
||||||
cmd.Parameters.AddWithValue ("@imageUrl", Permalink.toString podcast.ImageUrl)
|
cmd.Parameters.AddWithValue ("@imageUrl", Permalink.toString podcast.ImageUrl)
|
||||||
cmd.Parameters.AddWithValue ("@appleCategory", podcast.AppleCategory)
|
cmd.Parameters.AddWithValue ("@appleCategory", podcast.AppleCategory)
|
||||||
cmd.Parameters.AddWithValue ("@appleSubcategory", maybe podcast.AppleSubcategory)
|
cmd.Parameters.AddWithValue ("@appleSubcategory", maybe podcast.AppleSubcategory)
|
||||||
cmd.Parameters.AddWithValue ("@explicit", ExplicitRating.toString podcast.Explicit)
|
cmd.Parameters.AddWithValue ("@explicit", ExplicitRating.toString podcast.Explicit)
|
||||||
cmd.Parameters.AddWithValue ("@defaultMediaType", maybe podcast.DefaultMediaType)
|
cmd.Parameters.AddWithValue ("@defaultMediaType", maybe podcast.DefaultMediaType)
|
||||||
cmd.Parameters.AddWithValue ("@mediaBaseUrl", maybe podcast.MediaBaseUrl)
|
cmd.Parameters.AddWithValue ("@mediaBaseUrl", maybe podcast.MediaBaseUrl)
|
||||||
cmd.Parameters.AddWithValue ("@podcastGuid", maybe podcast.PodcastGuid)
|
cmd.Parameters.AddWithValue ("@podcastGuid", maybe podcast.PodcastGuid)
|
||||||
cmd.Parameters.AddWithValue ("@fundingUrl", maybe podcast.FundingUrl)
|
cmd.Parameters.AddWithValue ("@fundingUrl", maybe podcast.FundingUrl)
|
||||||
cmd.Parameters.AddWithValue ("@fundingText", maybe podcast.FundingText)
|
cmd.Parameters.AddWithValue ("@fundingText", maybe podcast.FundingText)
|
||||||
cmd.Parameters.AddWithValue ("@medium", maybe (podcast.Medium |> Option.map PodcastMedium.toString))
|
cmd.Parameters.AddWithValue ("@medium", maybe (podcast.Medium |> Option.map PodcastMedium.toString))
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
/// Get the current custom feeds for a web log
|
/// Get the current custom feeds for a web log
|
||||||
|
|
|
@ -12,18 +12,18 @@ type SQLiteWebLogUserData (conn : SqliteConnection) =
|
||||||
|
|
||||||
/// Add parameters for web log user INSERT or UPDATE statements
|
/// Add parameters for web log user INSERT or UPDATE statements
|
||||||
let addWebLogUserParameters (cmd : SqliteCommand) (user : WebLogUser) =
|
let addWebLogUserParameters (cmd : SqliteCommand) (user : WebLogUser) =
|
||||||
[ cmd.Parameters.AddWithValue ("@id", WebLogUserId.toString user.Id)
|
[ cmd.Parameters.AddWithValue ("@id", WebLogUserId.toString user.Id)
|
||||||
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString user.WebLogId)
|
cmd.Parameters.AddWithValue ("@webLogId", WebLogId.toString user.WebLogId)
|
||||||
cmd.Parameters.AddWithValue ("@email", user.Email)
|
cmd.Parameters.AddWithValue ("@email", user.Email)
|
||||||
cmd.Parameters.AddWithValue ("@firstName", user.FirstName)
|
cmd.Parameters.AddWithValue ("@firstName", user.FirstName)
|
||||||
cmd.Parameters.AddWithValue ("@lastName", user.LastName)
|
cmd.Parameters.AddWithValue ("@lastName", user.LastName)
|
||||||
cmd.Parameters.AddWithValue ("@preferredName", user.PreferredName)
|
cmd.Parameters.AddWithValue ("@preferredName", user.PreferredName)
|
||||||
cmd.Parameters.AddWithValue ("@passwordHash", user.PasswordHash)
|
cmd.Parameters.AddWithValue ("@passwordHash", user.PasswordHash)
|
||||||
cmd.Parameters.AddWithValue ("@salt", user.Salt)
|
cmd.Parameters.AddWithValue ("@salt", user.Salt)
|
||||||
cmd.Parameters.AddWithValue ("@url", maybe user.Url)
|
cmd.Parameters.AddWithValue ("@url", maybe user.Url)
|
||||||
cmd.Parameters.AddWithValue ("@accessLevel", AccessLevel.toString user.AccessLevel)
|
cmd.Parameters.AddWithValue ("@accessLevel", AccessLevel.toString user.AccessLevel)
|
||||||
cmd.Parameters.AddWithValue ("@createdOn", user.CreatedOn)
|
cmd.Parameters.AddWithValue ("@createdOn", user.CreatedOn)
|
||||||
cmd.Parameters.AddWithValue ("@lastSeenOn", maybe user.LastSeenOn)
|
cmd.Parameters.AddWithValue ("@lastSeenOn", maybe user.LastSeenOn)
|
||||||
] |> ignore
|
] |> ignore
|
||||||
|
|
||||||
// IMPLEMENTATION FUNCTIONS
|
// IMPLEMENTATION FUNCTIONS
|
||||||
|
|
|
@ -30,12 +30,12 @@ module Category =
|
||||||
|
|
||||||
/// An empty category
|
/// An empty category
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = CategoryId.empty
|
{ Id = CategoryId.empty
|
||||||
WebLogId = WebLogId.empty
|
WebLogId = WebLogId.empty
|
||||||
Name = ""
|
Name = ""
|
||||||
Slug = ""
|
Slug = ""
|
||||||
Description = None
|
Description = None
|
||||||
ParentId = None
|
ParentId = None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,15 +75,15 @@ module Comment =
|
||||||
|
|
||||||
/// An empty comment
|
/// An empty comment
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = CommentId.empty
|
{ Id = CommentId.empty
|
||||||
PostId = PostId.empty
|
PostId = PostId.empty
|
||||||
InReplyToId = None
|
InReplyToId = None
|
||||||
Name = ""
|
Name = ""
|
||||||
Email = ""
|
Email = ""
|
||||||
Url = None
|
Url = None
|
||||||
Status = Pending
|
Status = Pending
|
||||||
PostedOn = DateTime.UtcNow
|
PostedOn = DateTime.UtcNow
|
||||||
Text = ""
|
Text = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,19 +135,19 @@ module Page =
|
||||||
|
|
||||||
/// An empty page
|
/// An empty page
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = PageId.empty
|
{ Id = PageId.empty
|
||||||
WebLogId = WebLogId.empty
|
WebLogId = WebLogId.empty
|
||||||
AuthorId = WebLogUserId.empty
|
AuthorId = WebLogUserId.empty
|
||||||
Title = ""
|
Title = ""
|
||||||
Permalink = Permalink.empty
|
Permalink = Permalink.empty
|
||||||
PublishedOn = DateTime.MinValue
|
PublishedOn = DateTime.MinValue
|
||||||
UpdatedOn = DateTime.MinValue
|
UpdatedOn = DateTime.MinValue
|
||||||
IsInPageList = false
|
IsInPageList = false
|
||||||
Template = None
|
Template = None
|
||||||
Text = ""
|
Text = ""
|
||||||
Metadata = []
|
Metadata = []
|
||||||
PriorPermalinks = []
|
PriorPermalinks = []
|
||||||
Revisions = []
|
Revisions = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,22 +208,22 @@ module Post =
|
||||||
|
|
||||||
/// An empty post
|
/// An empty post
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = PostId.empty
|
{ Id = PostId.empty
|
||||||
WebLogId = WebLogId.empty
|
WebLogId = WebLogId.empty
|
||||||
AuthorId = WebLogUserId.empty
|
AuthorId = WebLogUserId.empty
|
||||||
Status = Draft
|
Status = Draft
|
||||||
Title = ""
|
Title = ""
|
||||||
Permalink = Permalink.empty
|
Permalink = Permalink.empty
|
||||||
PublishedOn = None
|
PublishedOn = None
|
||||||
UpdatedOn = DateTime.MinValue
|
UpdatedOn = DateTime.MinValue
|
||||||
Text = ""
|
Text = ""
|
||||||
Template = None
|
Template = None
|
||||||
CategoryIds = []
|
CategoryIds = []
|
||||||
Tags = []
|
Tags = []
|
||||||
Episode = None
|
Episode = None
|
||||||
Metadata = []
|
Metadata = []
|
||||||
PriorPermalinks = []
|
PriorPermalinks = []
|
||||||
Revisions = []
|
Revisions = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,10 +247,10 @@ module TagMap =
|
||||||
|
|
||||||
/// An empty tag mapping
|
/// An empty tag mapping
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = TagMapId.empty
|
{ Id = TagMapId.empty
|
||||||
WebLogId = WebLogId.empty
|
WebLogId = WebLogId.empty
|
||||||
Tag = ""
|
Tag = ""
|
||||||
UrlValue = ""
|
UrlValue = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,10 +274,10 @@ module Theme =
|
||||||
|
|
||||||
/// An empty theme
|
/// An empty theme
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = ThemeId ""
|
{ Id = ThemeId ""
|
||||||
Name = ""
|
Name = ""
|
||||||
Version = ""
|
Version = ""
|
||||||
Templates = []
|
Templates = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,9 +299,9 @@ module ThemeAsset =
|
||||||
|
|
||||||
/// An empty theme asset
|
/// An empty theme asset
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = ThemeAssetId (ThemeId "", "")
|
{ Id = ThemeAssetId (ThemeId "", "")
|
||||||
UpdatedOn = DateTime.MinValue
|
UpdatedOn = DateTime.MinValue
|
||||||
Data = [||]
|
Data = [||]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,13 +327,13 @@ type Upload =
|
||||||
module Upload =
|
module Upload =
|
||||||
|
|
||||||
/// An empty upload
|
/// An empty upload
|
||||||
let empty = {
|
let empty =
|
||||||
Id = UploadId.empty
|
{ Id = UploadId.empty
|
||||||
WebLogId = WebLogId.empty
|
WebLogId = WebLogId.empty
|
||||||
Path = Permalink.empty
|
Path = Permalink.empty
|
||||||
UpdatedOn = DateTime.MinValue
|
UpdatedOn = DateTime.MinValue
|
||||||
Data = [||]
|
Data = [||]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A web log
|
/// A web log
|
||||||
|
@ -381,18 +381,18 @@ module WebLog =
|
||||||
|
|
||||||
/// An empty web log
|
/// An empty web log
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = WebLogId.empty
|
{ Id = WebLogId.empty
|
||||||
Name = ""
|
Name = ""
|
||||||
Slug = ""
|
Slug = ""
|
||||||
Subtitle = None
|
Subtitle = None
|
||||||
DefaultPage = ""
|
DefaultPage = ""
|
||||||
PostsPerPage = 10
|
PostsPerPage = 10
|
||||||
ThemeId = ThemeId "default"
|
ThemeId = ThemeId "default"
|
||||||
UrlBase = ""
|
UrlBase = ""
|
||||||
TimeZone = ""
|
TimeZone = ""
|
||||||
Rss = RssOptions.empty
|
Rss = RssOptions.empty
|
||||||
AutoHtmx = false
|
AutoHtmx = false
|
||||||
Uploads = Database
|
Uploads = Database
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the host (including scheme) and extra path from the URL base
|
/// Get the host (including scheme) and extra path from the URL base
|
||||||
|
@ -461,18 +461,18 @@ module WebLogUser =
|
||||||
|
|
||||||
/// An empty web log user
|
/// An empty web log user
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = WebLogUserId.empty
|
{ Id = WebLogUserId.empty
|
||||||
WebLogId = WebLogId.empty
|
WebLogId = WebLogId.empty
|
||||||
Email = ""
|
Email = ""
|
||||||
FirstName = ""
|
FirstName = ""
|
||||||
LastName = ""
|
LastName = ""
|
||||||
PreferredName = ""
|
PreferredName = ""
|
||||||
PasswordHash = ""
|
PasswordHash = ""
|
||||||
Salt = Guid.Empty
|
Salt = Guid.Empty
|
||||||
Url = None
|
Url = None
|
||||||
AccessLevel = Author
|
AccessLevel = Author
|
||||||
CreatedOn = DateTime.UnixEpoch
|
CreatedOn = DateTime.UnixEpoch
|
||||||
LastSeenOn = None
|
LastSeenOn = None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the user's displayed name
|
/// Get the user's displayed name
|
||||||
|
|
|
@ -28,10 +28,10 @@ module AccessLevel =
|
||||||
|
|
||||||
/// Weightings for access levels
|
/// Weightings for access levels
|
||||||
let private weights =
|
let private weights =
|
||||||
[ Author, 10
|
[ Author, 10
|
||||||
Editor, 20
|
Editor, 20
|
||||||
WebLogAdmin, 30
|
WebLogAdmin, 30
|
||||||
Administrator, 40
|
Administrator, 40
|
||||||
]
|
]
|
||||||
|> Map.ofList
|
|> Map.ofList
|
||||||
|
|
||||||
|
@ -195,25 +195,25 @@ type Episode =
|
||||||
module Episode =
|
module Episode =
|
||||||
|
|
||||||
/// An empty episode
|
/// An empty episode
|
||||||
let empty = {
|
let empty =
|
||||||
Media = ""
|
{ Media = ""
|
||||||
Length = 0L
|
Length = 0L
|
||||||
Duration = None
|
Duration = None
|
||||||
MediaType = None
|
MediaType = None
|
||||||
ImageUrl = None
|
ImageUrl = None
|
||||||
Subtitle = None
|
Subtitle = None
|
||||||
Explicit = None
|
Explicit = None
|
||||||
ChapterFile = None
|
ChapterFile = None
|
||||||
ChapterType = None
|
ChapterType = None
|
||||||
TranscriptUrl = None
|
TranscriptUrl = None
|
||||||
TranscriptType = None
|
TranscriptType = None
|
||||||
TranscriptLang = None
|
TranscriptLang = None
|
||||||
TranscriptCaptions = None
|
TranscriptCaptions = None
|
||||||
SeasonNumber = None
|
SeasonNumber = None
|
||||||
SeasonDescription = None
|
SeasonDescription = None
|
||||||
EpisodeNumber = None
|
EpisodeNumber = None
|
||||||
EpisodeDescription = None
|
EpisodeDescription = None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
open Markdig
|
open Markdig
|
||||||
|
@ -285,8 +285,8 @@ module Revision =
|
||||||
|
|
||||||
/// An empty revision
|
/// An empty revision
|
||||||
let empty =
|
let empty =
|
||||||
{ AsOf = DateTime.UtcNow
|
{ AsOf = DateTime.UtcNow
|
||||||
Text = Html ""
|
Text = Html ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -505,10 +505,10 @@ module CustomFeed =
|
||||||
|
|
||||||
/// An empty custom feed
|
/// An empty custom feed
|
||||||
let empty =
|
let empty =
|
||||||
{ Id = CustomFeedId ""
|
{ Id = CustomFeedId ""
|
||||||
Source = Category (CategoryId "")
|
Source = Category (CategoryId "")
|
||||||
Path = Permalink ""
|
Path = Permalink ""
|
||||||
Podcast = None
|
Podcast = None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -542,13 +542,13 @@ module RssOptions =
|
||||||
|
|
||||||
/// An empty set of RSS options
|
/// An empty set of RSS options
|
||||||
let empty =
|
let empty =
|
||||||
{ IsFeedEnabled = true
|
{ IsFeedEnabled = true
|
||||||
FeedName = "feed.xml"
|
FeedName = "feed.xml"
|
||||||
ItemsInFeed = None
|
ItemsInFeed = None
|
||||||
IsCategoryEnabled = true
|
IsCategoryEnabled = true
|
||||||
IsTagEnabled = true
|
IsTagEnabled = true
|
||||||
Copyright = None
|
Copyright = None
|
||||||
CustomFeeds = []
|
CustomFeeds = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -79,10 +79,10 @@ type DisplayCustomFeed =
|
||||||
match feed.Source with
|
match feed.Source with
|
||||||
| Category (CategoryId catId) -> $"Category: {(cats |> Array.find (fun cat -> cat.Id = catId)).Name}"
|
| Category (CategoryId catId) -> $"Category: {(cats |> Array.find (fun cat -> cat.Id = catId)).Name}"
|
||||||
| Tag tag -> $"Tag: {tag}"
|
| Tag tag -> $"Tag: {tag}"
|
||||||
{ Id = CustomFeedId.toString feed.Id
|
{ Id = CustomFeedId.toString feed.Id
|
||||||
Source = source
|
Source = source
|
||||||
Path = Permalink.toString feed.Path
|
Path = Permalink.toString feed.Path
|
||||||
IsPodcast = Option.isSome feed.Podcast
|
IsPodcast = Option.isSome feed.Podcast
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,32 +123,32 @@ type DisplayPage =
|
||||||
/// Create a minimal display page (no text or metadata) from a database page
|
/// Create a minimal display page (no text or metadata) from a database page
|
||||||
static member fromPageMinimal webLog (page : Page) =
|
static member fromPageMinimal webLog (page : Page) =
|
||||||
let pageId = PageId.toString page.Id
|
let pageId = PageId.toString page.Id
|
||||||
{ Id = pageId
|
{ Id = pageId
|
||||||
AuthorId = WebLogUserId.toString page.AuthorId
|
AuthorId = WebLogUserId.toString page.AuthorId
|
||||||
Title = page.Title
|
Title = page.Title
|
||||||
Permalink = Permalink.toString page.Permalink
|
Permalink = Permalink.toString page.Permalink
|
||||||
PublishedOn = page.PublishedOn
|
PublishedOn = page.PublishedOn
|
||||||
UpdatedOn = page.UpdatedOn
|
UpdatedOn = page.UpdatedOn
|
||||||
IsInPageList = page.IsInPageList
|
IsInPageList = page.IsInPageList
|
||||||
IsDefault = pageId = webLog.DefaultPage
|
IsDefault = pageId = webLog.DefaultPage
|
||||||
Text = ""
|
Text = ""
|
||||||
Metadata = []
|
Metadata = []
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a display page from a database page
|
/// Create a display page from a database page
|
||||||
static member fromPage webLog (page : Page) =
|
static member fromPage webLog (page : Page) =
|
||||||
let _, extra = WebLog.hostAndPath webLog
|
let _, extra = WebLog.hostAndPath webLog
|
||||||
let pageId = PageId.toString page.Id
|
let pageId = PageId.toString page.Id
|
||||||
{ Id = pageId
|
{ Id = pageId
|
||||||
AuthorId = WebLogUserId.toString page.AuthorId
|
AuthorId = WebLogUserId.toString page.AuthorId
|
||||||
Title = page.Title
|
Title = page.Title
|
||||||
Permalink = Permalink.toString page.Permalink
|
Permalink = Permalink.toString page.Permalink
|
||||||
PublishedOn = page.PublishedOn
|
PublishedOn = page.PublishedOn
|
||||||
UpdatedOn = page.UpdatedOn
|
UpdatedOn = page.UpdatedOn
|
||||||
IsInPageList = page.IsInPageList
|
IsInPageList = page.IsInPageList
|
||||||
IsDefault = pageId = webLog.DefaultPage
|
IsDefault = pageId = webLog.DefaultPage
|
||||||
Text = if extra = "" then page.Text else page.Text.Replace ("href=\"/", $"href=\"{extra}/")
|
Text = if extra = "" then page.Text else page.Text.Replace ("href=\"/", $"href=\"{extra}/")
|
||||||
Metadata = page.Metadata
|
Metadata = page.Metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,9 +168,9 @@ with
|
||||||
|
|
||||||
/// Create a display revision from an actual revision
|
/// Create a display revision from an actual revision
|
||||||
static member fromRevision webLog (rev : Revision) =
|
static member fromRevision webLog (rev : Revision) =
|
||||||
{ AsOf = rev.AsOf
|
{ AsOf = rev.AsOf
|
||||||
AsOfLocal = WebLog.localTime webLog rev.AsOf
|
AsOfLocal = WebLog.localTime webLog rev.AsOf
|
||||||
Format = MarkupText.sourceType rev.Text
|
Format = MarkupText.sourceType rev.Text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,11 +199,56 @@ type DisplayUpload =
|
||||||
static member fromUpload webLog source (upload : Upload) =
|
static member fromUpload webLog source (upload : Upload) =
|
||||||
let path = Permalink.toString upload.Path
|
let path = Permalink.toString upload.Path
|
||||||
let name = Path.GetFileName path
|
let name = Path.GetFileName path
|
||||||
{ Id = UploadId.toString upload.Id
|
{ Id = UploadId.toString upload.Id
|
||||||
Name = name
|
Name = name
|
||||||
Path = path.Replace (name, "")
|
Path = path.Replace (name, "")
|
||||||
UpdatedOn = Some (WebLog.localTime webLog upload.UpdatedOn)
|
UpdatedOn = Some (WebLog.localTime webLog upload.UpdatedOn)
|
||||||
Source = UploadDestination.toString source
|
Source = UploadDestination.toString source
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// View model to display a user's information
|
||||||
|
[<NoComparison; NoEquality>]
|
||||||
|
type DisplayUser =
|
||||||
|
{ /// The ID of the user
|
||||||
|
Id : string
|
||||||
|
|
||||||
|
/// The user name (e-mail address)
|
||||||
|
Email : string
|
||||||
|
|
||||||
|
/// The user's first name
|
||||||
|
FirstName : string
|
||||||
|
|
||||||
|
/// The user's last name
|
||||||
|
LastName : string
|
||||||
|
|
||||||
|
/// The user's preferred name
|
||||||
|
PreferredName : string
|
||||||
|
|
||||||
|
/// The URL of the user's personal site
|
||||||
|
Url : string
|
||||||
|
|
||||||
|
/// The user's access level
|
||||||
|
AccessLevel : string
|
||||||
|
|
||||||
|
/// When the user was created
|
||||||
|
CreatedOn : DateTime
|
||||||
|
|
||||||
|
/// When the user last logged on
|
||||||
|
LastSeenOn : Nullable<DateTime>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a displayed user from a web log user
|
||||||
|
static member fromUser webLog (user : WebLogUser) =
|
||||||
|
{ Id = WebLogUserId.toString user.Id
|
||||||
|
Email = user.Email
|
||||||
|
FirstName = user.FirstName
|
||||||
|
LastName = user.LastName
|
||||||
|
PreferredName = user.PreferredName
|
||||||
|
Url = defaultArg user.Url ""
|
||||||
|
AccessLevel = AccessLevel.toString user.AccessLevel
|
||||||
|
CreatedOn = WebLog.localTime webLog user.CreatedOn
|
||||||
|
LastSeenOn = user.LastSeenOn |> Option.map (WebLog.localTime webLog) |> Option.toNullable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -228,11 +273,11 @@ type EditCategoryModel =
|
||||||
|
|
||||||
/// Create an edit model from an existing category
|
/// Create an edit model from an existing category
|
||||||
static member fromCategory (cat : Category) =
|
static member fromCategory (cat : Category) =
|
||||||
{ CategoryId = CategoryId.toString cat.Id
|
{ CategoryId = CategoryId.toString cat.Id
|
||||||
Name = cat.Name
|
Name = cat.Name
|
||||||
Slug = cat.Slug
|
Slug = cat.Slug
|
||||||
Description = defaultArg cat.Description ""
|
Description = defaultArg cat.Description ""
|
||||||
ParentId = cat.ParentId |> Option.map CategoryId.toString |> Option.defaultValue ""
|
ParentId = cat.ParentId |> Option.map CategoryId.toString |> Option.defaultValue ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -305,27 +350,27 @@ type EditCustomFeedModel =
|
||||||
|
|
||||||
/// An empty custom feed model
|
/// An empty custom feed model
|
||||||
static member empty =
|
static member empty =
|
||||||
{ Id = ""
|
{ Id = ""
|
||||||
SourceType = "category"
|
SourceType = "category"
|
||||||
SourceValue = ""
|
SourceValue = ""
|
||||||
Path = ""
|
Path = ""
|
||||||
IsPodcast = false
|
IsPodcast = false
|
||||||
Title = ""
|
Title = ""
|
||||||
Subtitle = ""
|
Subtitle = ""
|
||||||
ItemsInFeed = 25
|
ItemsInFeed = 25
|
||||||
Summary = ""
|
Summary = ""
|
||||||
DisplayedAuthor = ""
|
DisplayedAuthor = ""
|
||||||
Email = ""
|
Email = ""
|
||||||
ImageUrl = ""
|
ImageUrl = ""
|
||||||
AppleCategory = ""
|
AppleCategory = ""
|
||||||
AppleSubcategory = ""
|
AppleSubcategory = ""
|
||||||
Explicit = "no"
|
Explicit = "no"
|
||||||
DefaultMediaType = "audio/mpeg"
|
DefaultMediaType = "audio/mpeg"
|
||||||
MediaBaseUrl = ""
|
MediaBaseUrl = ""
|
||||||
FundingUrl = ""
|
FundingUrl = ""
|
||||||
FundingText = ""
|
FundingText = ""
|
||||||
PodcastGuid = ""
|
PodcastGuid = ""
|
||||||
Medium = ""
|
Medium = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a model from a custom feed
|
/// Create a model from a custom feed
|
||||||
|
@ -413,11 +458,11 @@ type EditMyInfoModel =
|
||||||
|
|
||||||
/// Create an edit model from a user
|
/// Create an edit model from a user
|
||||||
static member fromUser (user : WebLogUser) =
|
static member fromUser (user : WebLogUser) =
|
||||||
{ FirstName = user.FirstName
|
{ FirstName = user.FirstName
|
||||||
LastName = user.LastName
|
LastName = user.LastName
|
||||||
PreferredName = user.PreferredName
|
PreferredName = user.PreferredName
|
||||||
NewPassword = ""
|
NewPassword = ""
|
||||||
NewPasswordConfirm = ""
|
NewPasswordConfirm = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -459,15 +504,15 @@ type EditPageModel =
|
||||||
| Some rev -> rev
|
| Some rev -> rev
|
||||||
| None -> Revision.empty
|
| None -> Revision.empty
|
||||||
let page = if page.Metadata |> List.isEmpty then { page with Metadata = [ MetaItem.empty ] } else page
|
let page = if page.Metadata |> List.isEmpty then { page with Metadata = [ MetaItem.empty ] } else page
|
||||||
{ PageId = PageId.toString page.Id
|
{ PageId = PageId.toString page.Id
|
||||||
Title = page.Title
|
Title = page.Title
|
||||||
Permalink = Permalink.toString page.Permalink
|
Permalink = Permalink.toString page.Permalink
|
||||||
Template = defaultArg page.Template ""
|
Template = defaultArg page.Template ""
|
||||||
IsShownInPageList = page.IsInPageList
|
IsShownInPageList = page.IsInPageList
|
||||||
Source = MarkupText.sourceType latest.Text
|
Source = MarkupText.sourceType latest.Text
|
||||||
Text = MarkupText.text latest.Text
|
Text = MarkupText.text latest.Text
|
||||||
MetaNames = page.Metadata |> List.map (fun m -> m.Name) |> Array.ofList
|
MetaNames = page.Metadata |> List.map (fun m -> m.Name) |> Array.ofList
|
||||||
MetaValues = page.Metadata |> List.map (fun m -> m.Value) |> Array.ofList
|
MetaValues = page.Metadata |> List.map (fun m -> m.Value) |> Array.ofList
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this is a new page
|
/// Whether this is a new page
|
||||||
|
@ -612,39 +657,39 @@ type EditPostModel =
|
||||||
| None -> Revision.empty
|
| None -> Revision.empty
|
||||||
let post = if post.Metadata |> List.isEmpty then { post with Metadata = [ MetaItem.empty ] } else post
|
let post = if post.Metadata |> List.isEmpty then { post with Metadata = [ MetaItem.empty ] } else post
|
||||||
let episode = defaultArg post.Episode Episode.empty
|
let episode = defaultArg post.Episode Episode.empty
|
||||||
{ PostId = PostId.toString post.Id
|
{ PostId = PostId.toString post.Id
|
||||||
Title = post.Title
|
Title = post.Title
|
||||||
Permalink = Permalink.toString post.Permalink
|
Permalink = Permalink.toString post.Permalink
|
||||||
Source = MarkupText.sourceType latest.Text
|
Source = MarkupText.sourceType latest.Text
|
||||||
Text = MarkupText.text latest.Text
|
Text = MarkupText.text latest.Text
|
||||||
Tags = String.Join (", ", post.Tags)
|
Tags = String.Join (", ", post.Tags)
|
||||||
Template = defaultArg post.Template ""
|
Template = defaultArg post.Template ""
|
||||||
CategoryIds = post.CategoryIds |> List.map CategoryId.toString |> Array.ofList
|
CategoryIds = post.CategoryIds |> List.map CategoryId.toString |> Array.ofList
|
||||||
Status = PostStatus.toString post.Status
|
Status = PostStatus.toString post.Status
|
||||||
DoPublish = false
|
DoPublish = false
|
||||||
MetaNames = post.Metadata |> List.map (fun m -> m.Name) |> Array.ofList
|
MetaNames = post.Metadata |> List.map (fun m -> m.Name) |> Array.ofList
|
||||||
MetaValues = post.Metadata |> List.map (fun m -> m.Value) |> Array.ofList
|
MetaValues = post.Metadata |> List.map (fun m -> m.Value) |> Array.ofList
|
||||||
SetPublished = false
|
SetPublished = false
|
||||||
PubOverride = post.PublishedOn |> Option.map (WebLog.localTime webLog) |> Option.toNullable
|
PubOverride = post.PublishedOn |> Option.map (WebLog.localTime webLog) |> Option.toNullable
|
||||||
SetUpdated = false
|
SetUpdated = false
|
||||||
IsEpisode = Option.isSome post.Episode
|
IsEpisode = Option.isSome post.Episode
|
||||||
Media = episode.Media
|
Media = episode.Media
|
||||||
Length = episode.Length
|
Length = episode.Length
|
||||||
Duration = defaultArg (episode.Duration |> Option.map (fun it -> it.ToString """hh\:mm\:ss""")) ""
|
Duration = defaultArg (episode.Duration |> Option.map (fun it -> it.ToString """hh\:mm\:ss""")) ""
|
||||||
MediaType = defaultArg episode.MediaType ""
|
MediaType = defaultArg episode.MediaType ""
|
||||||
ImageUrl = defaultArg episode.ImageUrl ""
|
ImageUrl = defaultArg episode.ImageUrl ""
|
||||||
Subtitle = defaultArg episode.Subtitle ""
|
Subtitle = defaultArg episode.Subtitle ""
|
||||||
Explicit = defaultArg (episode.Explicit |> Option.map ExplicitRating.toString) ""
|
Explicit = defaultArg (episode.Explicit |> Option.map ExplicitRating.toString) ""
|
||||||
ChapterFile = defaultArg episode.ChapterFile ""
|
ChapterFile = defaultArg episode.ChapterFile ""
|
||||||
ChapterType = defaultArg episode.ChapterType ""
|
ChapterType = defaultArg episode.ChapterType ""
|
||||||
TranscriptUrl = defaultArg episode.TranscriptUrl ""
|
TranscriptUrl = defaultArg episode.TranscriptUrl ""
|
||||||
TranscriptType = defaultArg episode.TranscriptType ""
|
TranscriptType = defaultArg episode.TranscriptType ""
|
||||||
TranscriptLang = defaultArg episode.TranscriptLang ""
|
TranscriptLang = defaultArg episode.TranscriptLang ""
|
||||||
TranscriptCaptions = defaultArg episode.TranscriptCaptions false
|
TranscriptCaptions = defaultArg episode.TranscriptCaptions false
|
||||||
SeasonNumber = defaultArg episode.SeasonNumber 0
|
SeasonNumber = defaultArg episode.SeasonNumber 0
|
||||||
SeasonDescription = defaultArg episode.SeasonDescription ""
|
SeasonDescription = defaultArg episode.SeasonDescription ""
|
||||||
EpisodeNumber = defaultArg (episode.EpisodeNumber |> Option.map string) ""
|
EpisodeNumber = defaultArg (episode.EpisodeNumber |> Option.map string) ""
|
||||||
EpisodeDescription = defaultArg episode.EpisodeDescription ""
|
EpisodeDescription = defaultArg episode.EpisodeDescription ""
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this is a new post
|
/// Whether this is a new post
|
||||||
|
@ -736,12 +781,12 @@ type EditRssModel =
|
||||||
|
|
||||||
/// Create an edit model from a set of RSS options
|
/// Create an edit model from a set of RSS options
|
||||||
static member fromRssOptions (rss : RssOptions) =
|
static member fromRssOptions (rss : RssOptions) =
|
||||||
{ IsFeedEnabled = rss.IsFeedEnabled
|
{ IsFeedEnabled = rss.IsFeedEnabled
|
||||||
FeedName = rss.FeedName
|
FeedName = rss.FeedName
|
||||||
ItemsInFeed = defaultArg rss.ItemsInFeed 0
|
ItemsInFeed = defaultArg rss.ItemsInFeed 0
|
||||||
IsCategoryEnabled = rss.IsCategoryEnabled
|
IsCategoryEnabled = rss.IsCategoryEnabled
|
||||||
IsTagEnabled = rss.IsTagEnabled
|
IsTagEnabled = rss.IsTagEnabled
|
||||||
Copyright = defaultArg rss.Copyright ""
|
Copyright = defaultArg rss.Copyright ""
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update RSS options from values in this mode
|
/// Update RSS options from values in this mode
|
||||||
|
@ -774,9 +819,9 @@ type EditTagMapModel =
|
||||||
|
|
||||||
/// Create an edit model from the tag mapping
|
/// Create an edit model from the tag mapping
|
||||||
static member fromMapping (tagMap : TagMap) : EditTagMapModel =
|
static member fromMapping (tagMap : TagMap) : EditTagMapModel =
|
||||||
{ Id = TagMapId.toString tagMap.Id
|
{ Id = TagMapId.toString tagMap.Id
|
||||||
Tag = tagMap.Tag
|
Tag = tagMap.Tag
|
||||||
UrlValue = tagMap.UrlValue
|
UrlValue = tagMap.UrlValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -819,20 +864,20 @@ type ManagePermalinksModel =
|
||||||
|
|
||||||
/// Create a permalink model from a page
|
/// Create a permalink model from a page
|
||||||
static member fromPage (pg : Page) =
|
static member fromPage (pg : Page) =
|
||||||
{ Id = PageId.toString pg.Id
|
{ Id = PageId.toString pg.Id
|
||||||
Entity = "page"
|
Entity = "page"
|
||||||
CurrentTitle = pg.Title
|
CurrentTitle = pg.Title
|
||||||
CurrentPermalink = Permalink.toString pg.Permalink
|
CurrentPermalink = Permalink.toString pg.Permalink
|
||||||
Prior = pg.PriorPermalinks |> List.map Permalink.toString |> Array.ofList
|
Prior = pg.PriorPermalinks |> List.map Permalink.toString |> Array.ofList
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a permalink model from a post
|
/// Create a permalink model from a post
|
||||||
static member fromPost (post : Post) =
|
static member fromPost (post : Post) =
|
||||||
{ Id = PostId.toString post.Id
|
{ Id = PostId.toString post.Id
|
||||||
Entity = "post"
|
Entity = "post"
|
||||||
CurrentTitle = post.Title
|
CurrentTitle = post.Title
|
||||||
CurrentPermalink = Permalink.toString post.Permalink
|
CurrentPermalink = Permalink.toString post.Permalink
|
||||||
Prior = post.PriorPermalinks |> List.map Permalink.toString |> Array.ofList
|
Prior = post.PriorPermalinks |> List.map Permalink.toString |> Array.ofList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -854,18 +899,18 @@ type ManageRevisionsModel =
|
||||||
|
|
||||||
/// Create a revision model from a page
|
/// Create a revision model from a page
|
||||||
static member fromPage webLog (pg : Page) =
|
static member fromPage webLog (pg : Page) =
|
||||||
{ Id = PageId.toString pg.Id
|
{ Id = PageId.toString pg.Id
|
||||||
Entity = "page"
|
Entity = "page"
|
||||||
CurrentTitle = pg.Title
|
CurrentTitle = pg.Title
|
||||||
Revisions = pg.Revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
|
Revisions = pg.Revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a revision model from a post
|
/// Create a revision model from a post
|
||||||
static member fromPost webLog (post : Post) =
|
static member fromPost webLog (post : Post) =
|
||||||
{ Id = PostId.toString post.Id
|
{ Id = PostId.toString post.Id
|
||||||
Entity = "post"
|
Entity = "post"
|
||||||
CurrentTitle = post.Title
|
CurrentTitle = post.Title
|
||||||
Revisions = post.Revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
|
Revisions = post.Revisions |> List.map (DisplayRevision.fromRevision webLog) |> Array.ofList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -913,18 +958,18 @@ type PostListItem =
|
||||||
static member fromPost (webLog : WebLog) (post : Post) =
|
static member fromPost (webLog : WebLog) (post : Post) =
|
||||||
let _, extra = WebLog.hostAndPath webLog
|
let _, extra = WebLog.hostAndPath webLog
|
||||||
let inTZ = WebLog.localTime webLog
|
let inTZ = WebLog.localTime webLog
|
||||||
{ Id = PostId.toString post.Id
|
{ Id = PostId.toString post.Id
|
||||||
AuthorId = WebLogUserId.toString post.AuthorId
|
AuthorId = WebLogUserId.toString post.AuthorId
|
||||||
Status = PostStatus.toString post.Status
|
Status = PostStatus.toString post.Status
|
||||||
Title = post.Title
|
Title = post.Title
|
||||||
Permalink = Permalink.toString post.Permalink
|
Permalink = Permalink.toString post.Permalink
|
||||||
PublishedOn = post.PublishedOn |> Option.map inTZ |> Option.toNullable
|
PublishedOn = post.PublishedOn |> Option.map inTZ |> Option.toNullable
|
||||||
UpdatedOn = inTZ post.UpdatedOn
|
UpdatedOn = inTZ post.UpdatedOn
|
||||||
Text = if extra = "" then post.Text else post.Text.Replace ("href=\"/", $"href=\"{extra}/")
|
Text = if extra = "" then post.Text else post.Text.Replace ("href=\"/", $"href=\"{extra}/")
|
||||||
CategoryIds = post.CategoryIds |> List.map CategoryId.toString
|
CategoryIds = post.CategoryIds |> List.map CategoryId.toString
|
||||||
Tags = post.Tags
|
Tags = post.Tags
|
||||||
Episode = post.Episode
|
Episode = post.Episode
|
||||||
Metadata = post.Metadata
|
Metadata = post.Metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -986,15 +1031,15 @@ type SettingsModel =
|
||||||
|
|
||||||
/// Create a settings model from a web log
|
/// Create a settings model from a web log
|
||||||
static member fromWebLog (webLog : WebLog) =
|
static member fromWebLog (webLog : WebLog) =
|
||||||
{ Name = webLog.Name
|
{ Name = webLog.Name
|
||||||
Slug = webLog.Slug
|
Slug = webLog.Slug
|
||||||
Subtitle = defaultArg webLog.Subtitle ""
|
Subtitle = defaultArg webLog.Subtitle ""
|
||||||
DefaultPage = webLog.DefaultPage
|
DefaultPage = webLog.DefaultPage
|
||||||
PostsPerPage = webLog.PostsPerPage
|
PostsPerPage = webLog.PostsPerPage
|
||||||
TimeZone = webLog.TimeZone
|
TimeZone = webLog.TimeZone
|
||||||
ThemeId = ThemeId.toString webLog.ThemeId
|
ThemeId = ThemeId.toString webLog.ThemeId
|
||||||
AutoHtmx = webLog.AutoHtmx
|
AutoHtmx = webLog.AutoHtmx
|
||||||
Uploads = UploadDestination.toString webLog.Uploads
|
Uploads = UploadDestination.toString webLog.Uploads
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update a web log with settings from the form
|
/// Update a web log with settings from the form
|
||||||
|
|
|
@ -227,11 +227,12 @@ let register () =
|
||||||
typeof<CustomFeed>; typeof<Episode>; typeof<Episode option>; typeof<MetaItem>; typeof<Page>
|
typeof<CustomFeed>; typeof<Episode>; typeof<Episode option>; typeof<MetaItem>; typeof<Page>
|
||||||
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<DisplayRevision>; typeof<DisplayUpload>; typeof<EditCategoryModel>; typeof<EditCustomFeedModel>
|
typeof<DisplayRevision>; typeof<DisplayUpload>; typeof<DisplayUser>; typeof<EditCategoryModel>
|
||||||
typeof<EditMyInfoModel>; typeof<EditPageModel>; typeof<EditPostModel>; typeof<EditRssModel>
|
typeof<EditCustomFeedModel>; typeof<EditMyInfoModel>; typeof<EditPageModel>; typeof<EditPostModel>
|
||||||
typeof<EditTagMapModel>; typeof<LogOnModel>; typeof<ManagePermalinksModel>; typeof<ManageRevisionsModel>
|
typeof<EditRssModel>; typeof<EditTagMapModel>; typeof<LogOnModel>; typeof<ManagePermalinksModel>
|
||||||
typeof<PostDisplay>; typeof<PostListItem>; typeof<SettingsModel>; typeof<UserMessage>
|
typeof<ManageRevisionsModel>; 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>
|
||||||
|
|
|
@ -149,6 +149,7 @@ let router : HttpHandler = choose [
|
||||||
route "/new" >=> Upload.showNew
|
route "/new" >=> Upload.showNew
|
||||||
])
|
])
|
||||||
subRoute "/user" (choose [
|
subRoute "/user" (choose [
|
||||||
|
route "s" >=> User.all
|
||||||
route "/my-info" >=> User.myInfo
|
route "/my-info" >=> User.myInfo
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,6 +5,8 @@ open System
|
||||||
open System.Security.Cryptography
|
open System.Security.Cryptography
|
||||||
open System.Text
|
open System.Text
|
||||||
|
|
||||||
|
// ~~ LOG ON / LOG OFF ~~
|
||||||
|
|
||||||
/// Hash a password for a given user
|
/// Hash a password for a given user
|
||||||
let hashedPassword (plainText : string) (email : string) (salt : Guid) =
|
let hashedPassword (plainText : string) (email : string) (salt : Guid) =
|
||||||
let allSalt = Array.concat [ salt.ToByteArray (); Encoding.UTF8.GetBytes email ]
|
let allSalt = Array.concat [ salt.ToByteArray (); Encoding.UTF8.GetBytes email ]
|
||||||
|
@ -69,6 +71,24 @@ let logOff : HttpHandler = fun next ctx -> task {
|
||||||
return! redirectToGet "" next ctx
|
return! redirectToGet "" next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ~~ ADMINISTRATION ~~
|
||||||
|
|
||||||
|
// GET /admin/users
|
||||||
|
let all : HttpHandler = fun next ctx -> task {
|
||||||
|
let data = ctx.Data
|
||||||
|
let! tmpl = TemplateCache.get "admin" "user-list-body" data
|
||||||
|
let! users = data.WebLogUser.FindByWebLog ctx.WebLog.Id
|
||||||
|
let hash = Hash.FromAnonymousObject {|
|
||||||
|
page_title = "User Administration"
|
||||||
|
csrf = ctx.CsrfTokenSet
|
||||||
|
web_log = ctx.WebLog
|
||||||
|
users = users |> List.map (DisplayUser.fromUser ctx.WebLog) |> Array.ofList
|
||||||
|
|}
|
||||||
|
return!
|
||||||
|
addToHash "user_list" (tmpl.Render hash) hash
|
||||||
|
|> adminView "user-list" next ctx
|
||||||
|
}
|
||||||
|
|
||||||
/// Display the user "my info" page, with information possibly filled in
|
/// Display the user "my info" page, with information possibly filled in
|
||||||
let private showMyInfo (user : WebLogUser) (hash : Hash) : HttpHandler = fun next ctx ->
|
let private showMyInfo (user : WebLogUser) (hash : Hash) : HttpHandler = fun next ctx ->
|
||||||
addToHash "page_title" "Edit Your Information" hash
|
addToHash "page_title" "Edit Your Information" hash
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if is_web_log_admin %}
|
{% if is_web_log_admin %}
|
||||||
{{ "admin/categories" | nav_link: "Categories" }}
|
{{ "admin/categories" | nav_link: "Categories" }}
|
||||||
|
{{ "admin/users" | nav_link: "Users" }}
|
||||||
{{ "admin/settings" | nav_link: "Settings" }}
|
{{ "admin/settings" | nav_link: "Settings" }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
56
src/admin-theme/user-list-body.liquid
Normal file
56
src/admin-theme/user-list-body.liquid
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<form method="post" id="userList" class="container" hx-target="this" hx-swap="outerHTML show:window:top">
|
||||||
|
<input type="hidden" name="{{ csrf.form_field_name }}" value="{{ csrf.request_token }}">
|
||||||
|
<div class="row mwl-table-detail" id="user_new"></div>
|
||||||
|
{%- assign user_col = "col-12 col-md-4 col-xl-3" -%}
|
||||||
|
{%- assign email_col = "col-12 col-md-4 col-xl-4" -%}
|
||||||
|
{%- assign cre8_col = "d-none d-xl-block col-xl-2" -%}
|
||||||
|
{%- assign last_col = "col-12 col-md-4 col-xl-3" -%}
|
||||||
|
{%- assign badge = "ms-2 badge bg" -%}
|
||||||
|
{% for user in users -%}
|
||||||
|
<div class="row mwl-table-detail" id="user_{{ user.id }}">
|
||||||
|
<div class="{{ user_col }} no-wrap">
|
||||||
|
{{ user.preferred_name }}
|
||||||
|
{%- if user.access_level == "Administrator" %}
|
||||||
|
<span class="{{ badge }}-success">ADMINISTRATOR</span>
|
||||||
|
{%- elsif user.access_level == "WebLogAdmin" %}
|
||||||
|
<span class="{{ badge }}-primary">WEB LOG ADMIN</span>
|
||||||
|
{%- elsif user.access_level == "Editor" %}
|
||||||
|
<span class="{{ badge }}-secondary">EDITOR</span>
|
||||||
|
{%- elsif user.access_level == "Author" %}
|
||||||
|
<span class="{{ badge }}-dark">AUTHOR</span>
|
||||||
|
{%- endif %}<br>
|
||||||
|
<small>
|
||||||
|
{%- assign user_url_base = "admin/user/" | append: user.id -%}
|
||||||
|
<a href="{{ user_url_base | append: "/edit" | relative_link }}" hx-target="#user_{{ user.id }}"
|
||||||
|
hx-swap="innerHTML show:#user_{{ user.id }}:top">
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
<span class="text-muted"> • </span>
|
||||||
|
{%- assign user_del_link = user_url_base | append: "/delete" | relative_link -%}
|
||||||
|
<a href="{{ user_del_link }}" hx-post="{{ user_del_link }}" class="text-danger"
|
||||||
|
hx-confirm="Are you sure you want to delete the category “{{ cat.name }}”? This action cannot be undone. (This action will not succeed if the user has authored any posts or pages.)">
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="{{ email_col }}">
|
||||||
|
{{ user.first_name }} {{ user.last_name }}<br>
|
||||||
|
<small class="text-muted">
|
||||||
|
{{ user.email }}
|
||||||
|
{%- unless user.url == "" %}<br>{{ user.url }}{% endunless %}
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="{{ cre8_col }}">
|
||||||
|
{{ user.created_on | date: "MMMM d, yyyy" }}
|
||||||
|
</div>
|
||||||
|
<div class="{{ last_col }}">
|
||||||
|
{% if user.last_seen_on %}
|
||||||
|
{{ user.last_seen_on | date: "MMMM d, yyyy" }} at
|
||||||
|
{{ user.last_seen_on | date: "h:mmtt" | downcase }}
|
||||||
|
{% else %}
|
||||||
|
--
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{%- endfor %}
|
||||||
|
</form>
|
20
src/admin-theme/user-list.liquid
Normal file
20
src/admin-theme/user-list.liquid
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<h2 class="my-3">{{ page_title }}</h2>
|
||||||
|
<article>
|
||||||
|
<a href="{{ "admin/user/new/edit" | relative_link }}" class="btn btn-primary btn-sm mb-3"
|
||||||
|
hx-target="#user_new">
|
||||||
|
Add a New User
|
||||||
|
</a>
|
||||||
|
<div class="container">
|
||||||
|
{%- assign user_col = "col-12 col-md-4 col-xl-3" -%}
|
||||||
|
{%- assign email_col = "col-12 col-md-4 col-xl-4" -%}
|
||||||
|
{%- assign cre8_col = "d-none d-xl-block col-xl-2" -%}
|
||||||
|
{%- assign last_col = "col-12 col-md-4 col-xl-3" -%}
|
||||||
|
<div class="row mwl-table-heading">
|
||||||
|
<div class="{{ user_col }}">User<span class="d-md-none">; Details; Last Log On</span></div>
|
||||||
|
<div class="{{ email_col }} d-none d-md-inline-block">Details</div>
|
||||||
|
<div class="{{ cre8_col }}">Created</div>
|
||||||
|
<div class="{{ last_col }} d-none d-md-block">Last Log On</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ user_list }}
|
||||||
|
</article>
|
|
@ -334,13 +334,10 @@ htmx.on("htmx:afterOnLoad", function (evt) {
|
||||||
})
|
})
|
||||||
|
|
||||||
htmx.on("htmx:responseError", function (evt) {
|
htmx.on("htmx:responseError", function (evt) {
|
||||||
/** @type {XMLHttpRequest} */
|
|
||||||
const xhr = evt.detail.xhr
|
const xhr = evt.detail.xhr
|
||||||
const hdrs = xhr.getAllResponseHeaders()
|
const hdrs = xhr.getAllResponseHeaders()
|
||||||
// Show messages if there were any in the response
|
// Show an error message if there were none in the response
|
||||||
if (hdrs.indexOf("x-message") >= 0) {
|
if (hdrs.indexOf("x-message") < 0) {
|
||||||
Admin.showMessage(evt.detail.xhr.getResponseHeader("x-message"))
|
|
||||||
} else {
|
|
||||||
Admin.showMessage(`danger|||${xhr.status}: ${xhr.statusText}`)
|
Admin.showMessage(`danger|||${xhr.status}: ${xhr.statusText}`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue
Block a user