V2 #1

Merged
danieljsummers merged 102 commits from v2 into main 2022-06-23 00:35:12 +00:00
66 changed files with 320 additions and 47 deletions
Showing only changes of commit ff87a71c9c - Show all commits

View File

@ -376,7 +376,7 @@ module Post =
let findByPermalink (permalink : Permalink) (webLogId : WebLogId) = let findByPermalink (permalink : Permalink) (webLogId : WebLogId) =
rethink<Post list> { rethink<Post list> {
withTable Table.Post withTable Table.Post
getAll [ r.Array(permalink, webLogId) ] (nameof permalink) getAll [ r.Array(webLogId, permalink) ] (nameof permalink)
without [ "priorPermalinks"; "revisions" ] without [ "priorPermalinks"; "revisions" ]
limit 1 limit 1
result; withRetryDefault result; withRetryDefault
@ -468,18 +468,12 @@ module WebLog =
resultOption; withRetryOptionDefault resultOption; withRetryOptionDefault
} }
/// Update web log settings /// Update web log settings (updates all values)
let updateSettings (webLog : WebLog) = let updateSettings (webLog : WebLog) =
rethink { rethink {
withTable Table.WebLog withTable Table.WebLog
get webLog.id get webLog.id
update [ replace webLog
"name", webLog.name :> obj
"subtitle", webLog.subtitle
"defaultPage", webLog.defaultPage
"postsPerPage", webLog.postsPerPage
"timeZone", webLog.timeZone
]
write; withRetryDefault; ignoreResult write; withRetryDefault; ignoreResult
} }

View File

@ -218,6 +218,15 @@ type EditPostModel =
/// Values of metadata items /// Values of metadata items
metaValues : string[] metaValues : string[]
/// Whether to override the published date/time
setPublished : bool
/// The published date/time to override
pubOverride : Nullable<DateTime>
/// Whether all revisions should be purged and the override date set as the updated date as well
setUpdated : bool
} }
/// Create an edit model from an existing past /// Create an edit model from an existing past
static member fromPost (post : Post) = static member fromPost (post : Post) =
@ -226,17 +235,20 @@ type EditPostModel =
| Some rev -> rev | Some rev -> rev
| 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
{ 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)
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
pubOverride = Nullable<DateTime> ()
setUpdated = false
} }
@ -350,7 +362,19 @@ type SettingsModel =
/// The time zone in which dates/times should be displayed /// The time zone in which dates/times should be displayed
timeZone : string timeZone : string
/// The theme to use to display the web log
themePath : string
} }
/// Create a settings model from a web log
static member fromWebLog (webLog : WebLog) =
{ name = webLog.name
subtitle = defaultArg webLog.subtitle ""
defaultPage = webLog.defaultPage
postsPerPage = webLog.postsPerPage
timeZone = webLog.timeZone
themePath = webLog.themePath
}
[<CLIMutable; NoComparison; NoEquality>] [<CLIMutable; NoComparison; NoEquality>]

View File

@ -197,6 +197,16 @@ module private Helpers =
/// Handlers to manipulate admin functions /// Handlers to manipulate admin functions
module Admin = module Admin =
open System.IO
/// The currently available themes
let private themes () =
Directory.EnumerateDirectories "themes"
|> Seq.map (fun it -> it.Split Path.DirectorySeparatorChar |> Array.last)
|> Seq.filter (fun it -> it <> "admin")
|> Seq.map (fun it -> KeyValuePair.Create (it, it))
|> Array.ofSeq
// GET /admin // GET /admin
let dashboard : HttpHandler = requireUser >=> fun next ctx -> task { let dashboard : HttpHandler = requireUser >=> fun next ctx -> task {
let webLogId = webLogId ctx let webLogId = webLogId ctx
@ -230,20 +240,16 @@ module Admin =
return! return!
Hash.FromAnonymousObject Hash.FromAnonymousObject
{| csrf = csrfToken ctx {| csrf = csrfToken ctx
model = model = SettingsModel.fromWebLog webLog
{ name = webLog.name
subtitle = defaultArg webLog.subtitle ""
defaultPage = webLog.defaultPage
postsPerPage = webLog.postsPerPage
timeZone = webLog.timeZone
}
pages = pages =
seq { seq {
KeyValuePair.Create ("posts", "- First Page of Posts -") KeyValuePair.Create ("posts", "- First Page of Posts -")
yield! allPages yield! allPages
|> List.sortBy (fun p -> p.title.ToLower ())
|> List.map (fun p -> KeyValuePair.Create (PageId.toString p.id, p.title)) |> List.map (fun p -> KeyValuePair.Create (PageId.toString p.id, p.title))
} }
|> Array.ofSeq |> Array.ofSeq
themes = themes ()
web_log = webLog web_log = webLog
page_title = "Web Log Settings" page_title = "Web Log Settings"
|} |}
@ -263,6 +269,7 @@ module Admin =
defaultPage = model.defaultPage defaultPage = model.defaultPage
postsPerPage = model.postsPerPage postsPerPage = model.postsPerPage
timeZone = model.timeZone timeZone = model.timeZone
themePath = model.themePath
} }
do! Data.WebLog.updateSettings updated conn do! Data.WebLog.updateSettings updated conn
@ -510,8 +517,10 @@ module Post =
let permalink = (string >> Permalink) ctx.Request.RouteValues["link"] let permalink = (string >> Permalink) ctx.Request.RouteValues["link"]
// Current post // Current post
match! Data.Post.findByPermalink permalink webLog.id conn with match! Data.Post.findByPermalink permalink webLog.id conn with
| Some _ -> return! Error.notFound next ctx | Some post ->
// TODO: return via single-post action let! model = preparePostList webLog [ post ] 1 1 conn
model.Add ("page_title", post.title)
return! themedView "single-post" next ctx model
| None -> | None ->
// Current page // Current page
match! Data.Page.findByPermalink permalink webLog.id conn with match! Data.Page.findByPermalink permalink webLog.id conn with
@ -610,10 +619,29 @@ module Post =
|> List.ofSeq |> List.ofSeq
categoryIds = model.categoryIds |> Array.map CategoryId |> List.ofArray categoryIds = model.categoryIds |> Array.map CategoryId |> List.ofArray
status = if model.doPublish then Published else post.status status = if model.doPublish then Published else post.status
metadata = Seq.zip model.metaNames model.metaValues
|> Seq.filter (fun it -> fst it > "")
|> Seq.map (fun it -> { name = fst it; value = snd it })
|> Seq.sortBy (fun it -> $"{it.name.ToLower ()} {it.value.ToLower ()}")
|> List.ofSeq
revisions = match post.revisions |> List.tryHead with revisions = match post.revisions |> List.tryHead with
| Some r when r.text = revision.text -> post.revisions | Some r when r.text = revision.text -> post.revisions
| _ -> revision :: post.revisions | _ -> revision :: post.revisions
} }
let post =
match model.setPublished with
| true ->
let dt = DateTime (model.pubOverride.Value.ToUniversalTime().Ticks, DateTimeKind.Utc)
printf $"**** DateKind = {dt.Kind}"
match model.setUpdated with
| true ->
{ post with
publishedOn = Some dt
updatedOn = dt
revisions = [ { (List.head post.revisions) with asOf = dt } ]
}
| false -> { post with publishedOn = Some dt }
| false -> post
do! (match model.postId with "new" -> Data.Post.add | _ -> Data.Post.update) post conn do! (match model.postId with "new" -> Data.Post.add | _ -> Data.Post.update) post conn
do! addMessage ctx { UserMessage.success with message = "Post saved successfully" } do! addMessage ctx { UserMessage.success with message = "Post saved successfully" }
return! redirectToGet $"/post/{PostId.toString post.id}/edit" next ctx return! redirectToGet $"/post/{PostId.toString post.id}/edit" next ctx

View File

@ -3,5 +3,5 @@
"hostname": "data02.bitbadger.solutions", "hostname": "data02.bitbadger.solutions",
"database": "myWebLog-dev" "database": "myWebLog-dev"
}, },
"Generator": "myWebLog 2.0-alpha01" "Generator": "myWebLog 2.0-alpha02"
} }

View File

@ -8,14 +8,14 @@
<div class="col-6 col-lg-4 pb-3"> <div class="col-6 col-lg-4 pb-3">
<div class="form-floating"> <div class="form-floating">
<input type="text" name="name" id="name" class="form-control" placeholder="Name" autofocus required <input type="text" name="name" id="name" class="form-control" placeholder="Name" autofocus required
value="{{ model.name }}"> value="{{ model.name | escape }}">
<label for="name">Name</label> <label for="name">Name</label>
</div> </div>
</div> </div>
<div class="col-6 col-lg-4 pb-3"> <div class="col-6 col-lg-4 pb-3">
<div class="form-floating"> <div class="form-floating">
<input type="text" name="slug" id="slug" class="form-control" placeholder="Slug" required <input type="text" name="slug" id="slug" class="form-control" placeholder="Slug" required
value="{{ model.slug }}"> value="{{ model.slug | escape }}">
<label for="slug">Slug</label> <label for="slug">Slug</label>
</div> </div>
</div> </div>
@ -41,7 +41,7 @@
<div class="col"> <div class="col">
<div class="form-floating"> <div class="form-floating">
<input name="description" id="description" class="form-control" <input name="description" id="description" class="form-control"
placeholder="A short description of this category" value="{{ model.description }}"> placeholder="A short description of this category" value="{{ model.description | escape }}">
<label for="description">Description</label> <label for="description">Description</label>
</div> </div>
</div> </div>

View File

@ -62,6 +62,85 @@
<button type="submit" class="btn btn-primary">Save Changes</button> <button type="submit" class="btn btn-primary">Save Changes</button>
</div> </div>
</div> </div>
<div class="row mb-3">
<div class="col">
<fieldset>
<legend>
Metadata
<button type="button" class="btn btn-sm btn-secondary" data-bs-toggle="collapse"
data-bs-target="#metaItemContainer">
show
</button>
</legend>
<div id="metaItemContainer" class="collapse">
<div id="metaItems" class="container">
{%- for meta in model.metadata %}
<div id="meta_{{ meta[0] }}" class="row mb-3">
<div class="col-1 text-center align-self-center">
<button type="button" class="btn btn-sm btn-danger" onclick="Admin.removeMetaItem({{ meta[0] }})">
&minus;
</button>
</div>
<div class="col-3">
<div class="form-floating">
<input type="text" name="metaNames" id="metaNames_{{ meta[0] }}" class="form-control"
placeholder="Name" value="{{ meta[1] }}">
<label for="metaNames_{{ meta[0] }}">Name</label>
</div>
</div>
<div class="col-8">
<div class="form-floating">
<input type="text" name="metaValues" id="metaValues_{{ meta[0] }}" class="form-control"
placeholder="Value" value="{{ meta[2] }}">
<label for="metaValues_{{ meta[0] }}">Value</label>
</div>
</div>
</div>
{% endfor -%}
</div>
<button type="button" class="btn btn-sm btn-secondary" onclick="Admin.addMetaItem()">Add an Item</button>
<script>
document.addEventListener("DOMContentLoaded", () => Admin.setNextMetaIndex({{ model.metadata | size }}))
</script>
</div>
</fieldset>
</div>
</div>
{% if model.status == "Published" %}
<div class="row mb-3">
<div class="col">
<fieldset>
<legend>Maintenance</legend>
<div class="container">
<div class="row">
<div class="col align-self-center">
<div class="form-check pb-2">
<input type="checkbox" name="setPublished" id="setPublished" class="form-check-input"
value="true">
<label for="setPublished" class="form-check-label">Set Published Date</label>
</div>
</div>
<div class="col-3">
<div class="form-floating">
<input type="datetime-local" name="pubOverride" id="pubOverride" class="form-control"
placeholder="Override Date">
<label for="pubOverride" class="form-label">Published On</label>
</div>
</div>
<div class="col-6 align-self-center">
<div class="form-check pb-2">
<input type="checkbox" name="setUpdated" id="setUpdated" class="form-check-input" value="true">
<label for="setUpdated" class="form-check-label">
Purge revisions and set as updated date as well
</label>
</div>
</div>
</div>
</div>
</fieldset>
</div>
</div>
{% endif %}
</div> </div>
</form> </form>
</article> </article>

View File

@ -5,7 +5,7 @@
<thead> <thead>
<tr> <tr>
<th scope="col">Date</th> <th scope="col">Date</th>
<th scope="col">Title</th> <th scope="col" style="width:300px;">Title</th>
<th scope="col">Author</th> <th scope="col">Author</th>
<th scope="col">Status</th> <th scope="col">Status</th>
<th scope="col">Tags</th> <th scope="col">Tags</th>
@ -14,7 +14,7 @@
<tbody> <tbody>
{% for post in model.posts -%} {% for post in model.posts -%}
<tr> <tr>
<td> <td class="no-wrap">
{% if post.published_on.has_value -%} {% if post.published_on.has_value -%}
{{ post.published_on | date: "MMMM d, yyyy" }} {{ post.published_on | date: "MMMM d, yyyy" }}
{%- else -%} {%- else -%}
@ -31,9 +31,9 @@
<a href="#" class="text-danger">Delete</a> <a href="#" class="text-danger">Delete</a>
</small> </small>
</td> </td>
<td>{{ model.authors | value: post.author_id }}</td> <td class="no-wrap">{{ model.authors | value: post.author_id }}</td>
<td>{{ post.status }}</td> <td>{{ post.status }}</td>
<td>{{ post.tags | join: ", " }}</td> <td><span class="no-wrap">{{ post.tags | join: "</span>, <span class='no-wrap'>" }}</span></td>
</tr> </tr>
{%- endfor %} {%- endfor %}
</tbody> </tbody>

View File

@ -4,7 +4,7 @@
<input type="hidden" name="{{ csrf.form_field_name }}" value="{{ csrf.request_token }}"> <input type="hidden" name="{{ csrf.form_field_name }}" value="{{ csrf.request_token }}">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12 col-md-6 col-xl-4 offset-xl-2 pb-3"> <div class="col-12 col-md-6 col-xl-4 offset-xl-1 pb-3">
<div class="form-floating"> <div class="form-floating">
<input type="text" name="name" id="name" class="form-control" value="{{ model.name }}" required autofocus> <input type="text" name="name" id="name" class="form-control" value="{{ model.name }}" required autofocus>
<label for="name">Name</label> <label for="name">Name</label>
@ -16,15 +16,25 @@
<label for="subtitle">Subtitle</label> <label for="subtitle">Subtitle</label>
</div> </div>
</div> </div>
</div> <div class="col-12 col-md-4 col-xl-2 pb-3">
<div class="row">
<div class="col-12 col-md-4 col-xl-2 offset-xl-2 pb-3">
<div class="form-floating"> <div class="form-floating">
<input type="number" name="postsPerPage" id="postsPerPage" class="form-control" min="0" max="50" required <input type="number" name="postsPerPage" id="postsPerPage" class="form-control" min="0" max="50" required
value="{{ model.posts_per_page }}"> value="{{ model.posts_per_page }}">
<label for="postsPerPage">Posts per Page</label> <label for="postsPerPage">Posts per Page</label>
</div> </div>
</div> </div>
<div class="col-12 col-md-4 col-xl-3 offset-xl-1 pb-3">
<div class="form-floating">
<select name="themePath" id="themePath" class="form-control" required>
{% for theme in themes -%}
<option value="{{ theme[0] }}"{% if model.theme_path == theme[0] %} selected="selected"{% endif %}>
{{ theme[1] }}
</option>
{%- endfor %}
</select>
<label for="themePath">Theme</label>
</div>
</div>
<div class="col-12 col-md-4 col-xl-3 pb-3"> <div class="col-12 col-md-4 col-xl-3 pb-3">
<div class="form-floating"> <div class="form-floating">
<input type="text" name="timeZone" id="timeZone" class="form-control" required <input type="text" name="timeZone" id="timeZone" class="form-control" required
@ -32,7 +42,7 @@
<label for="timeZone">Time Zone</label> <label for="timeZone">Time Zone</label>
</div> </div>
</div> </div>
<div class="col-12 col-md-4 col-xl-3 pb-3"> <div class="col-12 col-md-4 col-xl-4 pb-3">
<div class="form-floating"> <div class="form-floating">
<select name="defaultPage" id="defaultPage" class="form-control" required> <select name="defaultPage" id="defaultPage" class="form-control" required>
{% for pg in pages -%} {% for pg in pages -%}

View File

@ -0,0 +1,59 @@
<div class="content">
{% for post in model.posts %}
<article class="item">
<h1 class="item-heading">
<a href="/{{ post.permalink }}" title="Permanent Link to &quot;{{ post.title | escape }}&quot;">
{{ post.title }}
</a>
</h1>
<h4 class="text-center">
<i class="fa fa-calendar" title="Date"></i> {{ post.published_on | date: "MMMM d, yyyy" }} &nbsp;
<i class="fa fa-clock-o" title="Time"></i> {{ post.published_on | date: "h:mmtt" | downcase }}
</h4>
{{ post.text }}
</article>
{% endfor %}
<nav aria-label="pagination">
<ul class="pager">
{% if model.newer_link -%}
<li class="previous item"><a href="/{{ model.newer_link }}">&laquo; Newer Posts</a></li>
{%- else -%}
<li></li>
{% endif %}
{% if model.older_link -%}
<li class="next item"><a href="/{{ model.older_link }}">Older Posts &raquo;</a></li>
{%- endif -%}
</ul>
</nav>
</div>
<div class="sidebar">
<br>
<div class="item votd-item">
<h4 class="item-heading votd-heading">Verse of the Day</h4>
<div>
<span class="verse"> &ndash;</span>
<a class="votd-reference" target="_blank" rel="noopener"></a>
<small> <a class="version-link" target="'_blank" rel="noopener">(ESV)</a></small><br>
<div class="votd-credits">
<small>Powered by <a href="https://biblegateway.com" target="_blank" rel="noopener">Bible Gateway</a></small>
</div>
<script src="https://www.biblegateway.com/votd/get/?format=json&amp;version=ESV&amp;callback=djs.displayVotd">
</script>
</div>
</div>
<div class="item">
<h4 class="item-heading">#VoteGold</h4>
<div class="text-center">
<p><em>
(Don't blame me;<br>
I voted for <a href="https://jo20.com/" title="Jorgensen / Cohen 2020" target="_blank" rel="noopener">Jo</a>)
</em></p>
</div>
</div>
<div class="item">
<h4 class="item-heading">Categories</h4>
<div>
TODO: list_categories({ class: 'cat' })
</div>
</div>
</div>

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="{{ generator }}"> <meta name="generator" content="{{ generator }}">
<title>{{ page_title }} &raquo; {{ web_log.name }}</title> <title>{{ page_title }}{% if page_title and page_title != "" %} &raquo; {% endif %}{{ web_log.name }}</title>
<link rel="preload" href="https://fonts.googleapis.com/css?family=Quicksand|Oswald" as="style"> <link rel="preload" href="https://fonts.googleapis.com/css?family=Quicksand|Oswald" as="style">
<link rel="preload" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" as="style"> <link rel="preload" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" as="style">
<link rel="preload" href="/themes/{{ web_log.theme_path }}/style.css" as="style"> <link rel="preload" href="/themes/{{ web_log.theme_path }}/style.css" as="style">
@ -22,7 +22,7 @@
{%- if web_log.subtitle %}<p>{{ web_log.subtitle.value }}</p>{% endif -%} {%- if web_log.subtitle %}<p>{{ web_log.subtitle.value }}</p>{% endif -%}
<p class="nav-spacer"></p> <p class="nav-spacer"></p>
{% for page in page_list %} {% for page in page_list %}
<p class="desktop"><a href="{{ page.permalink }}">{{ page.title }}</a></p> <p class="desktop"><a href="/{{ page.permalink }}">{{ page.title }}</a></p>
{% endfor %} {% endfor %}
<p class="desktop"> <p class="desktop">
<a href="https://devotions.summershome.org" target="_blank" rel="noopener">A Word from the Word</a> <a href="https://devotions.summershome.org" target="_blank" rel="noopener">A Word from the Word</a>
@ -72,7 +72,7 @@
<table style="width:100%;"><tbody><tr> <table style="width:100%;"><tbody><tr>
<td style="width:75px;"> <td style="width:75px;">
<a href="https://utsports.com" style="background:none;padding:0;" target="_blank" rel="noopener"> <a href="https://utsports.com" style="background:none;padding:0;" target="_blank" rel="noopener">
<img src="/themes/{{ web_log.theme_path }}/img/tennessee.png" alt="T" title="Tennessee Sports" <img src="/themes/{{ web_log.theme_path }}/tennessee.png" alt="T" title="Tennessee Sports"
style="border:0;" width="75px"> style="border:0;" width="75px">
</a> </a>
</td> </td>
@ -93,7 +93,7 @@
<table style="width:100%;"><tbody><tr> <table style="width:100%;"><tbody><tr>
<td style="width:75px;"> <td style="width:75px;">
<a href="https://csurams.com" style="background:none;padding:0;" target="_blank" rel="noopener"> <a href="https://csurams.com" style="background:none;padding:0;" target="_blank" rel="noopener">
<img src="/themes/{{ web_log.theme_path }}/img/csurams.png" alt="CSU Rams Logo" <img src="/themes/{{ web_log.theme_path }}/csurams.png" alt="CSU Rams Logo"
title="Colorado State Sports" style="border:0;" height="75px" width="75px"> title="Colorado State Sports" style="border:0;" height="75px" width="75px">
</a> </a>
</td> </td>

View File

@ -0,0 +1,6 @@
<div class="content single">
<article class="item">
<h1 class="item-heading">{{ page.title }}</h1>
{{ page.text }}
</article>
</div>

View File

@ -0,0 +1,63 @@
{%- assign post = model.posts | first -%}
<div class="content single">
<article class="item">
<h1 class="item-heading">{{ post.title }}</h1>
<h4 class="text-center">
{% if post.published_on -%}
<i class="fa fa-calendar" title="Date"></i> {{ post.published_on | date: "MMMM d, yyyy" }} &nbsp;
<i class="fa fa-clock-o" title="Time"></i> {{ post.published_on | date: "h:mmtt" | downcase }}
{%- else -%}
**DRAFT**
{% endif %}
</h4>
<div>{{ post.text }}</div>
{%- assign cat_count = post.category_ids | size -%}
{% if cat_count > 0 -%}
<h4>
Categorized &nbsp;
{% for cat in post.category_ids -%}
{% assign cat_name = model.categories | value: cat %}
<span class="no-wrap">
<i class="fa fa-folder-open-o" title="Category"></i>
<a href="/category/{{ cat }}" title="Categorized under &ldquo;{{ cat_name | escape }}&rdquo;">
{{ cat_name }}
</a> &nbsp; &nbsp;
</span>
{%- endfor %}
</h4>
{%- endif %}
{%- assign tag_count = post.tags | size -%}
{% if tag_count > 0 -%}
<h4>
Tagged &nbsp;
{% for tag in post.tags %}
<span class="no-wrap">
<a href="/tag/{{ tag | replace: " ", "-" }}" title="Posts tagged &ldquo;{{ tag | escape }}&rdquo;">
<i class="fa fa-tag"></i> {{ tag }}
</a> &nbsp; &nbsp;
</span>
{%- endfor %}
</h4>
{%- endif %}
</article>
<div>
<nav aria-label="pagination">
<ul class="pager">
{% if model.newer_link -%}
<li class="previous item">
<h4 class="item-heading"><a href="/{{ model.newer_link[0] }}">&ldquo;</a> Previous Post</h4>
<a href="/{{ model.newer_link[0] }}">&ldquo;{{ model.newer_link[1] }}&rdquo;</a>
</li>
{%- else -%}
<li></li>
{% endif %}
{% if model.older_link -%}
<li class="next item">
<h4 class="item-heading">Next Post <a href="/{{ model.older_link[0] }}">&rdquo;</a></h4>
<a href="/{{ model.older_link[0] }}">&ldquo;{{ model.older_link[1] }}&rdquo;</a>
</li>
{%- endif -%}
</ul>
</nav>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -20,3 +20,10 @@ legend {
float: unset; float: unset;
width: unset; width: unset;
} }
textarea {
font-family: monospace;
font-size: .8rem !important;
}
.no-wrap {
white-space: nowrap;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -27,7 +27,7 @@ body {
grid-template-rows: auto; grid-template-rows: auto;
color: var(--text-color); color: var(--text-color);
} }
a :link, a:visited { a:link, a:visited {
color: var(--accent-color); color: var(--accent-color);
text-decoration: none; text-decoration: none;
} }
@ -232,6 +232,9 @@ footer.part-3 {
.text-center { .text-center {
text-align: center; text-align: center;
} }
.no-wrap {
white-space: nowrap;
}
/* ----- SCALE UP STYLES ----- */ /* ----- SCALE UP STYLES ----- */
@media screen and ( min-width: 50rem ) { @media screen and ( min-width: 50rem ) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B