summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2023-11-15 17:08:29 -0500
committerluxagraf <sng@luxagraf.net>2023-11-15 17:08:29 -0500
commit5d26ed7dbba5475a93b70c450741b358153b0855 (patch)
tree8c9dcdb2bb1735e787cb0753215898b17e92f062
parent9f1c7ef8a47ee1a2df40ce1f57df105af8b99cc1 (diff)
gtd: rolled in wired stuff plus created my own gtd app
-rw-r--r--app/gtd/__init__.py0
-rw-r--r--app/gtd/forms.py66
-rw-r--r--app/gtd/migrations/0001_initial.py71
-rw-r--r--app/gtd/migrations/0002_alter_gtdnote_reminder.py18
-rw-r--r--app/gtd/migrations/0003_alter_gtdnote_date_completed.py18
-rw-r--r--app/gtd/migrations/0004_remove_gtdnote_slug_remove_gtdoutcome_slug_and_more.py30
-rw-r--r--app/gtd/migrations/0005_wiredpost.py35
-rw-r--r--app/gtd/migrations/0006_remove_gtdoutcome_featured_image_wirednote.py35
-rw-r--r--app/gtd/migrations/0007_alter_wiredpost_date_last_pub.py19
-rw-r--r--app/gtd/migrations/0008_alter_wiredpost_date_last_pub.py19
-rw-r--r--app/gtd/migrations/__init__.py0
-rw-r--r--app/gtd/models.py232
-rw-r--r--app/gtd/templates/gtd/note_form.html35
-rw-r--r--app/gtd/templates/gtd/note_list.html23
-rw-r--r--app/gtd/templates/gtd/post_list.html25
-rw-r--r--app/gtd/templates/gtd/post_table.html93
-rw-r--r--app/gtd/templates/gtd/project_detail.html17
-rw-r--r--app/gtd/templates/gtd/project_form.html35
-rw-r--r--app/gtd/templates/gtd/project_list.html23
-rw-r--r--app/gtd/templates/gtd/wirednote_form.html26
-rw-r--r--app/gtd/templates/gtd/wirednote_list.html23
-rw-r--r--app/gtd/templates/gtd/wiredpost_detail.html21
-rw-r--r--app/gtd/templates/gtd/wiredpost_form.html16
-rw-r--r--app/gtd/urls.py101
-rw-r--r--app/gtd/views.py221
-rw-r--r--config/base_urls.py1
-rw-r--r--templates/base_gtd.html48
27 files changed, 1251 insertions, 0 deletions
diff --git a/app/gtd/__init__.py b/app/gtd/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/gtd/__init__.py
diff --git a/app/gtd/forms.py b/app/gtd/forms.py
new file mode 100644
index 0000000..a4727cf
--- /dev/null
+++ b/app/gtd/forms.py
@@ -0,0 +1,66 @@
+from django.forms import ModelForm
+from django.forms import ChoiceField
+
+from .models import GTDNote, GTDProject, WiredNote, WiredPost
+
+
+class GTDNoteCreateForm(ModelForm):
+ class Meta:
+ model = GTDNote
+ fields = ['title', 'body_markdown', 'project', 'note_type', 'reminder', 'status']
+
+
+class GTDNoteEditForm(ModelForm):
+ class Meta:
+ model = GTDNote
+ fields = ['title', 'body_markdown', 'project', 'note_type', 'reminder', 'status']
+
+
+class GTDProjectCreateForm(ModelForm):
+ class Meta:
+ model = GTDProject
+ fields = ['title', 'body_markdown', 'date_goal', 'project_type', 'outcome']
+
+
+class GTDProjectUpdateForm(ModelForm):
+ class Meta:
+ model = GTDProject
+ fields = ['title', 'body_markdown', 'date_goal', 'project_type', 'outcome', 'date_ended']
+
+
+class WiredNoteCreateForm(ModelForm):
+
+ def __init__(self,*args,**kwargs):
+ user = kwargs.pop('user')
+ self.user = user
+ super(WiredNoteCreateForm,self).__init__(*args,**kwargs)
+ self.fields['post'].required = False
+
+ def save(self, commit=True):
+ self.instance.user = self.user
+ return super().save(commit=commit)
+
+ class Meta:
+ model = WiredNote
+ fields = ['title', 'url', 'body_markdown', 'post']
+
+
+class WiredNoteEditForm(ModelForm):
+
+ def __init__(self,*args,**kwargs):
+ super(WiredNoteEditForm,self).__init__(*args,**kwargs)
+ self.fields['post'].queryset = WiredPost.objects.all().order_by("title")
+
+ def save(self, commit=True):
+ return super().save(commit=commit)
+
+ class Meta:
+ model = WiredNote
+ fields = ['title', 'url', 'body_markdown', 'post', 'status', 'plan']
+
+
+class WiredPostUpdateForm(ModelForm):
+
+ class Meta:
+ model = WiredPost
+ fields = ['title', 'post_status', 'url', 'template_type', 'update_frequency', 'edit_url', 'date_last_pub']
diff --git a/app/gtd/migrations/0001_initial.py b/app/gtd/migrations/0001_initial.py
new file mode 100644
index 0000000..9df3dc9
--- /dev/null
+++ b/app/gtd/migrations/0001_initial.py
@@ -0,0 +1,71 @@
+# Generated by Django 4.2.7 on 2023-11-14 09:18
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('media', '0008_auto_20201202_1155'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='GTDOutcome',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=300)),
+ ('slug', models.SlugField()),
+ ('body_markdown', models.TextField()),
+ ('body_html', models.TextField(blank=True)),
+ ('date_goal', models.DateField()),
+ ('date_ended', models.DateField()),
+ ('featured_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='media.luximage')),
+ ],
+ options={
+ 'ordering': ('-date_goal',),
+ },
+ ),
+ migrations.CreateModel(
+ name='GTDProject',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=200)),
+ ('short_title', models.CharField(blank=True, max_length=200, null=True)),
+ ('slug', models.SlugField()),
+ ('body_markdown', models.TextField(blank=True, null=True)),
+ ('body_html', models.TextField(blank=True)),
+ ('date_goal', models.DateField(blank=True, null=True)),
+ ('date_ended', models.DateField(blank=True, null=True)),
+ ('project_type', models.IntegerField(choices=[(0, 'wired'), (1, 'lbh'), (2, 'personal')], default=0)),
+ ('outcome', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='gtd.gtdoutcome')),
+ ],
+ options={
+ 'ordering': ('-date_goal',),
+ 'get_latest_by': 'date_goal',
+ },
+ ),
+ migrations.CreateModel(
+ name='GTDNote',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=200)),
+ ('slug', models.SlugField()),
+ ('body_markdown', models.TextField()),
+ ('body_html', models.TextField(blank=True)),
+ ('date_completed', models.DateField()),
+ ('date_created', models.DateTimeField(auto_now=True)),
+ ('note_type', models.IntegerField(choices=[(0, 'action'), (1, 'reminder'), (2, 'reference')], default=0)),
+ ('reminder', models.BigIntegerField(help_text='In days')),
+ ('status', models.IntegerField(choices=[(0, 'None'), (1, 'Open'), (2, 'Completed')], default=0)),
+ ('project', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='gtd.gtdproject')),
+ ],
+ options={
+ 'ordering': ('-date_created',),
+ 'get_latest_by': 'date_created',
+ },
+ ),
+ ]
diff --git a/app/gtd/migrations/0002_alter_gtdnote_reminder.py b/app/gtd/migrations/0002_alter_gtdnote_reminder.py
new file mode 100644
index 0000000..c626625
--- /dev/null
+++ b/app/gtd/migrations/0002_alter_gtdnote_reminder.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.7 on 2023-11-14 09:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gtd', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='gtdnote',
+ name='reminder',
+ field=models.BigIntegerField(blank=True, help_text='In days', null=True),
+ ),
+ ]
diff --git a/app/gtd/migrations/0003_alter_gtdnote_date_completed.py b/app/gtd/migrations/0003_alter_gtdnote_date_completed.py
new file mode 100644
index 0000000..67eeffd
--- /dev/null
+++ b/app/gtd/migrations/0003_alter_gtdnote_date_completed.py
@@ -0,0 +1,18 @@
+# Generated by Django 4.2.7 on 2023-11-14 09:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gtd', '0002_alter_gtdnote_reminder'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='gtdnote',
+ name='date_completed',
+ field=models.DateField(blank=True, null=True),
+ ),
+ ]
diff --git a/app/gtd/migrations/0004_remove_gtdnote_slug_remove_gtdoutcome_slug_and_more.py b/app/gtd/migrations/0004_remove_gtdnote_slug_remove_gtdoutcome_slug_and_more.py
new file mode 100644
index 0000000..e706ab8
--- /dev/null
+++ b/app/gtd/migrations/0004_remove_gtdnote_slug_remove_gtdoutcome_slug_and_more.py
@@ -0,0 +1,30 @@
+# Generated by Django 4.2.7 on 2023-11-14 14:03
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gtd', '0003_alter_gtdnote_date_completed'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='gtdnote',
+ name='slug',
+ ),
+ migrations.RemoveField(
+ model_name='gtdoutcome',
+ name='slug',
+ ),
+ migrations.RemoveField(
+ model_name='gtdproject',
+ name='slug',
+ ),
+ migrations.AlterField(
+ model_name='gtdproject',
+ name='project_type',
+ field=models.IntegerField(choices=[(0, 'Wired'), (1, 'LBH'), (2, 'Personal')], default=0),
+ ),
+ ]
diff --git a/app/gtd/migrations/0005_wiredpost.py b/app/gtd/migrations/0005_wiredpost.py
new file mode 100644
index 0000000..ec97830
--- /dev/null
+++ b/app/gtd/migrations/0005_wiredpost.py
@@ -0,0 +1,35 @@
+# Generated by Django 4.2.7 on 2023-11-15 13:45
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gtd', '0004_remove_gtdnote_slug_remove_gtdoutcome_slug_and_more'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='WiredPost',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(blank=True, max_length=512, null=True)),
+ ('body', models.TextField(blank=True, null=True)),
+ ('url', models.CharField(blank=True, max_length=512, null=True)),
+ ('edit_url', models.CharField(blank=True, max_length=512, null=True)),
+ ('date_last_pub', models.DateField()),
+ ('guid', models.CharField(blank=True, db_index=True, max_length=512, null=True)),
+ ('author', models.CharField(blank=True, max_length=255, null=True)),
+ ('post_type', models.IntegerField(choices=[(0, 'review'), (1, 'guide'), (2, 'how-to')], default=1)),
+ ('template_type', models.IntegerField(choices=[(0, 'story'), (1, 'gallery')], default=0)),
+ ('update_frequency', models.BigIntegerField(help_text='In days')),
+ ('needs_update', models.BooleanField(default=False)),
+ ('is_live', models.BooleanField(default=True)),
+ ('post_status', models.IntegerField(choices=[(0, 'Assigned'), (1, 'turned in'), (2, 'published')], default=2)),
+ ],
+ options={
+ 'ordering': ('date_last_pub',),
+ },
+ ),
+ ]
diff --git a/app/gtd/migrations/0006_remove_gtdoutcome_featured_image_wirednote.py b/app/gtd/migrations/0006_remove_gtdoutcome_featured_image_wirednote.py
new file mode 100644
index 0000000..a301f26
--- /dev/null
+++ b/app/gtd/migrations/0006_remove_gtdoutcome_featured_image_wirednote.py
@@ -0,0 +1,35 @@
+# Generated by Django 4.2.7 on 2023-11-15 13:54
+
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gtd', '0005_wiredpost'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='gtdoutcome',
+ name='featured_image',
+ ),
+ migrations.CreateModel(
+ name='WiredNote',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=400)),
+ ('url', models.CharField(blank=True, max_length=400, null=True)),
+ ('body_markdown', models.TextField(blank=True, null=True)),
+ ('date_created', models.DateTimeField(default=django.utils.timezone.now)),
+ ('status', models.IntegerField(choices=[(0, 'Call In'), (1, 'Asked For'), (2, 'Coming'), (3, 'Testing'), (4, 'Done'), (5, 'Live')], default=0)),
+ ('plan', models.IntegerField(choices=[(0, 'For Guide'), (1, 'Review'), (2, 'Rave/Rant'), (3, 'No Plan')], default=0)),
+ ('post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='gtd.wiredpost')),
+ ],
+ options={
+ 'ordering': ('date_created', 'status'),
+ },
+ ),
+ ]
diff --git a/app/gtd/migrations/0007_alter_wiredpost_date_last_pub.py b/app/gtd/migrations/0007_alter_wiredpost_date_last_pub.py
new file mode 100644
index 0000000..b2f113c
--- /dev/null
+++ b/app/gtd/migrations/0007_alter_wiredpost_date_last_pub.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.2.7 on 2023-11-15 15:01
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gtd', '0006_remove_gtdoutcome_featured_image_wirednote'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='wiredpost',
+ name='date_last_pub',
+ field=models.DateField(default=datetime.datetime.now),
+ ),
+ ]
diff --git a/app/gtd/migrations/0008_alter_wiredpost_date_last_pub.py b/app/gtd/migrations/0008_alter_wiredpost_date_last_pub.py
new file mode 100644
index 0000000..a76d230
--- /dev/null
+++ b/app/gtd/migrations/0008_alter_wiredpost_date_last_pub.py
@@ -0,0 +1,19 @@
+# Generated by Django 4.2.7 on 2023-11-15 15:02
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('gtd', '0007_alter_wiredpost_date_last_pub'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='wiredpost',
+ name='date_last_pub',
+ field=models.DateField(default=datetime.datetime(2023, 11, 15, 15, 2, 22, 531344)),
+ ),
+ ]
diff --git a/app/gtd/migrations/__init__.py b/app/gtd/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/gtd/migrations/__init__.py
diff --git a/app/gtd/models.py b/app/gtd/models.py
new file mode 100644
index 0000000..e021b42
--- /dev/null
+++ b/app/gtd/models.py
@@ -0,0 +1,232 @@
+import datetime
+import os
+
+from django.utils import timezone
+from django.contrib.gis.db import models
+from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.sites.models import Site
+from django.urls import reverse
+from django.apps import apps
+from django.conf import settings
+from django.contrib.sitemaps import Sitemap
+
+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 GTDOutcome(models.Model):
+ title = models.CharField(max_length=300)
+ body_markdown = models.TextField()
+ body_html = models.TextField(blank=True)
+ date_goal = models.DateField()
+ date_ended = models.DateField()
+
+ def __str__(self):
+ return self.title
+
+ class Meta:
+ ordering = ('-date_goal',)
+
+ def get_absolute_url(self):
+ return reverse('gtd:outcome', kwargs={"slug": self.slug})
+
+ def save(self, *args, **kwargs):
+ created = self.pk is None
+ if not created:
+ md = render_images(self.body_markdown)
+ self.body_html = markdown_to_html(md)
+ super(Outcome, self).save(*args, **kwargs)
+
+
+class ProjectType(models.IntegerChoices):
+ WIRED = 0, ('Wired')
+ LBH = 1, ('LBH')
+ PERSONAL = 2, ('Personal')
+
+
+class GTDProject(models.Model):
+ title = models.CharField(max_length=200)
+ short_title = models.CharField(max_length=200, blank=True, null=True)
+ body_markdown = models.TextField(null=True, blank=True)
+ body_html = models.TextField(blank=True)
+ date_goal = models.DateField(blank=True, null=True)
+ date_ended = models.DateField(blank=True, null=True)
+ project_type = models.IntegerField(choices=ProjectType.choices, default=ProjectType.WIRED)
+ outcome = models.ForeignKey(GTDOutcome, on_delete=models.SET_NULL, null=True, blank=True)
+
+ class Meta:
+ ordering = ('-date_goal',)
+ get_latest_by = 'date_goal'
+
+ def __str__(self):
+ return self.title
+
+ def get_absolute_url(self):
+ return reverse('gtd:project-detail', kwargs={"pk": self.id})
+
+ @property
+ def get_previous_admin_url(self):
+ n = self.get_previous_by_date_goal()
+ return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[n.id] )
+
+ @property
+ def get_next_admin_url(self):
+ model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name)
+ try:
+ return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[self.get_next_by_date_goal().pk] )
+ except model.DoesNotExist:
+ return ''
+
+ def save(self, *args, **kwargs):
+ created = self.pk is None
+ if not created:
+ md = render_images(self.body_markdown)
+ self.body_html = markdown_to_html(md)
+ super(GTDProject, self).save(*args, **kwargs)
+
+
+class NoteType(models.IntegerChoices):
+ ACTION = 0, ('action')
+ REMINDER = 1, ('reminder')
+ REFERENCE = 2, ('reference')
+
+
+class GTDNote(models.Model):
+ title = models.CharField(max_length=200)
+ body_markdown = models.TextField()
+ body_html = models.TextField(blank=True)
+ date_completed = models.DateField(null=True, blank=True)
+ date_created = models.DateTimeField(auto_now=True)
+ note_type = models.IntegerField(choices=NoteType.choices, default=NoteType.ACTION)
+ reminder = models.BigIntegerField(help_text="In days", null=True, blank=True)
+ project = models.ForeignKey(GTDProject, on_delete=models.SET_NULL, null=True, blank=True)
+ STATUS = (
+ (0, 'None'),
+ (1, 'Open'),
+ (2, 'Completed'),
+ )
+ status = models.IntegerField(choices=STATUS, default=0)
+
+ class Meta:
+ ordering = ('-date_created',)
+ get_latest_by = 'date_created'
+
+ def __str__(self):
+ return self.title
+
+ def get_absolute_url(self, *args, **kwargs):
+ return reverse('gtd:note-edit', kwargs={"pk": self.pk})
+
+ def save(self, *args, **kwargs):
+ self.body_html = markdown_to_html(self.body_markdown)
+ super(GTDNote, self).save(*args, **kwargs)
+
+
+class PostType(models.IntegerChoices):
+ REVIEW = 0, ('review')
+ GUIDE = 1, ('guide')
+ HOWTO = 2, ('how-to')
+
+
+class TemplateType(models.IntegerChoices):
+ STORY = 0, ('story')
+ GALLERY = 1, ('gallery')
+
+
+class PostStatus(models.IntegerChoices):
+ ASSIGNED = 0, ('Assigned')
+ TURNEDIN = 1, ('turned in')
+ PUBLISHED = 2, ('published')
+
+
+class WiredPost(models.Model):
+ # an entry in a feed
+ title = models.CharField(max_length=512, blank=True, null=True)
+ body = models.TextField(blank=True, null=True)
+ url = models.CharField(max_length=512, blank=True, null=True)
+ edit_url = models.CharField(max_length=512, blank=True, null=True)
+ date_last_pub = models.DateField(default=timezone.now())
+ guid = models.CharField(max_length=512, blank=True, null=True, db_index=True)
+ author = models.CharField(max_length=255, blank=True, null=True)
+ post_type = models.IntegerField(choices=PostType.choices, default=PostType.GUIDE)
+ template_type = models.IntegerField(choices=TemplateType.choices, default=TemplateType.STORY)
+ update_frequency = models.BigIntegerField(help_text="In days")
+ #products = models.ManyToManyField(ProductLink, blank=True, null=True)
+ needs_update = models.BooleanField(default=False)
+ is_live = models.BooleanField(default=True)
+ post_status = models.IntegerField(choices=PostStatus.choices, default=PostStatus.PUBLISHED)
+
+
+ class Meta:
+ ordering = ('date_last_pub',)
+
+ def __str__(self):
+ return self.title
+
+ def time_since_update(self):
+ td = timezone.localdate() - self.date_last_pub
+ return int(td.days)
+
+ #def get_needs_update(self):
+ # if self.time_since_update() > self.update_frequency:
+ # return True
+ # else:
+ # return False
+
+ def days_overdue(self):
+ if self.needs_update == True:
+ return self.time_since_update() - self.update_frequency
+ else:
+ return 0
+
+ def admin_url(self):
+ return format_html('<a target="_blank" href="%s">%s</a>' % (self.url, self.url))
+ admin_link.short_description = 'Link'
+
+ def save(self, *args, **kwargs):
+ td = timezone.localdate() - self.date_last_pub
+ if td.days > self.update_frequency and self.post_status != 1:
+ self.needs_update = True
+ else:
+ self.needs_update = False
+ super(WiredPost, self).save()
+
+
+class WiredNote(models.Model):
+ title = models.CharField(max_length=400)
+ url = models.CharField(max_length=400, blank=True, null=True)
+ body_markdown = models.TextField(blank=True, null=True)
+ date_created = models.DateTimeField(default=timezone.now)
+ post = models.ForeignKey(WiredPost, on_delete=models.CASCADE, null=True, blank=True)
+ STATUS = (
+ (0, 'Call In'),
+ (1, 'Asked For'),
+ (2, 'Coming'),
+ (3, 'Testing'),
+ (4, 'Done'),
+ (5, 'Live'),
+ )
+ status = models.IntegerField(choices=STATUS, default=0)
+ PLAN = (
+ (0, 'For Guide'),
+ (1, 'Review'),
+ (2, 'Rave/Rant'),
+ (3, 'No Plan'),
+ )
+ plan = models.IntegerField(choices=PLAN, default=0)
+
+ class Meta:
+ ordering = ('date_created', 'status')
+
+ def __str__(self):
+ return self.title
+
+ def get_absolute_url(self):
+ return reverse('gtd:wirednote-edit', kwargs={"pk": self.pk})
+
+ def save(self, *args, **kwargs):
+ super(WiredNote, self).save()
diff --git a/app/gtd/templates/gtd/note_form.html b/app/gtd/templates/gtd/note_form.html
new file mode 100644
index 0000000..13591e8
--- /dev/null
+++ b/app/gtd/templates/gtd/note_form.html
@@ -0,0 +1,35 @@
+{% extends 'base_gtd.html' %}
+
+{% block extrahead %}
+<style>
+form .selector label {
+ position: inherit;
+}
+</style>
+{% endblock %}
+{% block primary %}
+<main role="main" class="archive-wrapper">
+ <div class="post-body">
+ <form action="" method="post" class="comment-form">{% csrf_token %}
+ {% for field in form %}
+ <fieldset>
+ {%if field.name == "project" or field.name == "status" or field.name == 'note_type'%}<span class="selector">{{field.label_tag}}</span>{%else%}{{field.label_tag}}{%endif%}
+ {%if field.name == "body_markdown"%}<div class="textarea-rounded">{{ field }}</div>{%else%}{{field}}{%endif%}
+ </fieldset>
+ <small class="alert">{% if field.errors %}{{field.errors}}{% endif %}</small>
+ {%endfor%}
+ <input class="btn" type="submit" name="add_new" value="Save and add another" />
+ <input type="submit" name="save" class="btn" value="Save" />
+ </form>
+ </div>
+</main>
+{% endblock %}
+ {% block js %}
+ {% if is_update %}{%else%}
+<script type="text/javascript">
+let params = new URL(document.location).searchParams;
+document.getElementById('id_title').value = params.get("title");
+document.getElementById('id_body_markdown').value = params.get("description");
+</script>
+{% endif %}
+ {% endblock%}
diff --git a/app/gtd/templates/gtd/note_list.html b/app/gtd/templates/gtd/note_list.html
new file mode 100644
index 0000000..2e4ea0a
--- /dev/null
+++ b/app/gtd/templates/gtd/note_list.html
@@ -0,0 +1,23 @@
+{% extends 'base_gtd.html' %}
+{% block primary %}
+<main class="post-detail">
+ <div class="post-header"><ul class="flex header-list">
+ {% for status in note_statuses %}
+ <li><a class="btn" href="{% url 'gtd:note-list-status' status.1|lower%}">{{status.1}}</a></li>
+ {% endfor %}
+ <li class="right"><a href="{% url 'gtd:note-create' %}" class="btn">New Note</a></li>
+ </ul>
+ </div>
+ <div class="note-list">{% for object in object_list %}<article>
+ <h2>{{object.title}}{{object.title}}<span class="note-edit"><a href="{%url 'gtd:note-edit' object.pk%}">edit</a></span></h2>
+ <p>{{object.body_markdown}}</p>
+ <p class="small">For: <a href="/post/{{object.post.pk}}/notes">{{object.post}}</a></p>
+ <p class="small">Status: <a href="/post/{{object.post.pk}}/notes">{{object.get_status_display}}</a></p>
+ </article>
+{% endfor%}</div>
+</main>
+
+
+{% endblock %}
+{% block js %}
+{% endblock%}
diff --git a/app/gtd/templates/gtd/post_list.html b/app/gtd/templates/gtd/post_list.html
new file mode 100644
index 0000000..1b56106
--- /dev/null
+++ b/app/gtd/templates/gtd/post_list.html
@@ -0,0 +1,25 @@
+{% extends 'base_gtd.html' %}
+{%block extrahead%}
+<link href="/media/sortable.min.css" rel="stylesheet" />
+{%endblock%}
+{% block primary %}
+<main class="content">
+ <div class="narrow mtop">
+ <h2>New Guides</h2>
+ <ul>{% for object in object_list %}
+ <li>
+ <a href="/post/{{object.id}}/notes">{{object.title}}</a>
+ </li>{% endfor %}
+ </ul>
+ <h2>Reviews and Raves</h2>
+ <ul>{% for object in reviews %}
+ <li>
+ <a href="{{object.get_absolute_url}}">{{object.title}}</a>
+ </li>{% endfor %}
+ </ul>
+ </div>
+</main>
+{% endblock %}
+{% block js %}
+<script src="/media/sortable.min.js"></script>
+{% endblock%}
diff --git a/app/gtd/templates/gtd/post_table.html b/app/gtd/templates/gtd/post_table.html
new file mode 100644
index 0000000..f6803fe
--- /dev/null
+++ b/app/gtd/templates/gtd/post_table.html
@@ -0,0 +1,93 @@
+{% extends 'base_gtd.html' %}
+{%block extrahead%}
+<link href="/media/sortable.min.css" rel="stylesheet" />
+{%endblock%}
+{% block primary %}
+<main class="content">
+<div class="results">
+<table class="sortable" id="result_list">
+<thead>
+<tr>
+<th scope="col" class="sortable column-title">
+ <div class="text"><span>Title</span></div>
+</th>
+<th scope="col" class="column-admin_url">
+ <div class="text"><span>URL</span></div>
+</th>
+<th scope="col" class="column-admin_url">
+ <div class="text"><span>Edit URL</span></div>
+</th>
+<th scope="col" class="sortable column-date_last_pub sorted ascending">
+Date last pub
+ </th>
+<th scope="col" class="sortable column-post_type">
+ <div class="text">Post type</div>
+</th>
+<th scope="col" class="sortable column-update_frequency">
+ <div class="text">Freq</div>
+</th>
+<th scope="col" class="sortable column-needs_update">
+ <div class="text">Update?</div>
+</th>
+<th scope="col" class="column-days_overdue">
+ <div class="text"><span>Overdue</span></div>
+</th>
+<th scope="col" class="column-days_overdue">
+ <div class="text"><span>Edit</span></div>
+</th>
+</tr>
+</thead>
+<tbody>{% for object in object_list %}
+<tr>
+ <td class="field-title">
+ <a href="{% url 'gtd:post-detail' object.id %}">{{object.title}}</a>
+ </td>
+ <td class="field-admin_url">
+ <a target="_blank" href="{{object.url}}">
+ {{object.url|truncatechars:45}}
+ </a>
+ </td>
+ <td class="field-admin_url">{% if object.edit_url %}
+ <a target="_blank" href="{{object.edit_url}}">
+ edit
+ </a>{%else%}<a href="{% url 'gtd:post-edit' object.pk %}">add</a>{%endif%}
+ </td>
+ <td class="field-date_last_pub nowrap">{{object.date_last_pub}}</td>
+ <td class="field-post_type"><span class="hide">{{object.post_type}}</span>{{object.get_post_type_display}}</td>
+ <td class="field-update_frequency">{{object.update_frequency}}</td>
+ <td class="field-needs_update">{% if object.needs_update %}
+ <span class="hide">1</span><img src="/static/admin/img/icon-yes.svg" alt="True">{%else%}
+ <span class="hide">0</span><img src="/static/admin/img/icon-no.svg" alt="False">{%endif%}
+ </td>
+ <td class="field-days_overdue">{{object.days_overdue}}</td>
+ <td class="field-days_overdue"><a href="{% url 'gtd:post-edit' object.pk %}">edit</a></td></tr>
+</tr>
+{% endfor %}
+{% if reviews %}{% for object in reviews %}
+<tr>
+ <td class="field-title">
+ <a href="/post/{{object.id}}/notes">{{object.title}}</a>
+ </td>
+ <td class="field-admin_url">
+ <a target="_blank" href="{{object.url}}">
+ {{object.url|truncatechars:55}}
+ </a>
+ </td>
+ <td class="field-date_last_pub nowrap">{{object.date_last_pub}}</td>
+ <td class="field-post_type"><span class="hide">{{object.post_type}}</span>{{object.get_plan_display}}</td>
+ <td class="field-update_frequency">{{object.update_frequency}}</td>
+ <td class="field-needs_update">{% if object.needs_update %}
+ <span class="hide">1</span><img src="/static/admin/img/icon-yes.svg" alt="True">{%else%}
+ <span class="hide">0</span><img src="/static/admin/img/icon-no.svg" alt="False">{%endif%}
+ </td>
+ <td class="field-days_overdue">{{object.days_overdue}}</td>
+ <td class="field-days_overdue"><a href="{% url 'notes:edit' object.pk %}">edit</a></td></tr>
+</tr>{% endfor %}{% endif %}
+</tbody>
+</table>
+</div>
+</main>
+{% endblock %}
+{% block js %}
+<script src="/media/sortable.min.js"></script>
+{% endblock%}
diff --git a/app/gtd/templates/gtd/project_detail.html b/app/gtd/templates/gtd/project_detail.html
new file mode 100644
index 0000000..bab6982
--- /dev/null
+++ b/app/gtd/templates/gtd/project_detail.html
@@ -0,0 +1,17 @@
+{% extends 'base_gtd.html' %}
+{% load typogrify_tags %}
+{% block primary %}
+<main role="main" class="archive-wrapper">
+ <div class="post-body">
+ <h2>Project: {{object.title}}</h2>
+ {{object.body_html|smartypants|safe}}
+ <h3>Actions</h3>
+ {% for object in object.gtdnote_set.all %}
+ <h4>{{object.title}} <span class="note-edit"><a href="{%url 'gtd:note-edit' object.pk%}">edit</a></span></h4>
+ {{object.body_html|smartypants|safe}}
+ {% endfor %}
+ </div>
+</main>
+{% endblock %}
+ {% block js %}
+ {% endblock%}
diff --git a/app/gtd/templates/gtd/project_form.html b/app/gtd/templates/gtd/project_form.html
new file mode 100644
index 0000000..ac7d13f
--- /dev/null
+++ b/app/gtd/templates/gtd/project_form.html
@@ -0,0 +1,35 @@
+{% extends 'base_gtd.html' %}
+
+{% block extrahead %}
+<style>
+form .selector label {
+ position: inherit;
+}
+</style>
+{% endblock %}
+{% block primary %}
+<main role="main" class="archive-wrapper">
+ <div class="post-body">
+ <form action="" method="post" class="comment-form">{% csrf_token %}
+ {% for field in form %}
+ <fieldset>
+ {%if field.name == "project_type" or field.name == "outcome" or field.name == 'note_type'%}<span class="selector">{{field.label_tag}}</span>{%else%}{{field.label_tag}}{%endif%}
+ {%if field.name == "body_markdown"%}<div class="textarea-rounded">{{ field }}</div>{%else%}{{field}}{%endif%}
+ </fieldset>
+ <small class="alert">{% if field.errors %}{{field.errors}}{% endif %}</small>
+ {%endfor%}
+ <input class="btn" type="submit" name="add_new" value="Save and add another" />
+ <input type="submit" name="save" class="btn" value="Save" />
+ </form>
+ </div>
+</main>
+{% endblock %}
+ {% block js %}
+ {% if is_update %}{%else%}
+<script type="text/javascript">
+let params = new URL(document.location).searchParams;
+document.getElementById('id_title').value = params.get("title");
+document.getElementById('id_body_markdown').value = params.get("description");
+</script>
+{% endif %}
+ {% endblock%}
diff --git a/app/gtd/templates/gtd/project_list.html b/app/gtd/templates/gtd/project_list.html
new file mode 100644
index 0000000..a37f4e8
--- /dev/null
+++ b/app/gtd/templates/gtd/project_list.html
@@ -0,0 +1,23 @@
+{% extends 'base_gtd.html' %}
+{% block primary %}
+<main class="post-detail">
+ <div class="post-header"><ul class="flex header-list">
+ {% for status in note_statuses %}
+ <li><a class="btn" href="{% url 'gtd:note-list-status' status.1|lower%}">{{status.1}}</a></li>
+ {% endfor %}
+ <li class="right"><a href="{% url 'gtd:note-create' %}" class="btn">New Note</a></li>
+ </ul>
+ </div>
+ <div class="note-list">{% for object in object_list %}<article>
+ <h2>{{object.title}}<span class="note-edit"><a href="{% url 'gtd:project-edit' object.pk %}">edit</a></span></h2>
+ <p>{{object.body_markdown}}</p>
+ <p class="small">Date Goal: {{object.date_goal}}</p>
+ <p class="small">Type: {{object.get_project_type_display}}</p>
+ </article>
+{% endfor%}</div>
+</main>
+
+
+{% endblock %}
+{% block js %}
+{% endblock%}
diff --git a/app/gtd/templates/gtd/wirednote_form.html b/app/gtd/templates/gtd/wirednote_form.html
new file mode 100644
index 0000000..92b8230
--- /dev/null
+++ b/app/gtd/templates/gtd/wirednote_form.html
@@ -0,0 +1,26 @@
+{% extends 'base_gtd.html' %}
+{% block primary %}
+<main role="main" class="archive-wrapper">
+ <form action="" method="post" class="comment-form">{% csrf_token %}
+ {% for field in form %}
+ <fieldset>
+ {%if field.name == "post" or field.name == "status" or field.name == 'plan'%}<span class="selector">{{field.label_tag}}</span>{%else%}{{field.label_tag}}{%endif%}
+ {%if field.name == "body_markdown"%}<div class="textarea-rounded">{{ field }}</div>{%else%}{{field}}{%endif%}
+ </fieldset>
+ <small class="alert">{% if field.errors %}{{field.errors}}{% endif %}</small>
+ {%endfor%}
+ <input class="btn" type="submit" name="add_new" value="Save and add another" />
+ <input type="submit" name="save" class="btn" value="Save" />
+ </form>
+</main>
+{% endblock %}
+ {% block js %}
+ {% if is_update %}{%else%}
+<script type="text/javascript">
+let params = new URL(document.location).searchParams;
+document.getElementById('id_title').value = params.get("title");
+document.getElementById('id_url').value = params.get("url");
+document.getElementById('id_body_markdown').value = params.get("description");
+</script>
+{% endif %}
+ {% endblock%}
diff --git a/app/gtd/templates/gtd/wirednote_list.html b/app/gtd/templates/gtd/wirednote_list.html
new file mode 100644
index 0000000..7b17617
--- /dev/null
+++ b/app/gtd/templates/gtd/wirednote_list.html
@@ -0,0 +1,23 @@
+{% extends 'base_gtd.html' %}
+{% block primary %}
+<main class="post-detail">
+ <div class="post-header"><ul class="flex header-list">
+ {% for status in note_statuses %}
+ <li><a class="btn" href="{% url 'gtd:wirednote-list' status.1|lower%}">{{status.1}}</a></li>
+ {% endfor %}
+ <li class="right"><a href="{% url 'gtd:wirednote-create' %}" class="btn">New Note</a></li>
+ </ul>
+ </div>
+ <div class="note-list">{% for object in object_list %}<article>
+ <h2>{%if object.url%}<a href="{{object.url}}">{{object.title}}</a>{%else%}{{object.title}}{%endif%}<span class="note-edit"><a href="{{object.get_absolute_url}}">edit</a></span></h2>
+ <p>{{object.body_markdown}}</p>
+ <p class="small">For: <a href="/post/{{object.post.pk}}/notes">{{object.post}}</a></p>
+ <p class="small">Status: <a href="/post/{{object.post.pk}}/notes">{{object.get_status_display}}</a></p>
+ </article>
+{% endfor%}</div>
+</main>
+
+
+{% endblock %}
+{% block js %}
+{% endblock%}
diff --git a/app/gtd/templates/gtd/wiredpost_detail.html b/app/gtd/templates/gtd/wiredpost_detail.html
new file mode 100644
index 0000000..92ac269
--- /dev/null
+++ b/app/gtd/templates/gtd/wiredpost_detail.html
@@ -0,0 +1,21 @@
+{% extends 'base_gtd.html' %}
+{% block primary %}
+<main class="post-detail">
+ <div class="post-header">
+<h1><a href="{{object.url}}">{{object.title}}</a></h1>
+<p>Last Updated: {{object.date_last_pub}}</p>
+<p>Needs Update: {% if object.needs_update %} Yes {% if object.days_overdue %}{{object.days_overdue}} days overdue{%endif %}{%endif%}</p>
+ </div>{% regroup notes by get_status_display as newlist %}
+ <div class="note-list">{% for obj in newlist %}
+ <h5>{{obj.grouper}}</h5>
+ {% for object in obj.list %}
+ <article>
+ <h2>{%if object.url%}<a href="{{object.url}}">{{object.title}}</a>{%else%}{{object.title}}{%endif%}<span class="note-edit"><a href="{{object.get_absolute_url}}">edit</a></span></h2>
+ <p>{{object.body_markdown}}</p>
+ <p>Status: {% if object.status == 0 %}<span class="alert">{{object.get_status_display}}</span>{%else%}{{object.get_status_display}}{%endif%}</p>
+ </article>{%endfor%}
+{% endfor%}</div>
+</main>
+{% endblock %}
+ {% block js %}
+ {% endblock%}
diff --git a/app/gtd/templates/gtd/wiredpost_form.html b/app/gtd/templates/gtd/wiredpost_form.html
new file mode 100644
index 0000000..a9880cf
--- /dev/null
+++ b/app/gtd/templates/gtd/wiredpost_form.html
@@ -0,0 +1,16 @@
+{% extends 'base_gtd.html' %}
+{% block primary %}
+<main role="main" class="archive-wrapper">
+ <form action="" method="post" class="comment-form">{% csrf_token %}
+ {% for field in form %}
+ <fieldset>
+ {%if field.name == "guide_type" or field.name == "post_status" or field.name == "template_type" %}<span class="selector">{{field.label_tag}}</span>{%else%}{{field.label_tag}}{%endif%}
+ {%if field.name == "body_markdown"%}<div class="textarea-rounded">{{ field }}</div>{%else%}{{field}}{%endif%}
+ </fieldset>
+ <small class="alert">{% if field.errors %}{{field.errors}}{% endif %}</small>
+ {%endfor%}
+ <input class="btn" type="submit" name="add_new" value="Save and add another" />
+ <input type="submit" name="save" class="btn" value="Save" />
+ </form>
+</main>
+{% endblock %}
diff --git a/app/gtd/urls.py b/app/gtd/urls.py
new file mode 100644
index 0000000..db416bb
--- /dev/null
+++ b/app/gtd/urls.py
@@ -0,0 +1,101 @@
+from django.urls import path, re_path
+
+from . import views
+
+app_name = "gtd"
+
+urlpatterns = [
+ path(
+ r'todo',
+ views.GTDNoteTODOView.as_view(),
+ name="note-list"
+ ),
+ path(
+ r'notes',
+ views.GTDNoteListView.as_view(),
+ {'status':None},
+ name="note-list"
+ ),
+ path(
+ r'notes/create',
+ views.GTDNoteCreateView.as_view(),
+ name="note-create"
+ ),
+ path(
+ r'notes/<str:status>',
+ views.GTDNoteListView.as_view(),
+ name="note-list-status"
+ ),
+ path(
+ r'note/<pk>/edit',
+ views.GTDNoteUpdateView.as_view(),
+ name="note-edit"
+ ),
+ path(
+ r'projects',
+ views.GTDProjectListView.as_view(),
+ name="project-list"
+ ),
+ path(
+ r'projects/create',
+ views.GTDProjectCreateView.as_view(),
+ name="project-create"
+ ),
+ path(
+ r'projects/<pk>',
+ views.GTDProjectDetailView.as_view(),
+ name="project-detail"
+ ),
+ path(
+ r'projects/<pk>/edit',
+ views.GTDProjectUpdateView.as_view(),
+ name="project-edit"
+ ),
+ path(
+ r'wirednote',
+ views.WiredNoteListView.as_view(),
+ {'status':None},
+ name="wirednote-list"
+ ),
+ path(
+ r'wirednote/create',
+ views.WiredNoteCreateView.as_view(),
+ name="wirednote-create"
+ ),
+ path(
+ r'wirednote/<str:status>',
+ views.WiredNoteListView.as_view(),
+ name="wirednote-list"
+ ),
+ path(
+ r'wirednote/<pk>/edit',
+ views.WiredNoteUpdateView.as_view(),
+ name="wirednote-edit"
+ ),
+
+ path(
+ r'post',
+ views.WiredPostListView.as_view(),
+ name="post-list"
+ ),
+ path(
+ r'post/new',
+ views.WiredPostNewView.as_view(),
+ name="post-create"
+ ),
+ path(
+ r'post/<pk>/edit',
+ views.WiredPostUpdateView.as_view(),
+ name="post-edit"
+ ),
+ path(
+ r'posts/todo',
+ views.WiredPostTodoView.as_view(),
+ name="post-todo"
+ ),
+ path(
+ r'<pk>/notes',
+ views.WiredPostNotesView.as_view(),
+ name="post-detail"
+ ),
+]
diff --git a/app/gtd/views.py b/app/gtd/views.py
new file mode 100644
index 0000000..8082db3
--- /dev/null
+++ b/app/gtd/views.py
@@ -0,0 +1,221 @@
+from django.views.generic import UpdateView, DetailView, ListView
+from django.views.generic.edit import CreateView, DeleteView, UpdateView
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.urls import reverse
+
+from .models import GTDNote, GTDProject, WiredNote, WiredPost
+from .forms import GTDNoteCreateForm, GTDNoteEditForm, GTDProjectCreateForm, GTDProjectUpdateForm, WiredNoteCreateForm, WiredNoteEditForm, WiredPostUpdateForm
+
+class GTDNoteCreateView(CreateView):
+ model = GTDNote
+ form_class = GTDNoteCreateForm
+ template_name = "gtd/note_form.html"
+
+ def get_form_kwargs(self):
+ kwargs = super(GTDNoteCreateView, self).get_form_kwargs()
+ return kwargs
+
+ def get_success_url(self):
+ if 'add_new' in self.request.POST:
+ return reverse('gtd:note-create')
+ else:
+ if self.object.project:
+ return reverse('gtd:project-detail', kwargs={"pk": self.object.project.pk})
+ else:
+ return reverse('gtd:note-create')
+
+
+class GTDNoteUpdateView(UpdateView):
+ model = GTDNote
+ form_class = GTDNoteEditForm
+ template_name = "gtd/note_form.html"
+
+ def get_context_data(self, **kwargs):
+ context = super(GTDNoteUpdateView, self).get_context_data(**kwargs)
+ context['is_update'] = True
+ return context
+
+ def get_success_url(self):
+ return reverse('gtd:project-detail', kwargs={"pk": self.object.project.pk})
+
+
+class GTDNoteListView(ListView):
+ model = GTDNote
+ template_name = "gtd/note_list.html"
+
+ def get_queryset(self):
+ if self.kwargs['status']:
+ status_reverse = dict((v, k) for k, v in GTDNote.STATUS)
+ status = status_reverse[self.kwargs['status'].title()]
+ return GTDNote.objects.filter(status=status)
+ return GTDNote.objects.filter(status=1)
+
+ def get_context_data(self, **kwargs):
+ context = super(GTDNoteListView, self).get_context_data(**kwargs)
+ context['note_statuses'] = GTDNote.STATUS
+ return context
+
+
+class GTDProjectCreateView(CreateView):
+ model = GTDProject
+ form_class = GTDProjectCreateForm
+ template_name = "gtd/project_form.html"
+
+ def get_form_kwargs(self):
+ kwargs = super(GTDProjectCreateView, self).get_form_kwargs()
+ return kwargs
+
+ def get_success_url(self):
+ if 'add_new' in self.request.POST:
+ return reverse('gtd:project-create')
+ else:
+ return reverse('gtd:project-detail', kwargs={"pk": self.object.pk})
+
+
+class GTDProjectUpdateView(UpdateView):
+ model = GTDProject
+ form_class = GTDProjectUpdateForm
+ template_name = "gtd/project_form.html"
+
+ def get_context_data(self, **kwargs):
+ context = super(GTDProjectUpdateView, self).get_context_data(**kwargs)
+ context['is_update'] = True
+ return context
+
+
+class GTDProjectDetailView(DetailView):
+ model = GTDProject
+ template_name = "gtd/project_detail.html"
+
+ def get_context_data(self, **kwargs):
+ context = super(GTDProjectDetailView, self).get_context_data(**kwargs)
+ return context
+
+
+class GTDProjectListView(ListView):
+ model = GTDProject
+ template_name = "gtd/project_list.html"
+
+ def get_context_data(self, **kwargs):
+ context = super(GTDProjectListView, self).get_context_data(**kwargs)
+ return context
+
+
+class GTDNoteTODOView(ListView):
+ model = GTDNote
+ template_name = "gtd/note_list.html"
+
+ def get_queryset(self):
+ return GTDNote.objects.filter(status=1)
+
+
+class WiredNoteCreateView(CreateView):
+ model = WiredNote
+ form_class = WiredNoteCreateForm
+
+ def get_form_kwargs(self):
+ kwargs = super(WiredNoteCreateView, self).get_form_kwargs()
+ kwargs.update({'user': self.request.user})
+ return kwargs
+
+ def get_success_url(self):
+ if 'add_new' in self.request.POST:
+ return reverse('gtd:wirednotes-create')
+ else:
+ if self.object.post:
+ return reverse('gtd:wiredposts-detail', kwargs={"pk": self.object.post.pk})
+ else:
+ return reverse('gtd:wirednotes-create')
+
+
+class WiredNoteUpdateView(UpdateView):
+ model = WiredNote
+ form_class = WiredNoteEditForm
+
+ def get_form_kwargs(self):
+ kwargs = super(WiredNoteUpdateView, self).get_form_kwargs()
+ return kwargs
+
+ def get_context_data(self, **kwargs):
+ context = super(WiredNoteUpdateView, self).get_context_data(**kwargs)
+ context['is_update'] = True
+ return context
+
+ def get_success_url(self):
+ return reverse('gtd:post-detail', kwargs={"pk": self.object.post.pk})
+
+
+class WiredNoteListView(ListView):
+ model = WiredNote
+
+ def get_queryset(self):
+ if self.kwargs['status']:
+ status_reverse = dict((v, k) for k, v in WiredNote.STATUS)
+ status = status_reverse[self.kwargs['status'].title()]
+ return WiredNote.objects.filter(status=status)
+ return WiredNote.objects.all()
+
+ def get_context_data(self, **kwargs):
+ context = super(WiredNoteListView, self).get_context_data(**kwargs)
+ context['note_statuses'] = WiredNote.STATUS
+ return context
+
+
+class WiredPostListView(ListView):
+ model = WiredPost
+ template_name = 'gtd/post_table.html'
+
+ def get_queryset(self):
+ return WiredPost.objects.all().order_by("-needs_update")
+
+
+class WiredPostNewView(ListView):
+ template_name = 'gtd/post_list.html'
+
+ def get_queryset(self):
+ return WiredPost.objects.filter(is_live=0)
+
+ def get_context_data(self, **kwargs):
+ context = super(WiredPostNewView, self).get_context_data(**kwargs)
+ context['reviews'] = WiredNote.objects.filter(plan__in=[1,2], status__in=[0,1,2,3])
+ return context
+
+
+class WiredPostTodoView(LoginRequiredMixin, ListView):
+ template_name = 'posts/post_table.html'
+
+ def get_queryset(self):
+ qs = WiredPost.objects.filter(user=self.request.user)
+ qs = qs.filter(Q(needs_update=True) | Q(is_live=0)).exclude(post_status=1)
+ unsorted_results = qs.all()
+ return sorted(unsorted_results, key=lambda a: a.days_overdue(), reverse=True)
+
+ def get_context_data(self, **kwargs):
+ context = super(WiredPostTodoView, self).get_context_data(**kwargs)
+ context['reviews'] = WiredNote.objects.filter(plan__in=[1,2,3]).exclude(status=4)
+ return context
+
+
+class WiredPostNotesView(DetailView):
+ model = WiredPost
+
+ def get_context_data(self, **kwargs):
+ context = super(WiredPostNotesView, self).get_context_data(**kwargs)
+ context['notes'] = self.get_object().wirednote_set.all().order_by("status")
+ return context
+
+class WiredPostUpdateView(UpdateView):
+ model = WiredPost
+ form_class = WiredPostUpdateForm
+
+ def get_form_kwargs(self):
+ kwargs = super(WiredPostUpdateView, self).get_form_kwargs()
+ return kwargs
+
+ def get_success_url(self):
+ if 'add_new' in self.request.POST:
+ return reverse('gtd:posts-create')
+ else:
+ return reverse('gtd:posts-detail', kwargs={"pk": self.object.pk})
+
+
diff --git a/config/base_urls.py b/config/base_urls.py
index 0501947..1265e7b 100644
--- a/config/base_urls.py
+++ b/config/base_urls.py
@@ -33,6 +33,7 @@ urlpatterns = [
#path(r'admin/income/invoice/monthlyview/<str:slug>/', MonthlyInvoiceView.as_view(), name="monthly-invoice"),
path(r'admin/', admin.site.urls),
path(r'trading/', include('trading.urls')),
+ path(r'gtd/', include('gtd.urls')),
path(r'spending/', include('budget.urls')),
path(r'planner/', include('planner.urls')),
path(r'luximages/insert/', utils.views.insert_image),
diff --git a/templates/base_gtd.html b/templates/base_gtd.html
new file mode 100644
index 0000000..06655e3
--- /dev/null
+++ b/templates/base_gtd.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html {%block htmlclass%}{%endblock%} dir="ltr" lang="en-US">
+ {% block sitename %}
+<head>
+ <title>{% block pagetitle %}{% endblock %}</title>{%endblock%}
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="description"
+ content="{% block metadescription %}{% endblock %}">
+ <meta name="author" content="luxagraf">
+ {%block stylesheet%}<link rel="stylesheet"
+ href="/media/gtdscreenv1.css{%comment%}?{% now "u" %}{%endcomment%}"
+ media="screen">{%endblock%}
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+ {%block extrahead%}{%endblock%}
+</head>
+<body {%block bodyid%}{%endblock%}{%block bodyevents%}{%endblock%}>
+ <header class="header-wrapper">
+ <div id="logo">
+ <a class="logo-link" href="/" title="Home">L</span></a>
+ </div>
+ <nav>
+ <a class="nav-item" href="/gtd/todo" title="View things that need to be done">todo</a>
+ <a class="nav-item" href="/gtd/outcomes" title="View Guides">Outcomes</a>
+ <a class="nav-item" href="/gtd/projects" title="View Notes">Projects</a>
+ <a class="nav-item" href="/gtd/notes" title="View Notes">Notes</a>
+ <a class="nav-item" href="{% url 'gtd:post-list' %}" title="View Notes">Wired Posts</a>
+ <a class="nav-item" href="{% url 'gtd:wirednote-list' %}" title="View Notes">Wired Notes</a>
+ <a class="nav-item" href="{%url 'gtd:note-create'%}" title="View new stuff todo">new</a>
+ </nav>
+ </header>
+ {% block breadcrumbs %}{% endblock %}
+ {% block primary %}{% endblock %}
+ {% block extrabody %}{% endblock %}
+ <footer class="page-footer">
+ <nav>
+ <a class="nav-item" href="/notes/todo" title="See what needs to be called in">Todo</a>
+ <a class="nav-item" href="/notes" title="View Guides">Notes</a>
+ <a class="nav-item" href="/posts" title="View Guides">Guides</a>
+ </nav>
+ <p id="license">
+ &copy; 2020-{% now "Y" %}
+ <span class="h-card"><a class="p-name u-url" href="https://luxagraf.net/">luxagraf</a><data class="p-locality" value="Everywhere"></data><data class="p-country-name" value="United States"></data></span>.
+ </p>
+ </footer>
+ {% block js %}{% endblock%}
+</body>
+</html>