diff options
Diffstat (limited to 'app/jrnl')
-rw-r--r-- | app/jrnl/models.py | 19 | ||||
-rw-r--r-- | app/jrnl/templates/jrnl/entry_detail.html | 240 | ||||
-rw-r--r-- | app/jrnl/templates/jrnl/entry_detail.txt | 8 | ||||
-rw-r--r-- | app/jrnl/templates/jrnl/entry_list.html | 33 | ||||
-rw-r--r-- | app/jrnl/views.py | 4 |
5 files changed, 296 insertions, 8 deletions
diff --git a/app/jrnl/models.py b/app/jrnl/models.py index dda9d6d..f3734da 100644 --- a/app/jrnl/models.py +++ b/app/jrnl/models.py @@ -273,14 +273,17 @@ def cache_gravatar(sender, comment, **kwargs): urllib.request.urlretrieve(url, local_grav) -#@receiver(post_save, sender=Entry) -#def post_save_events(sender, update_fields, created, instance, **kwargs): -# related, created = RelatedPost.objects.get_or_create(model_name=instance.get_content_type(), entry_id = instance.id) -# related.title = instance.title -# related.slug = instance.slug -# post_save.disconnect(post_save_events, sender=Entry) -# instance.save() -# post_save.connect(post_save_events, sender=Entry) +@receiver(post_save, sender=Entry) +def post_save_events(sender, update_fields, created, instance, **kwargs): + """ + Creates a generic related entry when a new post is added + """ + if created: + related, c = RelatedPost.objects.get_or_create(model_name=instance.get_content_type(), entry_id = instance.id, pub_date=instance.pubdate) + if c: + related.title = instance.title + related.slug = instance.slug + related.save() # from django_comments.signals import comment_will_be_posted # from django_comments import akismet diff --git a/app/jrnl/templates/jrnl/entry_detail.html b/app/jrnl/templates/jrnl/entry_detail.html new file mode 100644 index 0000000..0904178 --- /dev/null +++ b/app/jrnl/templates/jrnl/entry_detail.html @@ -0,0 +1,240 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load comments %} + +{% block pagetitle %}{{object.title|title|smartypants|safe}} - by Scott Gilbertson{% endblock %} + +{% block metadescription %}{% autoescape on %}{{object.meta_description|striptags|safe}}{% endautoescape %}{% endblock %} +{%block extrahead%} + <link rel="canonical" href="https://luxagraf.net{{object.get_absolute_url}}" /> + <meta name="ICBM" content="{{object.latitude}}, {{object.longitude}}" /> + <meta name="geo.position" content="{{object.latitude}}; {{object.longitude}}" /> + <meta name="geo.placename" content="{% if object.location.country_name == "United States" %}{{object.location.name|smartypants|safe}}, {{object.state.name}}{%else%}{{object.location.name|smartypants|safe}}, {{object.location.country_name}}{%endif%}"> + <meta name="geo.region" content="{{object.country.iso2}}{%if object.state.code != '' %}-{{object.state.code}}{%endif%}"> + <meta property="og:type" content="article" /> + <meta property="og:title" content="{{object.title|safe}}" /> + <meta property="og:url" content="https://luxagraf.net{{object.get_absolute_url}}" /> + <meta property="og:description" content="{{object.meta_description}}" /> + <meta property="article:published_time" content="{{object.pub_date|date:'c'}}" /> + <meta property="article:author" content="Scott Gilbertson" /> + <meta property="og:site_name" content="Luxagraf" /> + <meta property="og:image" content="{{object.get_featured_image}}" /> + <meta property="og:locale" content="en_US" /> + <meta name="twitter:card" content="summary_large_image"/> + <meta name="twitter:description" content="{{object.meta_description}}"/> + <meta name="twitter:title" content="{{object.title|safe}}"/> + <meta name="twitter:site" content="@luxagraf"/> + <meta name="twitter:domain" content="luxagraf"/> + <meta name="twitter:image:src" content="{{object.get_featured_image}}"/> + <meta name="twitter:creator" content="@luxagraf"/> +<script type="application/ld+json"> +{ + "@context": "https://schema.org", + "@type": "Article", + "mainEntityOfPage": { + "@type": "WebPage", + "@id": "https://luxagraf.net{{object.get_absolute_url}}" + }, + "headline": "{{object.title}}", + "datePublished": "{{object.pub_date|date:'c'}}+04:00", + "dateModified": "{{object.pub_date|date:'c'}}+04:00", + "author": { + "@type": "Person", + "name": "Scott Gilbertson" + }, + "publisher": { + "@type": "Organization", + "name": "Luxagraf", + "logo": { + "@type": "ImageObject", + "url": "https://luxagraf.net/media/img/logo-white.jpg" + } + }, + "description": "{{object.meta_description}}" +} +</script> +{%endblock%} +{%block htmlclass%}{% with object.template_name as t %} +class="detail {%if t == 1 or t == 3 or t == 5 %}double{%else%}single{%endif%}{%if t == 2 or t == 3 %} dark{%endif%}{%if t == 4 or t == 5 %} black{%endif%}"{%endwith%}{%endblock%} + + {% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} +{% block primary %} + <main> + <article class="h-entry hentry entry-content content{% with object.get_template_name_display as t %}{%if t == "double" or t == "double-dark" %} post--article--double{%endif%}{%endwith%}" itemscope itemType="http://schema.org/BlogPosting"> + <header id="header" class="post-header {% with object.get_template_name_display as t %}{%if t == "double" or t == "double-dark" %}post--header--double{%endif%}{%endwith%}"> + <h1 class="p-name entry-title post-title" itemprop="headline">{%if object.template_name == 1 or object.template_name == 3 %}{{object.title|smartypants|safe}}{%else%}{{object.title|smartypants|safe}}{%endif%}</h1> + {% if object.subtitle %}<h2 class="post-subtitle">{{object.subtitle|smartypants|safe}}</h2>{%endif%} + <div class="post-linewrapper"> + {% if object.location %}<div class="p-location h-adr adr post-location" itemprop="contentLocation" itemscope itemtype="http://schema.org/Place"> + <h3 class="h-adr" itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">{% if object.location.country_name == "United States" %}<span class="p-locality locality" itemprop="addressLocality">{{object.location.name|smartypants|safe}}</span>, <a class="p-region region" href="/jrnl/united-states/" title="travel writing from the United States">{{object.location.state_name|safe}}</a>, <span class="p-country-name" itemprop="addressCountry">U.S.</span>{%else%}<span class="p-region" itemprop="addressRegion">{{object.location.name|smartypants|safe}}</span>, <a class="p-country-name country-name" href="/jrnl/{{object.location.country_slug}}/" title="travel writing from {{object.location.country_name}}"><span itemprop="addressCountry">{{object.location.country_name|safe}}</span></a>{%endif%}</h3> + – <a href="" onclick="showMap({{object.latitude}}, {{object.longitude}}, { type:'point', lat:'{{object.latitude}}', lon:'{{object.longitude}}'}); return false;" title="see a map">Map</a> + </div>{%endif%} + <time class="dt-published published dt-updated post-date" datetime="{{object.pub_date|date:'c'}}" itemprop="datePublished">{{object.pub_date|date:"F"}} <span>{{object.pub_date|date:"j, Y"}}</span></time> + <span class="hide" itemprop="author" itemscope itemtype="http://schema.org/Person">by <a class="p-author h-card" href="/about"><span itemprop="name">Scott Gilbertson</span></a></span> + </div> + </header> + <div id="article" class="e-content entry-content post--body post--body--{% with object.template_name as t %}{%if t == 0 or t == 2 %}single{%endif%}{%if t == 1 or t == 3 %}double{%endif%}{%endwith%}" itemprop="articleBody"> + {{object.body_html|safe|smartypants}} + </div> + {%if wildlife or object.field_notes.all or object.books.all %}<div class="entry-footer">{%if wildlife %} + <aside id="wildlife"> + <h3>Fauna and Flora</h3> + {% regroup wildlife by ap.apclass.get_kind_display as wildlife_list %} + <ul> + {% for object_list in wildlife_list %} + <li class="grouper">{{object_list.grouper}}<ul> + {% for object in object_list.list %} + <li>{%if object.ap.body_markdown%}<a href="{% url 'sightings:detail' object.ap.slug %}">{{object}}</a>{%else%}{{object}}{%endif%} </li> + {% endfor %}</ul> + {% endfor %}</ul> + </aside> + {% endif %}{%if object.field_notes.all %} + <aside {% if wildlife %}class="margin-left-none" {%endif%}id="field_notes"> + <h3>Field Notes</h3> + <ul>{% for obj in object.field_notes.all %} + <li><a href="{% url 'fieldnotes:detail' year=obj.pub_date.year month=obj.pub_date|date:"m" slug=obj.slug %}">{{obj}}</a></li> + {% endfor %}</ul> + </aside>{% endif %} + {%if object.books.all %} + <aside id="recommended-reading" {%if object.field_notes.all and wildlife %}class="rr-clear{%endif%}" > + <h3>Recommended Reading</h3> + <ul>{% for obj in object.books.all %} + <li><a href="{% url 'books:detail' slug=obj.slug %}"><img src="{{obj.get_small_image_url}}" /></a></li> + {% endfor %}</ul> + </aside>{% endif %} + </div>{%endif%} + </article> + {% with object.get_next_published as next %} + {% with object.get_previous_published as prev %} + <div class="nav-wrapper"> + <nav id="page-navigation" {%if wildlife or object.field_notes.all or object.books.all %}{%else%}class="page-border-top"{%endif%}> + <ul>{% if prev%} + <li id="prev"><span class="bl">Previous:</span> + <a href="{{ prev.get_absolute_url }}" rel="prev" title=" {{prev.title}}">{{prev.title|safe}}</a> + </li>{%endif%}{% if next%} + <li id="next"><span class="bl">Next:</span> + <a href="{{ next.get_absolute_url }}" rel="next" title=" {{next.title}}">{{next.title|safe}}</a> + </li>{%endif%} + </ul> + </nav>{%endwith%}{%endwith%} + </div> + {% if object.related.all %}<div class="article-afterward related"> + <div class="related-bottom"> + <h6 class="hedtinycaps">You might also enjoy</h6> + <ul class="article-card-list">{% for object in related %} + <li class="article-card-mini"><a href="{{object.get_absolute_url}}" title="{{object.title}}"> + <div class="post-image post-mini-image"> + {% if object.featured_image %} + {% include "lib/img_archive.html" with image=object.featured_image nolightbox=True %} + {% elif object.image %} + {% include "lib/img_archive.html" with image=object.image nolightbox=True %} + {% else %} + <img src="{{object.get_image_url}}" alt="{{ object.title }}" class="u-photo post-image" itemprop="image" />{%endif%} + </div> + <h4 class="p-name entry-title post-title" itemprop="headline">{% if object.title %}{{object.title|safe|smartypants|widont}}{% else %}{{object.common_name}}{%endif%}</h4> + <p class="p-author author hide" itemprop="author"><span class="byline-author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Scott Gilbertson</span></span></p> + <p class="post-summary"> + <span class="p-location h-adr adr post-location" itemprop="contentLocation" itemscope itemtype="http://schema.org/Place"> + {% if object.location.country_name == "United States" %}{{object.location.state_name}}{%else%}{{object.location.country_name}}{%endif%} + </span> + – + <time class="dt-published published dt-updated post-date" datetime="{{object.pub_date|date:'c'}}"><span>{{object.pub_date|date:" Y"}}</span></time> + </p> + </a> + </li> + {% endfor %}</ul> + </div> + </div>{%endif%} + + {% comment %} <div class="mailing-list--wrapper"> + <h5>If you enjoyed this, you should join the mailing list…</h5> + {% include 'mailing_list.html' %} + </div> {% endcomment %} + {% if object.enable_comments %} +{% get_comment_count for object as comment_count %} +{%if comment_count > 0 %} +<p class="comments--header">{{comment_count}} Comment{{ comment_count|pluralize }}</p> +{% render_comment_list for object %} +{%endif%} +<div class="comment--form--wrapper {%if comment_count > 0%}comment-form-border{%endif%}"> +{% render_comment_form for object %} +</div> +{% else %} +<p class="comments--header" style="text-align: center">Sorry, comments have been disabled for this post.</p> +{%endif%} +</main> +{% endblock %} +{% block js %} +<script> +document.addEventListener("DOMContentLoaded", function(event) { + var leaflet = document.createElement('script'); + leaflet.src = "/media/js/leaflet-master/leaflet-mod.js"; + document.body.appendChild(leaflet); + var lightbox = document.createElement('script'); + lightbox.src = "/media/js/lightbox.js"; + document.body.appendChild(lightbox); + leaflet.onload = function(){ + var detail = document.createElement('script'); + detail.src = "/media/js/detail.min.js"; + document.body.appendChild(detail); + {% with object.get_template_name_display as t %}{%if t == "single" or t == "single-dark" %} + detail.onload = function(){ + createMap(); + var open = false; + } + {%endif%}{%endwith%} + } + + lightbox.onload = function() { + var opts= { + //nextOnClick: false, + captions: true, + onload: function(){ + var im = document.getElementById("jslghtbx-contentwrapper"); + var link = im.appendChild(document.createElement('a')) + link.href = im.firstChild.src; + link.innerHTML= "open "; + link.target = "_blank"; + link.setAttribute('class', 'p-link'); + im.appendChild(link); + } + }; + var lightbox = new Lightbox(); + lightbox.load(opts); + } + {% if object.enable_comments %} +{% get_comment_count for object as comment_count %} +{%if comment_count > 0 %} + //delay loading of gravatar images using noscript data-hash attribute + dataattr = document.getElementsByClassName("datahashloader"); + for(var i=0; i<dataattr.length; i++) { + var c = dataattr[i].parentNode; + var img = document.createElement("img"); + img.src = 'https://images.luxagraf.net/gravcache/' + dataattr[i].getAttribute('data-hash') + '.jpg'; + img.className += "gravatar"; + img.alt = "gravatar icon"; + c.insertBefore(img, c.childNodes[3]); + } +{%endif%} +{%endif%} +{% if object.has_video %} +var tester = document.getElementsByClassName("vidauto"); +var wrapper = document.getElementById('wrapper'); +var dist = 100; + +window.onscroll = function() { + for (var i=0; i<tester.length; i++) { + checkVisible(tester[i]) ? tester[i].play() : tester[i].pause(); + } +}; + +function checkVisible(elm) { + var rect = elm.getBoundingClientRect(); + var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight); + return !(rect.bottom < 0 || rect.top - viewHeight >= 0); +} +{%endif%} + +}); +</script> +{%endblock%} diff --git a/app/jrnl/templates/jrnl/entry_detail.txt b/app/jrnl/templates/jrnl/entry_detail.txt new file mode 100644 index 0000000..547ce79 --- /dev/null +++ b/app/jrnl/templates/jrnl/entry_detail.txt @@ -0,0 +1,8 @@ +{{object.title|safe}} +{% for letter in object.title %}={%endfor%} + + by Scott Gilbertson + <{{SITE_URL}}{{object.get_absolute_url}}> + {{object.pub_date|date:"l, d F Y"}} + +{{object.body_markdown|safe}} diff --git a/app/jrnl/templates/jrnl/entry_list.html b/app/jrnl/templates/jrnl/entry_list.html new file mode 100644 index 0000000..6eefe10 --- /dev/null +++ b/app/jrnl/templates/jrnl/entry_list.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load pagination_tags %} +{% block pagetitle %}Luxagraf | {% if region %}Travel Writing from {{region.name|title|smartypants|safe}}{%else%}Travel Writing from Around the World {%endif%}{% if page != "1" %} -- Page {{page}}{%endif%}{% endblock %} +{% block metadescription %}{% if region %}Travel writing, essays and dispatches from {{region.name|title|smartypants|safe}}{%else%}Travel writing, essays and dispatches from around the world{%endif%} Page {{page}}{% endblock %} +{%block bodyid%}id="writing" class="archive"{%endblock%} +{% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} +{% block primary %}<main class="archive-grid"> + <h1 class="hide">{% if region %}Journal entries from {%if region.name == 'United States'%}the United States{%else%}{{region.name|title|smartypants|safe}}{%endif%}{%else%}Journal {%endif%}</h1>{% autopaginate object_list 24 %} {% for object in object_list %} + <article class="h-entry hentry archive-card {% cycle 'odd' 'even' %} {% cycle 'first' 'second' 'third' %}" itemscope itemType="http://schema.org/Article"> + <div class="post-image"> + <a href="{{object.get_absolute_url}}" title="{{object.title}}">{% if object.featured_image %} + {% include "lib/img_archive.html" with image=object.featured_image %} + {%else%} + <img src="{{object.get_image_url}}" alt="{{ object.title }}" class="u-photo post-image" itemprop="image" />{%endif%}</a> + </div> + <h2 class="p-name entry-title post-title" itemprop="headline"><a href="{{object.get_absolute_url}}" class="u-url" title="{%if object.title_keywords%}{{object.title_keywords}}{%else%}{{object.title}}{%endif%}">{{object.title|safe|smartypants|widont}}</a></h2> + <p class="p-author author hide" itemprop="author"><span class="byline-author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Scott Gilbertson</span></span></p> + <time class="dt-published published dt-updated post-date" datetime="{{object.pub_date|date:'c'}}">{{object.pub_date|date:"F"}} <span>{{object.pub_date|date:"j, Y"}}</span></time> + <p class="post-summary"> + <span class="p-location h-adr adr post-location" itemprop="contentLocation" itemscope itemtype="http://schema.org/Place"> + {% if object.location.country_name == "United States" %}<span class="p-locality locality">{{object.location.name|smartypants|safe}}</span>, <a class="p-region region" href="/jrnl/united-states/" title="travel writing from the United States">{{object.location.state_name}}</a>, <span class="p-country-name">U.S.</span>{%else%}<span class="p-region">{{object.location.name|smartypants|safe}}</span>, <a class="p-country-name country-name" href="/jrnl/{{object.location.country_slug}}/" title="travel writing from {{object.location.country_name}}">{{object.location.country_name}}</a>{%endif%} + </span> – + <span class="p-summary" itemprop="description"> + {{object.dek|safe}} + </span> + </p> + </article> {% endfor %} + </main> + <nav aria-label="page navigation" class="pagination"> + {% paginate %} + </nav> +{% endblock %} diff --git a/app/jrnl/views.py b/app/jrnl/views.py index 1b38de9..6b7cc8d 100644 --- a/app/jrnl/views.py +++ b/app/jrnl/views.py @@ -1,6 +1,7 @@ from django.views.generic import ListView from django.views.generic.detail import DetailView from django.views.generic.dates import DateDetailView +from django.urls import reverse from django.views.generic.dates import YearArchiveView, MonthArchiveView from django.contrib.syndication.views import Feed from django.apps import apps @@ -31,6 +32,7 @@ class EntryCountryList(PaginatedListView): """ Return a list of Entries by Country in reverse chronological order """ + model = Entry def get_context_data(self, **kwargs): # Call the base implementation first to get a context @@ -102,6 +104,8 @@ class EntryDetailView(DateDetailView): model = apps.get_model(obj.model_name.app_label, obj.model_name.model) related.append(model.objects.get(slug=obj.slug, pub_date=obj.pub_date)) context['related'] = related + context['breadcrumbs'] = ("jrnl",) + context['crumb_url'] = reverse('jrnl:list') return context |