diff options
-rw-r--r-- | TODO | 10 | ||||
-rw-r--r-- | app/pages/build.py | 8 | ||||
-rw-r--r-- | app/pages/models.py | 2 | ||||
-rw-r--r-- | app/pages/views.py | 2 | ||||
-rw-r--r-- | app/posts/importer.py | 78 | ||||
-rw-r--r-- | app/posts/migrations/0014_auto_20201113_1444.py | 18 | ||||
-rw-r--r-- | app/posts/migrations/0015_post_old_image.py | 19 | ||||
-rw-r--r-- | app/posts/models.py | 16 | ||||
-rw-r--r-- | app/posts/templates/posts/jrnl_date.html | 42 | ||||
-rw-r--r-- | app/posts/templates/posts/jrnl_detail.html | 240 | ||||
-rw-r--r-- | app/posts/templates/posts/jrnl_detail.txt (renamed from app/posts/templates/posts/entry_detail.txt) | 0 | ||||
-rw-r--r-- | app/posts/templates/posts/jrnl_list.html | 33 | ||||
-rw-r--r-- | app/posts/urls/jrnl_urls.py | 60 | ||||
-rw-r--r-- | app/posts/views.py | 95 | ||||
-rw-r--r-- | app/posts/views/jrnl_views.py | 173 | ||||
-rw-r--r-- | app/utils/util.py | 10 | ||||
-rw-r--r-- | config/base_urls.py | 7 | ||||
-rw-r--r-- | design/templates/base.html | 2 |
18 files changed, 696 insertions, 119 deletions
@@ -1,8 +1,8 @@ -- port jrnl to posts - - port comments - - port ??? -- take guides out of main menu, they're not good enough yet. - +- port jrnl to posts ---DONE + - port comments ---DONE +- take guides out of main menu, they're not good enough yet. ---DONE +- Shift build tools for Jrnl to Posts +- Figure out how to handle homepage diff --git a/app/pages/build.py b/app/pages/build.py index b1bd53d..2309983 100644 --- a/app/pages/build.py +++ b/app/pages/build.py @@ -11,14 +11,6 @@ class BuildPages(BuildNew): self.build_detail_view() print("building pages") - ''' - def build_essays(self): - qs = self.model.objects.filter(path="essays", build=True) - c = {'object_list': qs, 'MEDIA_URL': settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL} - t = render_to_string('archives/essays.html', c).encode('utf-8') - self.write_file('essays/', t) - ''' - def get_model_queryset(self): return self.model.objects.filter(build=True) diff --git a/app/pages/models.py b/app/pages/models.py index 76f7d1d..5e9cd5b 100644 --- a/app/pages/models.py +++ b/app/pages/models.py @@ -39,4 +39,4 @@ class PageSitemap(Sitemap): protocol = "https" def items(self): - return Page.objects.all() + return Page.objects.filter(build=True) diff --git a/app/pages/views.py b/app/pages/views.py index bef6529..167ad01 100644 --- a/app/pages/views.py +++ b/app/pages/views.py @@ -10,6 +10,8 @@ class PageDetailView(LuxDetailView): obj = self.get_object() return ["pages/%s.html" % obj.slug, 'pages/page_detail.html'] + class PageDetailTXTView(LuxDetailView): model = Page slug_field = "slug" + template_name = "pages/page_detail.txt" diff --git a/app/posts/importer.py b/app/posts/importer.py index 53a84aa..7ed4782 100644 --- a/app/posts/importer.py +++ b/app/posts/importer.py @@ -27,3 +27,81 @@ for e in essaysold: epilogue_markdown=e.afterword, ) print(created) + + + +# migrate jrnl to posts +for e in Entry.objects.all(): + if e.meta_description: + meta_description = e.meta_description + else: + meta_description = "needs" + if e.image: + old_image = e.image + else: + old_image = None + p, created = Post.objects.get_or_create( + old_id=e.pk, + title = e.title, + short_title = '', + subtitle = e.subtitle, + slug = e.slug, + body_markdown = e.body_markdown, + body_html = e.body_html, + dek = e.dek, + meta_description = meta_description, + pub_date = e.pub_date, + enable_comments = e.enable_comments, + status = e.status, + featured_image = e.featured_image, + post_type = PostType.JRNL, + template_name = e.template_name, + has_video = e.has_video, + point = e.point, + location = e.location, + old_image=old_image + ) + for b in e.books.all(): + c = Book.objects.get( + slug=b.slug, + title=b.title, + ) + p.books.add(c) + for f in e.field_notes.all(): + c = Post.objects.get( + slug=f.slug, + title=f.title, + ) + p.field_notes.add(c) + p.save() + +#Then after they're all in there: +ctype = ContentType.objects.get(app_label='posts',model='post') +oldctype = ContentType.objects.get(app_label='jrnl',model='entry') +for e in Entry.objects.all(): + p = Post.objects.get(title=e.title,old_id=e.id) + if e.related: + for t in e.related.all(): + if t.model_name == oldctype: + tp = ctype + else: + tp = t.model_name + c = RelatedPost.objects.get( + model_name=tp, + title=t.title, + slug=t.slug, + pub_date=t.pub_date + ) + p.related.add(c) + p.save() + +# Then to port comments: +ctype = ContentType.objects.get(app_label='posts',model='post') +oldctype = ContentType.objects.get(app_label='jrnl',model='entry') +for c in Comment.objects.filter(content_type=oldctype): + e = Entry.objects.get(pk=c.object_pk) + p = Post.objects.get(title=e.title,old_id=e.id) + c.object_pk = p.pk + c.content_type = ctype + print("%s --> %s" %(c.content_object,p)) + c.save() diff --git a/app/posts/migrations/0014_auto_20201113_1444.py b/app/posts/migrations/0014_auto_20201113_1444.py new file mode 100644 index 0000000..2ac1df0 --- /dev/null +++ b/app/posts/migrations/0014_auto_20201113_1444.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1 on 2020-11-13 14:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0013_auto_20201111_2231'), + ] + + operations = [ + migrations.AlterField( + model_name='post', + name='template_name', + field=models.IntegerField(choices=[(0, 'single'), (1, 'double'), (2, 'single-dark'), (3, 'double-dark'), (4, 'single-black'), (5, 'double-black')], default=0), + ), + ] diff --git a/app/posts/migrations/0015_post_old_image.py b/app/posts/migrations/0015_post_old_image.py new file mode 100644 index 0000000..e9d6088 --- /dev/null +++ b/app/posts/migrations/0015_post_old_image.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1 on 2020-11-13 16:14 + +from django.db import migrations, models +import posts.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('posts', '0014_auto_20201113_1444'), + ] + + operations = [ + migrations.AddField( + model_name='post', + name='old_image', + field=models.FileField(blank=True, help_text='should be 520 by 290', null=True, upload_to=posts.models.get_upload_path), + ), + ] diff --git a/app/posts/models.py b/app/posts/models.py index 838e269..c686070 100644 --- a/app/posts/models.py +++ b/app/posts/models.py @@ -32,6 +32,10 @@ from taxonomy.models import TaggedItems, Category from utils.util import render_images, render_products, parse_video, markdown_to_html, extract_main_image +def get_upload_path(self, filename): + return "images/post-images/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + class PostType(models.IntegerChoices): FIELD_TEST = 0, ('field test') REVIEW = 1, ('review') @@ -66,6 +70,11 @@ class Post(models.Model): featured_image = models.ForeignKey(LuxImage, on_delete=models.CASCADE, null=True, blank=True) TEMPLATES = ( (0, 'single'), + (1, 'double'), + (2, 'single-dark'), + (3, 'double-dark'), + (4, 'single-black'), + (5, 'double-black'), ) post_type = models.IntegerField(choices=PostType.choices, default=PostType.JRNL) template_name = models.IntegerField(choices=TEMPLATES, default=0) @@ -73,7 +82,7 @@ class Post(models.Model): has_code = models.BooleanField(blank=True, default=False) disclaimer = models.BooleanField(blank=True, default=False) books = models.ManyToManyField(Book, blank=True) - #field_notes = models.ManyToManyField(FieldNote, blank=True) + old_image = models.FileField(upload_to=get_upload_path, blank=True, null=True, help_text="should be 520 by 290") related = models.ManyToManyField(RelatedPost, blank=True) point = models.PointField(null=True, blank=True) location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True) @@ -101,6 +110,8 @@ class Post(models.Model): return reverse('src:detail', kwargs={"slug": self.slug}) if self.post_type == 5: return reverse('fieldnote:detail', kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) + if self.post_type == PostType.JRNL: + return reverse('jrnl:detail', kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) def comment_period_open(self): return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date @@ -146,7 +157,7 @@ class Post(models.Model): @property def sitemap_priority(self): - if self.post_type in [0,1,4,5]: + if self.post_type in [2,4,5]: return 1.0 else: return 0.7 @@ -156,6 +167,7 @@ class Post(models.Model): if not created: md = render_images(self.body_markdown) prods = render_products(md) + print(self.title) self.body_html = markdown_to_html(prods) if self.epilogue_html: self.epilogue_html = markdown_to_html(self.epilogue_markdown) diff --git a/app/posts/templates/posts/jrnl_date.html b/app/posts/templates/posts/jrnl_date.html new file mode 100644 index 0000000..dba1c53 --- /dev/null +++ b/app/posts/templates/posts/jrnl_date.html @@ -0,0 +1,42 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load html5_datetime %} +{% block pagetitle %} Field Notes | luxagraf {% endblock %} +{% block metadescription %} Rough notes and sketches from the field {% endblock %} +{%block bodyid%}id="field-notes"{%endblock%} + +{% block primary %} + <ul class="bl" id="breadcrumbs" itemscope itemtype="http://data-vocabulary.org/Breadcrumb"> + <li><a href="/" title="luxagraf homepage" itemprop="url"><span itemprop="title">Home</span></a> → </li> + <li>{% if month or year %}<a href="{% url 'jrnl:list' %}">Jrnl</a> →{%else%}Field Notes{%endif%}</li> + <li>{% if not month %}{{year|date:"Y"}}{%else%}<a href="/jrnl/{{month|date:"Y"}}/">{{month|date:"Y"}}</a> →{%endif%}</li> + {% if month %}<li itemprop="title">{{month|date:"F"}}</li>{% endif %} + </ul> + <main role="main" id="essay-archive" class="essay-archive archive-list"> + <div class="essay-intro"> + <h2>Journal {% if month or year %}{% if month %} from {{month|date:"F"}} {{month|date:"Y"}}{%else%} from {{year|date:"Y"}}{%endif%}{%endif%}</h2> + </div> + <ul class="fancy-archive-list">{% for object in object_list %}{% if object.slug != 'about' %} + <li class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <a href="{{object.get_absolute_url}}"> + {% if object.featured_image %}<div class="circle-img-wrapper"><img src="{{object.featured_image.get_thumbnail_url}}" alt="{{object.featured_image.alt}}" /></div>{%endif%} + <span class="date dt-published">{{object.pub_date|date:"F d, Y"}}</span> + <a href="{{object.get_absolute_url}}"> + <h2>{{object.title|safe|smartypants|widont}}</h2> + {% if object.subtitle %}<h3 class="p-summary">{{object.subtitle|safe|smartypants|widont}}</h3>{%endif%} + </a> + {% if object.location %}<h4 class="p-location h-adr post-location" itemprop="geo" itemscope itemtype="http://data-vocabulary.org/Geo"> + <span class="p-locality">{{object.location.name|smartypants|safe}}</span>, + <span class="p-region">{{object.location.state_name}}</span>, + <span class="p-country-name">{{object.location.country_name}}</span> + <data class="p-latitude" value="{{object.latitude}}"></data> + <data class="p-longitude" value="{{object.longitude}}"></data> + </h4>{% endif %} + </li> + {%endif%}{%endfor%}</ul> + </main> + +{% endblock %} + + + diff --git a/app/posts/templates/posts/jrnl_detail.html b/app/posts/templates/posts/jrnl_detail.html new file mode 100644 index 0000000..0904178 --- /dev/null +++ b/app/posts/templates/posts/jrnl_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/posts/templates/posts/entry_detail.txt b/app/posts/templates/posts/jrnl_detail.txt index 547ce79..547ce79 100644 --- a/app/posts/templates/posts/entry_detail.txt +++ b/app/posts/templates/posts/jrnl_detail.txt diff --git a/app/posts/templates/posts/jrnl_list.html b/app/posts/templates/posts/jrnl_list.html new file mode 100644 index 0000000..6eefe10 --- /dev/null +++ b/app/posts/templates/posts/jrnl_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/posts/urls/jrnl_urls.py b/app/posts/urls/jrnl_urls.py new file mode 100644 index 0000000..d7f0fb1 --- /dev/null +++ b/app/posts/urls/jrnl_urls.py @@ -0,0 +1,60 @@ +from django.urls import path, re_path + +from ..views import jrnl_views as views + +app_name = "jrnl" + +urlpatterns = [ + path( + r'feed.xml', + views.JrnlRSSFeedView(), + name="feed" + ), + re_path( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+).txt$', + views.JrnlDetailViewTXT.as_view(), + name="detail-txt" + ), + re_path( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+)$', + views.JrnlDetailView.as_view(), + name="detail" + ), + re_path( + r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', + views.JrnlMonthArchiveView.as_view(month_format='%m'), + name="list_month" + ), + re_path( + r'(?P<year>\d{4})/$', + views.JrnlYearArchiveView.as_view(), + name="list_year" + ), + re_path( + r'^(?P<page>\d+)/$', + views.JrnlListView.as_view(), + name="list" + ), + path( + r'latest/', + views.JrnlLatestView.as_view(), + name="latest" + ), + re_path( + r'(?P<slug>[-\w]+)/(?P<page>\d+)/$', + views.JrnlCountryListView.as_view(), + name="list_country" + ), + re_path( + r'^(?P<slug>[-\w]+)/$', + views.JrnlCountryListView.as_view(), + {'page':1}, + name="list_country" + ), + re_path( + r'', + views.JrnlListView.as_view(), + {'page':1}, + name="list" + ), +] diff --git a/app/posts/views.py b/app/posts/views.py deleted file mode 100644 index a3f1a1f..0000000 --- a/app/posts/views.py +++ /dev/null @@ -1,95 +0,0 @@ -from django.views.generic import ListView -from django.views.generic.detail import DetailView -from django.contrib.syndication.views import Feed -from django.apps import apps -from django.conf import settings - -from utils.views import PaginatedListView, LuxDetailView - -from .models import Post -from taxonomy.models import Category - - -class GuideListView(PaginatedListView): - """ - Return a list of Entries in reverse chronological order - """ - model = Post - template_name = "posts/guide_base.html" - - def get_queryset(self): - queryset = super(GuideListView, self).get_queryset() - return queryset.filter(status__exact=1).order_by('-pub_date').prefetch_related('location').prefetch_related('featured_image') - - -class ReviewsListView(GuideListView): - template_name = "posts/post.html" - - def get_queryset(self): - queryset = super(ReviewsListView, self).get_queryset() - return queryset.filter(post_type__in=[0,1]).filter(status__exact=1).order_by('-pub_date').prefetch_related('location').prefetch_related('featured_image') - - def get_context_data(self, **kwargs): - context = super(ReviewsListView, self).get_context_data(**kwargs) - context['archive_type'] = 'Field Tests' - return context - - -class EssayListView(GuideListView): - template_name = "posts/essay_list.html" - - def get_queryset(self): - queryset = super(EssayListView, self).get_queryset() - return queryset.filter(post_type__in=[2,]).filter(status__exact=1).order_by('-pub_date').prefetch_related('location').prefetch_related('featured_image') - - def get_context_data(self, **kwargs): - ''' - override for custom breadcrumb path - ''' - # Call the base implementation first to get a context - context = super(EssayListView, self).get_context_data(**kwargs) - context['breadcrumbs'] = ('Essays',) - return context - - -class PostDetailView(LuxDetailView): - model = Post - slug_field = "slug" - - def get_queryset(self): - queryset = super(PostDetailView, self).get_queryset() - return queryset.select_related('location').prefetch_related('field_notes') - - def get_context_data(self, **kwargs): - context = super(PostDetailView, self).get_context_data(**kwargs) - related = [] - for obj in self.object.related.all(): - model = apps.get_model(obj.post_model.app_label, obj.post_model.model) - related.append(model.objects.get(slug=obj.slug)) - context['related'] = related - return context - - def get_template_names(self): - obj = self.get_object() - return ["posts/%s_detail.html" % obj.get_post_type_display(), 'posts/post_detail.html'] - - -class PostDetailViewTXT(PostDetailView): - template_name = "posts/entry_detail.txt" - - -class PostsRSSFeedView(Feed): - title = "VanLifeReviews.com: " - link = "/" - description = "Latest reviews, stories and guides" - description_template = 'feeds/blog_description.html' - - def items(self): - return Post.objects.filter(status__exact=1).order_by('-pub_date')[:10] - - def item_pubdate(self, item): - """ - Takes an item, as returned by items(), and returns the item's - pubdate. - """ - return item.pub_date diff --git a/app/posts/views/jrnl_views.py b/app/posts/views/jrnl_views.py new file mode 100644 index 0000000..1ff7a4c --- /dev/null +++ b/app/posts/views/jrnl_views.py @@ -0,0 +1,173 @@ +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 +from django.shortcuts import get_object_or_404 +from django.conf import settings +from django.db.models import Q + +from utils.views import PaginatedListView + +#from ..models import Entry, HomepageCurrator, Home +from ..models import Post, PostType +from locations.models import LuxCheckIn, Country, Region, Location +from sightings.models import Sighting + + +class JrnlListView(PaginatedListView): + """ + Return a list of Entries in reverse chronological order + """ + model = Post + template_name = "posts/jrnl_list.html" + queryset = Post.objects.filter(post_type=PostType.JRNL).filter(status__exact=1).order_by('-pub_date').prefetch_related('location').prefetch_related('featured_image') + + def get_context_data(self, **kwargs): + context = super(JrnlListView, self).get_context_data(**kwargs) + context['breadcrumbs'] = ['jrnl',] + return context + +class JrnlCountryListView(PaginatedListView): + """ + Return a list of Entries by Country in reverse chronological order + """ + model = Post + template_name = "posts/jrnl_list.html" + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(JrnlCountryListView, self).get_context_data(**kwargs) + try: + context['region'] = Country.objects.get(slug__exact=self.kwargs['slug']) + except: + context['region'] = Region.objects.get(slug__exact=self.kwargs['slug']) + context['breadcrumbs'] = ['jrnl',] + return context + + def get_queryset(self): + try: + region = Country.objects.get(slug__exact=self.kwargs['slug']) + qs = Post.objects.filter( + post_type=PostType.JRNL, + status__exact=1, + location__state__country=region + ).order_by('-pub_date') + except: + region = Region.objects.get(slug__exact=self.kwargs['slug']) + qs = Post.objects.filter( + post_type=PostType.JRNL, + status__exact=1, + location__state__country__lux_region=region.id + ).order_by('-pub_date') + return qs + + +class JrnlYearArchiveView(YearArchiveView): + queryset = Post.objects.filter(status__exact=1).filter(post_type=PostType.JRNL).select_related() + date_field = "pub_date" + make_object_list = True + allow_future = True + template_name = "posts/jrnl_date.html" + + +class JrnlMonthArchiveView(MonthArchiveView): + queryset = Post.objects.filter(status__exact=1).filter(post_type=PostType.JRNL).select_related() + date_field = "pub_date" + allow_future = True + template_name = "posts/jrnl_date.html" + + +class JrnlDetailView(DateDetailView): + model = Post + date_field = 'pub_date' + slug_field = "slug" + template_name = "posts/jrnl_detail.html" + + def get_queryset(self): + queryset = super(JrnlDetailView, self).get_queryset() + return queryset.filter(post_type=PostType.JRNL).select_related('location').prefetch_related('field_notes').prefetch_related('books') + + def get_object(self, queryset=None): + obj = get_object_or_404( + self.model, + slug=self.kwargs['slug'], + pub_date__month=self.kwargs['month'], + pub_date__year=self.kwargs['year'] + ) + self.location = obj.location + return obj + + def get_context_data(self, **kwargs): + context = super(JrnlDetailView, self).get_context_data(**kwargs) + context['wildlife'] = Sighting.objects.filter( + Q(location=self.location) | + Q(location__in=Location.objects.filter(parent=self.location)) + ).select_related().order_by('ap_id', 'ap__apclass__kind').distinct("ap") + related = [] + for obj in self.object.related.all(): + 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 + + +class JrnlDetailViewTXT(JrnlDetailView): + template_name = "posts/jrnl_detail.txt" + + +class JrnlLatestView(JrnlDetailView): + template_name = "details/entry_latest.html" + + def get_object(self, queryset=None): + obj = self.model.objects.filter(status=1).latest() + self.location = obj.location + return obj + + +class JrnlRSSFeedView(Feed): + title = "Luxagraf: Topographical Writings" + link = "/jrnl/" + description = "Latest postings to luxagraf.net" + description_template = 'feeds/blog_description.html' + + def items(self): + return Post.objects.filter(status__exact=1).filter(post_type=PostType.JRNL).order_by('-pub_date')[:10] + + def item_pubdate(self, item): + """ + Takes an item, as returned by items(), and returns the item's + pubdate. + """ + return item.pub_date + +''' +class HomepageList(ListView): + """ + Return a main entry and list of Entries in reverse chronological order + """ + model = Entry + + def get_home(self): + return Home.objects.filter(pk=1).prefetch_related('featured_image').select_related('featured').select_related('featured__location').get() + + def get_queryset(self): + queryset = super(HomepageList, self).get_queryset() + self.home = self.get_home() + return queryset.filter(status__exact=1).order_by('-pub_date').exclude().select_related('location').select_related('featured_image')[1:9] + + def get_template_names(self): + return ['%s' % self.home.template_name] + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(HomepageList, self).get_context_data(**kwargs) + context['homepage'] = self.home + context['location'] = LuxCheckIn.objects.latest() + context['IMAGES_URL'] = settings.IMAGES_URL + return context +''' diff --git a/app/utils/util.py b/app/utils/util.py index 93ae5b1..dc04b0b 100644 --- a/app/utils/util.py +++ b/app/utils/util.py @@ -53,9 +53,11 @@ def extract_main_image(markdown): def parse_products(s): soup = BeautifulSoup(s.group(), "lxml") for div in soup.find_all('div'): - p = apps.get_model('products', 'Product').objects.get(pk=int(div['id'].split("product-")[1])) - print(p.get_full_name()) - return render_to_string("products/snippet.html", {'object': p}) + try: + p = apps.get_model('products', 'Product').objects.get(pk=int(div['id'].split("product-")[1])) + return render_to_string("products/snippet.html", {'object': p}) + except KeyError: + return str(s) def parse_image(s): @@ -67,7 +69,7 @@ def parse_image(s): replacer = "[[base_url]]" if replacer in str(img): s = str(img).replace('[[base_url]]', settings.IMAGES_URL) - print(s) + #print(s) return s else: try: diff --git a/config/base_urls.py b/config/base_urls.py index 989a876..169b7f4 100644 --- a/config/base_urls.py +++ b/config/base_urls.py @@ -6,12 +6,12 @@ from django.contrib.sitemaps.views import sitemap from django.views.generic.base import RedirectView from pages.views import PageDetailView, PageDetailTXTView -from jrnl.models import BlogSitemap from jrnl.views import HomepageList from locations.models import WritingbyCountrySitemap from photos.models import PhotoGallerySitemap from books.models import BookSitemap from posts.models import PostSitemap +from pages.models import PageSitemap import builder.views import utils.views import products.views @@ -23,8 +23,8 @@ from posts.views import PostRSSFeedView admin.autodiscover() sitemaps = { - 'blog': BlogSitemap, 'posts': PostSitemap, + 'pages': PageSitemap, 'writingbyloc': WritingbyCountrySitemap, 'books': BookSitemap, } @@ -41,7 +41,8 @@ urlpatterns = [ path(r'sitemap.xml', sitemap, {'sitemaps': sitemaps}), path(r'links/', include('links.urls')), path(r'newsletter/', include('lttr.urls')), - path(r'jrnl/', include('jrnl.urls')), + #path(r'jrnl/', include('jrnl.urls')), + path(r'jrnl/', include('posts.urls.jrnl_urls', namespace='jrnl')), #path(r'projects/', include('projects.urls')), path(r'topics/', include('taxonomy.urls')), path(r'walk/', include('locations.walk_urls')), diff --git a/design/templates/base.html b/design/templates/base.html index f3b6e79..0098e7f 100644 --- a/design/templates/base.html +++ b/design/templates/base.html @@ -34,7 +34,7 @@ <ul> <li><a href="{% url "jrnl:list" %}" title="Stories of life on the road.">Jrnl</a> & <a href="{% url "fieldnotes:list" %}" title="Short stories, snapshots of daily life on the road.">Field Notes</a></li> <!--<li><a href="{% url "guide:guide-base" %}" title="Advice, Tools, Tips and Tricks for Full Time Van or RV Life.">Guides</a></li>--> - <li><a href="/newsletter/" title="The 'friends of a long year' newsletter">newsletter</a></li> + <li><a href="/newsletter/friends/" title="The 'friends of a long year' newsletter">newsletter</a></li> <li><a href="/about" title="About Scott">About</a></li> </ul> </nav> |