diff options
-rw-r--r-- | app/notes/admin.py | 34 | ||||
-rw-r--r-- | app/notes/migrations/0001_initial.py | 63 | ||||
-rw-r--r-- | app/notes/migrations/0002_auto_20160208_1107.py | 20 | ||||
-rw-r--r-- | app/notes/migrations/0003_auto_20160208_1120.py | 33 | ||||
-rw-r--r-- | app/notes/migrations/__init__.py | 0 | ||||
-rw-r--r-- | app/notes/models.py | 58 | ||||
-rw-r--r-- | app/notes/urls.py | 28 | ||||
-rw-r--r-- | app/notes/views.py | 33 | ||||
-rw-r--r-- | app/utils/widgets.py | 7 | ||||
-rw-r--r-- | config/base_urls.py | 5 | ||||
-rw-r--r-- | design/templates/admin/notes/change_form.html | 19 | ||||
-rw-r--r-- | design/templates/archives/notes.html | 6 | ||||
-rw-r--r-- | design/templates/details/note.html | 6 |
13 files changed, 291 insertions, 21 deletions
diff --git a/app/notes/admin.py b/app/notes/admin.py index 794e882..3e15be2 100644 --- a/app/notes/admin.py +++ b/app/notes/admin.py @@ -1,19 +1,37 @@ from django.contrib import admin from django.contrib.gis.admin import OSMGeoAdmin -from notes.models import Note -from django import forms +from notes.models import Note, LuxNote +from utils.widgets import AdminImageWidget, LGEntryForm, LGEntryFormSmall, OLAdminBase -class NoteModelForm(forms.ModelForm): - body_markdown = forms.CharField(widget=forms.Textarea(attrs={'maxlength': 40000, 'rows': 20, 'cols': 75}), label='Note') - class Meta: - model = Note - fields = '__all__' +class LuxNoteAdmin(OLAdminBase): + form = LGEntryFormSmall + prepopulated_fields = {"slug": ('title',)} + list_display = ('slug', 'pub_date', 'location') + fieldsets = ( + ('Note', { + 'fields': ( + ('title', 'slug'), + 'body_markdown', + 'pub_date', + 'point' + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + } + ), + ) + + +admin.site.register(LuxNote, LuxNoteAdmin) class NoteAdmin(OSMGeoAdmin): - form = NoteModelForm + form = LGEntryForm list_display = ('slug', 'date_created', 'location', 'twitter_id') list_filter = ('location',) prepopulated_fields = {"slug": ('title',)} diff --git a/app/notes/migrations/0001_initial.py b/app/notes/migrations/0001_initial.py new file mode 100644 index 0000000..cf8396a --- /dev/null +++ b/app/notes/migrations/0001_initial.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-02-08 10:57 +from __future__ import unicode_literals + +import django.contrib.gis.db.models.fields +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('locations', '__first__'), + ] + + operations = [ + migrations.CreateModel( + name='LuxNote', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(blank=True, max_length=250, null=True)), + ('slug', models.SlugField(blank=True, unique_for_date='date_created')), + ('date_created', models.DateTimeField(editable=False)), + ('date_last_updated', models.DateTimeField(blank=True, verbose_name='Date')), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField(verbose_name='Note')), + ], + ), + migrations.CreateModel( + name='Note', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(blank=True, max_length=250, null=True)), + ('slug', models.SlugField(blank=True, unique_for_date='date_created')), + ('date_created', models.DateTimeField(blank=True, verbose_name='Date')), + ('date_last_updated', models.DateTimeField(blank=True, verbose_name='Date')), + ('point', django.contrib.gis.db.models.fields.PointField(srid=4326)), + ('city_name', models.CharField(blank=True, max_length=250, null=True)), + ('state_name', models.CharField(blank=True, max_length=250, null=True)), + ('country_name', models.CharField(blank=True, max_length=150, null=True)), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField(verbose_name='Note')), + ('twitter_text', models.CharField(blank=True, max_length=450, null=True, verbose_name='Twitter text')), + ('twitter_id', models.CharField(max_length=450, verbose_name='twitter_id')), + ('twitter_send', models.BooleanField(default=False, verbose_name='send to twitter?')), + ('twitter_sent', models.BooleanField(default=False)), + ('location', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Location')), + ], + ), + migrations.CreateModel( + name='OriginNoteForReplies', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date_created', models.DateTimeField()), + ('profile_image', models.CharField(blank=True, max_length=450, null=True)), + ('screen_name', models.CharField(blank=True, max_length=75, null=True)), + ('body_html', models.TextField(blank=True)), + ('remote_url', models.CharField(blank=True, max_length=450, null=True)), + ], + ), + ] diff --git a/app/notes/migrations/0002_auto_20160208_1107.py b/app/notes/migrations/0002_auto_20160208_1107.py new file mode 100644 index 0000000..3333a34 --- /dev/null +++ b/app/notes/migrations/0002_auto_20160208_1107.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-02-08 11:07 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('notes', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='luxnote', + old_name='date_created', + new_name='pub_date', + ), + ] diff --git a/app/notes/migrations/0003_auto_20160208_1120.py b/app/notes/migrations/0003_auto_20160208_1120.py new file mode 100644 index 0000000..ccdf46f --- /dev/null +++ b/app/notes/migrations/0003_auto_20160208_1120.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-02-08 11:20 +from __future__ import unicode_literals + +import django.contrib.gis.db.models.fields +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('locations', '__first__'), + ('notes', '0002_auto_20160208_1107'), + ] + + operations = [ + migrations.AddField( + model_name='luxnote', + name='location', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='locations.Location'), + ), + migrations.AddField( + model_name='luxnote', + name='point', + field=django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326), + ), + migrations.AlterField( + model_name='luxnote', + name='slug', + field=models.SlugField(blank=True, unique_for_date='pub_date'), + ), + ] diff --git a/app/notes/migrations/__init__.py b/app/notes/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/notes/migrations/__init__.py diff --git a/app/notes/models.py b/app/notes/models.py index 6d5e805..775c78c 100644 --- a/app/notes/models.py +++ b/app/notes/models.py @@ -3,6 +3,7 @@ import datetime from django.contrib.gis.db import models from django.template.defaultfilters import slugify from django.utils.html import urlize +from django.utils import timezone from django.db.models.signals import post_save from django.dispatch import receiver from django.conf import settings @@ -14,10 +15,67 @@ from twython import Twython import markdown #from twitter_text.autolink import Autolink +from utils.widgets import markdown_to_html +from daily.models import CheckIn + + def twitter_truncate(txt): return txt.split("|")[0] +class LuxNote(models.Model): + title = models.CharField(max_length=250, null=True, blank=True) + slug = models.SlugField(unique_for_date='pub_date', blank=True) + pub_date = models.DateTimeField(default=timezone.now) + date_last_updated = models.DateTimeField('Date', blank=True) + body_html = models.TextField(blank=True) + body_markdown = models.TextField('Note') + point = models.PointField(blank=True, null=True) + location = models.ForeignKey(Location, blank=True, null=True) + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse("notes:detail", kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) + + @property + def region(self): + return self.location.state.country.lux_region + + @property + def longitude(self): + '''Get the site's longitude.''' + return round(self.point.x, 2) + + @property + def latitude(self): + '''Get the site's latitude.''' + return round(self.point.y, 2) + + @property + def get_previous_published(self): + return self.get_previous_by_pub_date() + + @property + def get_next_published(self): + return self.get_next_by_pub_date() + + + def save(self, *args, **kwargs): + self.body_html = markdown_to_html(self.body_markdown) + if not self.point: + self.point = CheckIn.objects.latest().point + try: + self.location = Location.objects.filter(geometry__contains=self.point).get() + except Location.DoesNotExist: + raise forms.ValidationError("There is no location associated with that point, add it: %sadmin/locations/location/add/" % (settings.BASE_URL)) + if not self.id: + self.pub_date= timezone.now() + self.date_last_updated = timezone.now() + super(LuxNote, self).save() + + class Note(models.Model): title = models.CharField(max_length=250, null=True, blank=True) slug = models.SlugField(unique_for_date='date_created', blank=True) diff --git a/app/notes/urls.py b/app/notes/urls.py index 3f46915..00a8cce 100644 --- a/app/notes/urls.py +++ b/app/notes/urls.py @@ -1,4 +1,5 @@ from django.conf.urls import url +from django.views.generic.base import RedirectView from . import views @@ -6,9 +7,23 @@ app_name = "notes" urlpatterns = [ url( + r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+).txt$', + views.NoteDetailViewTXT.as_view(), + name="detail-txt" + ), + url( + r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+).amp$', + views.NoteDetailViewAMP.as_view(), + name="detail-amp" + ), + url( r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+)$', - views.entry_detail + views.NoteDetailView.as_view(), + name="detail" ), + + + url( r'(?P<year>\d{4})/(?P<month>\d{2})/$', views.date_list, @@ -20,6 +35,17 @@ urlpatterns = [ name="notes_by_year" ), url( + r'(?P<page>\d+)/$', + views.NoteList.as_view(), + name="list" + ), + # redirect / to /1/ for live server + url( + r'', + RedirectView.as_view(url="/field-notes/1/", permanent=False), + name="live_redirect" + ), + url( r'^$', views.entry_list, name="notes_archive" diff --git a/app/notes/views.py b/app/notes/views.py index e89087e..b8bc04e 100644 --- a/app/notes/views.py +++ b/app/notes/views.py @@ -1,6 +1,37 @@ from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext -from notes.models import Note +from django.views.generic.detail import DetailView + +from utils.views import PaginatedListView + +from notes.models import LuxNote, Note + + +class NoteList(PaginatedListView): + """ + Return a list of Notes in reverse chronological order + """ + queryset = LuxNote.objects.all().order_by('-pub_date') + template_name = "archives/notes.html" + + +class NoteDetailView(DetailView): + model = LuxNote + template_name = "details/note.html" + slug_field = "slug" + + +class NoteDetailViewTXT(NoteDetailView): + template_name = "details/entry.txt" + + +class NoteDetailViewAMP(NoteDetailView): + template_name = "details/entry.amp" + + +""" +Legacy Notes views +""" def entry_detail(request, year, month, slug): diff --git a/app/utils/widgets.py b/app/utils/widgets.py index 6d6a334..290c7ab 100644 --- a/app/utils/widgets.py +++ b/app/utils/widgets.py @@ -90,10 +90,15 @@ class AdminImageWidget(AdminFileWidget): class LGEntryForm(forms.ModelForm): class Meta: widgets = { - 'body_markdown': forms.Textarea(attrs={'rows': 50, 'cols': 100}), + 'body_markdown': forms.Textarea(attrs={'rows': 40, 'cols': 100}), } +class LGEntryFormSmall(forms.ModelForm): + class Meta: + widgets = { + 'body_markdown': forms.Textarea(attrs={'rows': 12, 'cols': 100}), + } class OLAdminBase(OSMGeoAdmin): default_lon = -9285175 default_lat = 4025046 diff --git a/config/base_urls.py b/config/base_urls.py index b5ee0db..122dfd1 100644 --- a/config/base_urls.py +++ b/config/base_urls.py @@ -46,10 +46,7 @@ urlpatterns += [ url(r'^expenses/', include('expenses.urls', namespace='expenses')), url(r'^photos/', include('photos.urls')), url(r'^books/', include('books.urls')), - url( - r'^field-notes/', - include('notes.urls', namespace='notes') - ), + url(r'^field-notes/', include('notes.urls')), url( r'^birds/', include('birds.urls', namespace='birds') diff --git a/design/templates/admin/notes/change_form.html b/design/templates/admin/notes/change_form.html new file mode 100644 index 0000000..3d97a4f --- /dev/null +++ b/design/templates/admin/notes/change_form.html @@ -0,0 +1,19 @@ +{% extends "admin/change_form.html" %} +{% load i18n admin_urls %} +{% block content %} + <a class="btn" onclick="geoFindMe();" href="javascript:void(0);" class="historylink">Get Location</a> + {{block.super}} +{% endblock %} +{% block object-tools-items %} + <li> + <a onclick="geoFindMe();" href="javascript:void(0);" class="historylink">Get Location</a> + </li> + <li> + <a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% trans "History" %}</a> + </li> + {% if has_absolute_url %} + <li> + <a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% trans "View on site" %}</a> + </li> + {% endif %} +{% endblock %} diff --git a/design/templates/archives/notes.html b/design/templates/archives/notes.html index 4ee5269..ed2a7be 100644 --- a/design/templates/archives/notes.html +++ b/design/templates/archives/notes.html @@ -16,7 +16,7 @@ <article class="h-entry"> <h2 class="p-name note--title">{{object.title|safe|amp|smartypants}}</h2> <div class="e-content"> - {{object.render|safe|amp|smartypants|urlizetrunc:45 }} + {{object.body_html|safe|amp|smartypants|urlizetrunc:45 }} </div> <span class="p-author h-card"> <data class="p-name" value="Scott Gilbertson"></data> @@ -24,11 +24,11 @@ </span> <footer> <p class="note--date"> - <a class="u-url" href="{{object.get_absolute_url}}" rel="bookmark"><time class="dt-published" datetime="{{object.date_created|html5_datetime}}">{{object.date_created|date:"F j, Y"}}</time></a> + <a class="u-url" href="{{object.get_absolute_url}}" rel="bookmark"><time class="dt-published" datetime="{{object.pub_date|html5_datetime}}">{{object.pub_date|date:"F j, Y"}}</time></a> </p>{% if object.location %} <p class="p-location h-adr note--location bl" itemprop="geo" itemscope itemtype="http://data-vocabulary.org/Geo"> <span class="p-locality">{{object.location.name|smartypants|safe}}</span>, - <span class="p-region">{{object.state_name}}</span>, + <span class="p-region">{{object.location.state.name}}</span>, <span class="p-country-name">{{object.location.state.country.name}}</span> <data class="p-latitude" value="{{object.latitude}}"></data> <data class="p-longitude" value="{{object.longitude}}"></data> diff --git a/design/templates/details/note.html b/design/templates/details/note.html index 87a1e25..269d82a 100644 --- a/design/templates/details/note.html +++ b/design/templates/details/note.html @@ -20,7 +20,7 @@ <article class="h-entry"> <h1 class="p-name note--title hide">{{object.title|safe|amp|smartypants}}</h1> <div class="e-content"> - {{object.render|safe|amp|smartypants|urlizetrunc:45 }} + {{object.body_html|safe|amp|smartypants}} </div> <span class="p-author h-card"> <data class="p-name" value="Scott Gilbertson"></data> @@ -28,11 +28,11 @@ </span> <footer class="note--footer"> <p class="note--date"> - <a class="u-url" href="{{object.get_absolute_url}}" rel="bookmark"><time class="dt-published" datetime="{{object.date_created|html5_datetime}}">{{object.date_created|date:"F j, Y"}}</time></a> + <a class="u-url" href="{{object.get_absolute_url}}" rel="bookmark"><time class="dt-published" datetime="{{object.pub_date|html5_datetime}}">{{object.pub_date|date:"F j, Y"}}</time></a> </p>{% if object.location %} <p class="p-location h-adr note--location bl" itemprop="geo" itemscope itemtype="http://data-vocabulary.org/Geo"> <span class="p-locality">{{object.location.name|smartypants|safe}}</span>, - <span class="p-region">{{object.state_name}}</span>, + <span class="p-region">{{object.location.state}}</span>, <span class="p-country-name">{{object.location.state.country.name}}</span> <data class="p-latitude" value="{{object.latitude}}"></data> <data class="p-longitude" value="{{object.longitude}}"></data> |