myWebLog/src/MyWebLog.Domain/DataTypes.fs

358 lines
9.2 KiB
Forth
Raw Normal View History

2022-04-16 16:21:16 +00:00
namespace MyWebLog
open System
open MyWebLog
2022-04-16 16:21:16 +00:00
/// A category under which a post may be identified
2022-04-16 16:21:16 +00:00
[<CLIMutable; NoComparison; NoEquality>]
type Category =
{ /// The ID of the category
id : CategoryId
/// The ID of the web log to which the category belongs
webLogId : WebLogId
/// The displayed name
name : string
/// The slug (used in category URLs)
slug : string
/// A longer description of the category
description : string option
/// The parent ID of this category (if a subcategory)
parentId : CategoryId option
}
/// Functions to support categories
module Category =
/// An empty category
let empty =
{ id = CategoryId.empty
webLogId = WebLogId.empty
name = ""
slug = ""
description = None
parentId = None
}
/// A comment on a post
[<CLIMutable; NoComparison; NoEquality>]
type Comment =
{ /// The ID of the comment
id : CommentId
/// The ID of the post to which this comment applies
postId : PostId
/// The ID of the comment to which this comment is a reply
inReplyToId : CommentId option
/// The name of the commentor
name : string
/// The e-mail address of the commentor
email : string
/// The URL of the commentor's personal website
url : string option
/// The status of the comment
status : CommentStatus
/// When the comment was posted
postedOn : DateTime
/// The text of the comment
text : string
}
/// Functions to support comments
module Comment =
/// An empty comment
let empty =
{ id = CommentId.empty
postId = PostId.empty
inReplyToId = None
name = ""
email = ""
url = None
status = Pending
postedOn = DateTime.UtcNow
text = ""
}
/// A page (text not associated with a date/time)
[<CLIMutable; NoComparison; NoEquality>]
type Page =
{ /// The ID of this page
id : PageId
/// The ID of the web log to which this page belongs
webLogId : WebLogId
/// The ID of the author of this page
authorId : WebLogUserId
/// The title of the page
title : string
/// The link at which this page is displayed
permalink : Permalink
/// When this page was published
publishedOn : DateTime
/// When this page was last updated
updatedOn : DateTime
/// Whether this page shows as part of the web log's navigation
showInPageList : bool
/// The template to use when rendering this page
template : string option
/// The current text of the page
text : string
/// Metadata for this page
metadata : MetaItem list
2022-04-16 16:21:16 +00:00
/// Permalinks at which this page may have been previously served (useful for migrated content)
priorPermalinks : Permalink list
2022-04-16 16:21:16 +00:00
/// Revisions of this page
revisions : Revision list
}
/// Functions to support pages
module Page =
/// An empty page
let empty =
{ id = PageId.empty
webLogId = WebLogId.empty
authorId = WebLogUserId.empty
title = ""
permalink = Permalink.empty
publishedOn = DateTime.MinValue
updatedOn = DateTime.MinValue
showInPageList = false
template = None
text = ""
metadata = []
2022-04-16 16:21:16 +00:00
priorPermalinks = []
revisions = []
}
/// A web log post
[<CLIMutable; NoComparison; NoEquality>]
type Post =
{ /// The ID of this post
id : PostId
/// The ID of the web log to which this post belongs
webLogId : WebLogId
/// The ID of the author of this post
authorId : WebLogUserId
/// The status
status : PostStatus
/// The title
title : string
/// The link at which the post resides
permalink : Permalink
/// The instant on which the post was originally published
publishedOn : DateTime option
/// The instant on which the post was last updated
updatedOn : DateTime
/// The text of the post in HTML (ready to display) format
text : string
/// The Ids of the categories to which this is assigned
categoryIds : CategoryId list
/// The tags for the post
tags : string list
/// Metadata for the post
metadata : MetaItem list
2022-04-16 16:21:16 +00:00
/// Permalinks at which this post may have been previously served (useful for migrated content)
priorPermalinks : Permalink list
/// The revisions for this post
revisions : Revision list
}
/// Functions to support posts
module Post =
/// An empty post
let empty =
{ id = PostId.empty
webLogId = WebLogId.empty
authorId = WebLogUserId.empty
status = Draft
title = ""
permalink = Permalink.empty
publishedOn = None
updatedOn = DateTime.MinValue
text = ""
categoryIds = []
tags = []
metadata = []
2022-04-16 16:21:16 +00:00
priorPermalinks = []
revisions = []
}
/// 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
/// The ID of the web log to which this tag mapping belongs
webLogId : WebLogId
/// The tag which should be mapped to a different value in links
tag : string
/// The value by which the tag should be linked
urlValue : string
}
/// Functions to support tag mappings
module TagMap =
/// An empty tag mapping
let empty =
{ id = TagMapId.empty
webLogId = WebLogId.empty
tag = ""
urlValue = ""
}
2022-04-16 16:21:16 +00:00
/// A web log
[<CLIMutable; NoComparison; NoEquality>]
type WebLog =
{ /// The ID of the web log
id : WebLogId
/// The name of the web log
name : string
/// A subtitle for the web log
subtitle : string option
/// The default page ("posts" or a page Id)
defaultPage : string
/// The number of posts to display on pages of posts
postsPerPage : int
/// The path of the theme (within /views/themes)
themePath : string
/// The URL base
urlBase : string
/// The time zone in which dates/times should be displayed
timeZone : string
}
/// Functions to support web logs
module WebLog =
/// An empty set of web logs
let empty =
{ id = WebLogId.empty
name = ""
subtitle = None
defaultPage = ""
postsPerPage = 10
2022-04-17 03:06:38 +00:00
themePath = "default"
2022-04-16 16:21:16 +00:00
urlBase = ""
timeZone = ""
}
/// Convert a permalink to an absolute URL
let absoluteUrl webLog = function Permalink link -> $"{webLog.urlBase}{link}"
/// Convert a date/time to the web log's local date/time
let localTime webLog (date : DateTime) =
let tz = TimeZoneInfo.FindSystemTimeZoneById webLog.timeZone
TimeZoneInfo.ConvertTimeFromUtc (DateTime (date.Ticks, DateTimeKind.Utc), tz)
2022-04-16 16:21:16 +00:00
/// A user of the web log
[<CLIMutable; NoComparison; NoEquality>]
type WebLogUser =
{ /// The ID of the user
id : WebLogUserId
/// The ID of the web log to which this user belongs
webLogId : WebLogId
/// The user name (e-mail address)
userName : string
/// The user's first name
firstName : string
/// The user's last name
lastName : string
/// The user's preferred name
preferredName : string
/// The hash of the user's password
passwordHash : string
/// Salt used to calculate the user's password hash
salt : Guid
/// The URL of the user's personal site
url : string option
/// The user's authorization level
authorizationLevel : AuthorizationLevel
}
/// Functions to support web log users
module WebLogUser =
/// An empty web log user
let empty =
{ id = WebLogUserId.empty
webLogId = WebLogId.empty
userName = ""
firstName = ""
lastName = ""
preferredName = ""
passwordHash = ""
salt = Guid.Empty
url = None
authorizationLevel = User
}
/// 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 ()