WIP on person table, podcast/ep assignment (#17)
This commit is contained in:
@@ -143,6 +143,36 @@ type Page = {
|
||||
OpenGraph = None }
|
||||
|
||||
|
||||
/// <summary>A person (associated with podcasting)</summary>
|
||||
[<CLIMutable; NoComparison; NoEquality>]
|
||||
type Person = {
|
||||
/// <summary>The ID of this person</summary>
|
||||
Id: PersonId
|
||||
|
||||
/// <summary>The ID of the web log to which this person belongs</summary>
|
||||
WebLogId: WebLogId
|
||||
|
||||
/// <summary>The person's name</summary>
|
||||
Name: string
|
||||
|
||||
/// <summary>A URL for more information about this person</summary>
|
||||
/// <remarks>Non-absolute URLs will be treated as a permalink</remarks>
|
||||
Url: string option
|
||||
|
||||
/// <summary>A URL with an image / avatar for this person</summary>
|
||||
/// <remarks>Non-absolute URLs will be treated as a permalink</remarks>
|
||||
ImageUrl: string option
|
||||
} with
|
||||
|
||||
/// <summary>An empty person entry</summary>
|
||||
static member Empty =
|
||||
{ Id = PersonId.Empty
|
||||
WebLogId = WebLogId.Empty
|
||||
Name = ""
|
||||
Url = None
|
||||
ImageUrl = None }
|
||||
|
||||
|
||||
/// <summary>A web log post</summary>
|
||||
[<CLIMutable; NoComparison; NoEquality>]
|
||||
type Post = {
|
||||
|
||||
@@ -402,6 +402,37 @@ type PersonRole =
|
||||
PersonRole.GroupXref |> List.find (fun it -> fst it = this) |> snd
|
||||
|
||||
|
||||
open System
|
||||
|
||||
/// <summary>An identifier for a person</summary>
|
||||
[<Struct>]
|
||||
type PersonId =
|
||||
| PersonId of string
|
||||
|
||||
/// <summary>An empty person ID</summary>
|
||||
static member Empty = PersonId ""
|
||||
|
||||
/// <summary>Create a new person ID</summary>
|
||||
/// <returns>A new person ID</returns>
|
||||
static member Create =
|
||||
Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Replace('/', '_').Replace('+', '-')[..21] |> PersonId
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with PersonId it -> it
|
||||
|
||||
|
||||
/// <summary>The combination of a person and a role</summary>
|
||||
[<CLIMutable>]
|
||||
type PersonAssignment = {
|
||||
/// <summary>The ID of the person to whom this assignment applies</summary>
|
||||
PersonId: PersonId
|
||||
|
||||
/// <summary>The role to which this person is assigned</summary>
|
||||
Role: PersonRole
|
||||
}
|
||||
|
||||
|
||||
open NodaTime.Text
|
||||
|
||||
/// <summary>A podcast episode</summary>
|
||||
@@ -462,6 +493,9 @@ type Episode = {
|
||||
|
||||
/// <summary>A description of the episode</summary>
|
||||
EpisodeDescription: string option
|
||||
|
||||
/// <summary>The people and roles for this episode</summary>
|
||||
People: PersonAssignment list option
|
||||
} with
|
||||
|
||||
/// <summary>An empty episode</summary>
|
||||
@@ -484,7 +518,8 @@ type Episode = {
|
||||
SeasonNumber = None
|
||||
SeasonDescription = None
|
||||
EpisodeNumber = None
|
||||
EpisodeDescription = None }
|
||||
EpisodeDescription = None
|
||||
People = None }
|
||||
|
||||
/// <summary>Format a duration for an episode</summary>
|
||||
/// <returns>A duration formatted in hours, minutes, and seconds</returns>
|
||||
@@ -529,3 +564,83 @@ type PodcastMedium =
|
||||
| Newsletter -> "newsletter"
|
||||
| Blog -> "blog"
|
||||
|
||||
|
||||
/// <summary>Options for a feed that describes a podcast</summary>
|
||||
[<CLIMutable; NoComparison; NoEquality>]
|
||||
type PodcastOptions = {
|
||||
/// <summary>The title of the podcast</summary>
|
||||
Title: string
|
||||
|
||||
/// <summary>A subtitle for the podcast</summary>
|
||||
Subtitle: string option
|
||||
|
||||
/// <summary>The number of items in the podcast feed</summary>
|
||||
ItemsInFeed: int
|
||||
|
||||
/// <summary>A summary of the podcast (iTunes field)</summary>
|
||||
Summary: string
|
||||
|
||||
/// <summary>The display name of the podcast author (iTunes field)</summary>
|
||||
DisplayedAuthor: string
|
||||
|
||||
/// <summary>The e-mail address of the user who registered the podcast at iTunes</summary>
|
||||
Email: string
|
||||
|
||||
/// <summary>The link to the image for the podcast</summary>
|
||||
/// <remarks>Non-absolute URLs will be treated as a permalink</remarks>
|
||||
ImageUrl: string
|
||||
|
||||
/// <summary>The category from Apple Podcasts (iTunes) under which this podcast is categorized</summary>
|
||||
AppleCategory: string
|
||||
|
||||
/// <summary>
|
||||
/// A further refinement of the categorization of this podcast (Apple Podcasts/iTunes field / values)
|
||||
/// </summary>
|
||||
AppleSubcategory: string option
|
||||
|
||||
/// <summary>The explictness rating (iTunes field)</summary>
|
||||
Explicit: ExplicitRating
|
||||
|
||||
/// <summary>The default media type for files in this podcast</summary>
|
||||
DefaultMediaType: string option
|
||||
|
||||
/// <summary>
|
||||
/// The base URL for relative URL media files for this podcast (optional; defaults to web log base)
|
||||
/// </summary>
|
||||
MediaBaseUrl: string option
|
||||
|
||||
/// <summary>A GUID for this podcast</summary>
|
||||
PodcastGuid: Guid option
|
||||
|
||||
/// <summary>A URL at which information on supporting the podcast may be found (supports permalinks)</summary>
|
||||
FundingUrl: string option
|
||||
|
||||
/// <summary>The text to be displayed in the funding item within the feed</summary>
|
||||
FundingText: string option
|
||||
|
||||
/// <summary>The medium (what the podcast IS, not what it is ABOUT)</summary>
|
||||
Medium: PodcastMedium option
|
||||
|
||||
/// <summary>The people and roles for the podcast overall</summary>
|
||||
People: PersonAssignment list option
|
||||
} with
|
||||
|
||||
/// <summary>A default set of podcast options</summary>
|
||||
static member Empty =
|
||||
{ Title = ""
|
||||
Subtitle = None
|
||||
ItemsInFeed = 0
|
||||
Summary = ""
|
||||
DisplayedAuthor = ""
|
||||
Email = ""
|
||||
ImageUrl = ""
|
||||
AppleCategory = ""
|
||||
AppleSubcategory = None
|
||||
Explicit = No
|
||||
DefaultMediaType = None
|
||||
MediaBaseUrl = None
|
||||
PodcastGuid = None
|
||||
FundingUrl = None
|
||||
FundingText = None
|
||||
Medium = None
|
||||
People = None }
|
||||
|
||||
@@ -552,19 +552,6 @@ type OpenGraphProperties = {
|
||||
}
|
||||
|
||||
|
||||
/// <summary>A permanent link</summary>
|
||||
[<Struct>]
|
||||
type Permalink =
|
||||
| Permalink of string
|
||||
|
||||
/// <summary>An empty permalink</summary>
|
||||
static member Empty = Permalink ""
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with Permalink it -> it
|
||||
|
||||
|
||||
/// <summary>An identifier for a page</summary>
|
||||
[<Struct>]
|
||||
type PageId =
|
||||
@@ -583,6 +570,19 @@ type PageId =
|
||||
match this with PageId it -> it
|
||||
|
||||
|
||||
/// <summary>A permanent link</summary>
|
||||
[<Struct>]
|
||||
type Permalink =
|
||||
| Permalink of string
|
||||
|
||||
/// <summary>An empty permalink</summary>
|
||||
static member Empty = Permalink ""
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with Permalink it -> it
|
||||
|
||||
|
||||
/// <summary>Statuses for posts</summary>
|
||||
[<Struct>]
|
||||
type PostStatus =
|
||||
@@ -683,82 +683,6 @@ type CustomFeedSource =
|
||||
match this with | Category (CategoryId catId) -> $"category:{catId}" | Tag tag -> $"tag:{tag}"
|
||||
|
||||
|
||||
/// <summary>Options for a feed that describes a podcast</summary>
|
||||
[<CLIMutable; NoComparison; NoEquality>]
|
||||
type PodcastOptions = {
|
||||
/// <summary>The title of the podcast</summary>
|
||||
Title: string
|
||||
|
||||
/// <summary>A subtitle for the podcast</summary>
|
||||
Subtitle: string option
|
||||
|
||||
/// <summary>The number of items in the podcast feed</summary>
|
||||
ItemsInFeed: int
|
||||
|
||||
/// <summary>A summary of the podcast (iTunes field)</summary>
|
||||
Summary: string
|
||||
|
||||
/// <summary>The display name of the podcast author (iTunes field)</summary>
|
||||
DisplayedAuthor: string
|
||||
|
||||
/// <summary>The e-mail address of the user who registered the podcast at iTunes</summary>
|
||||
Email: string
|
||||
|
||||
/// <summary>The link to the image for the podcast</summary>
|
||||
ImageUrl: Permalink
|
||||
|
||||
/// <summary>The category from Apple Podcasts (iTunes) under which this podcast is categorized</summary>
|
||||
AppleCategory: string
|
||||
|
||||
/// <summary>
|
||||
/// A further refinement of the categorization of this podcast (Apple Podcasts/iTunes field / values)
|
||||
/// </summary>
|
||||
AppleSubcategory: string option
|
||||
|
||||
/// <summary>The explictness rating (iTunes field)</summary>
|
||||
Explicit: ExplicitRating
|
||||
|
||||
/// <summary>The default media type for files in this podcast</summary>
|
||||
DefaultMediaType: string option
|
||||
|
||||
/// <summary>
|
||||
/// The base URL for relative URL media files for this podcast (optional; defaults to web log base)
|
||||
/// </summary>
|
||||
MediaBaseUrl: string option
|
||||
|
||||
/// <summary>A GUID for this podcast</summary>
|
||||
PodcastGuid: Guid option
|
||||
|
||||
/// <summary>A URL at which information on supporting the podcast may be found (supports permalinks)</summary>
|
||||
FundingUrl: string option
|
||||
|
||||
/// <summary>The text to be displayed in the funding item within the feed</summary>
|
||||
FundingText: string option
|
||||
|
||||
/// <summary>The medium (what the podcast IS, not what it is ABOUT)</summary>
|
||||
Medium: PodcastMedium option
|
||||
} with
|
||||
|
||||
/// <summary>A default set of podcast options</summary>
|
||||
static member Empty =
|
||||
{ Title = ""
|
||||
Subtitle = None
|
||||
ItemsInFeed = 0
|
||||
Summary = ""
|
||||
DisplayedAuthor = ""
|
||||
Email = ""
|
||||
ImageUrl = Permalink.Empty
|
||||
AppleCategory = ""
|
||||
AppleSubcategory = None
|
||||
Explicit = No
|
||||
DefaultMediaType = None
|
||||
MediaBaseUrl = None
|
||||
PodcastGuid = None
|
||||
FundingUrl = None
|
||||
FundingText = None
|
||||
Medium = None }
|
||||
|
||||
|
||||
/// <summary>A custom feed</summary>
|
||||
[<CLIMutable; NoComparison; NoEquality>]
|
||||
type CustomFeed = {
|
||||
|
||||
@@ -684,7 +684,7 @@ type EditCustomFeedModel = {
|
||||
Summary = this.Summary
|
||||
DisplayedAuthor = this.DisplayedAuthor
|
||||
Email = this.Email
|
||||
ImageUrl = Permalink this.ImageUrl
|
||||
ImageUrl = this.ImageUrl
|
||||
AppleCategory = this.AppleCategory
|
||||
AppleSubcategory = noneIfBlank this.AppleSubcategory
|
||||
Explicit = ExplicitRating.Parse this.Explicit
|
||||
@@ -693,7 +693,8 @@ type EditCustomFeedModel = {
|
||||
PodcastGuid = noneIfBlank this.PodcastGuid |> Option.map Guid.Parse
|
||||
FundingUrl = noneIfBlank this.FundingUrl
|
||||
FundingText = noneIfBlank this.FundingText
|
||||
Medium = noneIfBlank this.Medium |> Option.map PodcastMedium.Parse }
|
||||
Medium = noneIfBlank this.Medium |> Option.map PodcastMedium.Parse
|
||||
People = None } // TODO: add this to UI or handle differently
|
||||
else
|
||||
None }
|
||||
|
||||
@@ -974,6 +975,7 @@ type EditPostModel() =
|
||||
| Some it -> Some (double it)
|
||||
| None -> None
|
||||
EpisodeDescription = noneIfBlank this.EpisodeDescription
|
||||
People = None // TODO: add this to UI or handle differently
|
||||
}
|
||||
else
|
||||
None }
|
||||
|
||||
Reference in New Issue
Block a user