aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2019-01-13 11:42:01 -0600
committerluxagraf <sng@luxagraf.net>2019-01-13 11:42:01 -0600
commit5b9343d77d8321e44d1ffc60769c651771dc38dd (patch)
tree8bbce1b415fbf2fd4c4ee1a7913ca41d362216ec /apps
parent261f9df4911f861a71e11eb3f0bfbe1a5a5d12b9 (diff)
Refactored Javascript, started on forums
Diffstat (limited to 'apps')
-rw-r--r--apps/forum/admin.py2
-rw-r--r--apps/forum/forms.py13
-rw-r--r--apps/forum/migrations/0002_category_description.py19
-rw-r--r--apps/forum/migrations/0003_auto_20190110_1405.py18
-rw-r--r--apps/forum/migrations/0004_category_color_rgb.py18
-rw-r--r--apps/forum/migrations/0005_auto_20190110_2023.py18
-rw-r--r--apps/forum/migrations/0006_auto_20190111_1002.py28
-rw-r--r--apps/forum/models.py22
-rw-r--r--apps/forum/templatetags/__init__.py0
-rw-r--r--apps/forum/templatetags/timesinceabbr.py107
-rw-r--r--apps/forum/urls.py6
-rw-r--r--apps/forum/views.py14
12 files changed, 254 insertions, 11 deletions
diff --git a/apps/forum/admin.py b/apps/forum/admin.py
index 9fddd4e..1dfe734 100644
--- a/apps/forum/admin.py
+++ b/apps/forum/admin.py
@@ -1,6 +1,7 @@
from django.contrib import admin
from .models import Topic, Category, Post
+from .forms import CategoryForm
@admin.register(Topic)
@@ -10,6 +11,7 @@ class TopicAdmin(admin.ModelAdmin):
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
+ form = CategoryForm
pass
diff --git a/apps/forum/forms.py b/apps/forum/forms.py
new file mode 100644
index 0000000..655a318
--- /dev/null
+++ b/apps/forum/forms.py
@@ -0,0 +1,13 @@
+#form.py
+from django.forms import ModelForm
+from django.forms.widgets import TextInput
+from .models import Category
+
+
+class CategoryForm(ModelForm):
+ class Meta:
+ model = Category
+ fields = '__all__'
+ widgets = {
+ 'color_rgb': TextInput(attrs={'type': 'color'}),
+ }
diff --git a/apps/forum/migrations/0002_category_description.py b/apps/forum/migrations/0002_category_description.py
new file mode 100644
index 0000000..6c13147
--- /dev/null
+++ b/apps/forum/migrations/0002_category_description.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.1.2 on 2019-01-10 17:23
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('forum', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='category',
+ name='description',
+ field=models.CharField(default='', max_length=350),
+ preserve_default=False,
+ ),
+ ]
diff --git a/apps/forum/migrations/0003_auto_20190110_1405.py b/apps/forum/migrations/0003_auto_20190110_1405.py
new file mode 100644
index 0000000..446f0a4
--- /dev/null
+++ b/apps/forum/migrations/0003_auto_20190110_1405.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.1.2 on 2019-01-10 20:05
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('forum', '0002_category_description'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='category',
+ old_name='title',
+ new_name='name',
+ ),
+ ]
diff --git a/apps/forum/migrations/0004_category_color_rgb.py b/apps/forum/migrations/0004_category_color_rgb.py
new file mode 100644
index 0000000..04de146
--- /dev/null
+++ b/apps/forum/migrations/0004_category_color_rgb.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.1.2 on 2019-01-10 20:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('forum', '0003_auto_20190110_1405'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='category',
+ name='color_rgb',
+ field=models.CharField(blank=True, max_length=20),
+ ),
+ ]
diff --git a/apps/forum/migrations/0005_auto_20190110_2023.py b/apps/forum/migrations/0005_auto_20190110_2023.py
new file mode 100644
index 0000000..3040a48
--- /dev/null
+++ b/apps/forum/migrations/0005_auto_20190110_2023.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.1.2 on 2019-01-11 02:23
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('forum', '0004_category_color_rgb'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='topic',
+ old_name='last_post_userj',
+ new_name='last_post_user',
+ ),
+ ]
diff --git a/apps/forum/migrations/0006_auto_20190111_1002.py b/apps/forum/migrations/0006_auto_20190111_1002.py
new file mode 100644
index 0000000..c1673cb
--- /dev/null
+++ b/apps/forum/migrations/0006_auto_20190111_1002.py
@@ -0,0 +1,28 @@
+# Generated by Django 2.1.2 on 2019-01-11 16:02
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('forum', '0005_auto_20190110_2023'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='post',
+ old_name='post_body_html',
+ new_name='body_html',
+ ),
+ migrations.RenameField(
+ model_name='post',
+ old_name='post_body_json',
+ new_name='body_json',
+ ),
+ migrations.RenameField(
+ model_name='post',
+ old_name='post_body_text',
+ new_name='body_text',
+ ),
+ ]
diff --git a/apps/forum/models.py b/apps/forum/models.py
index d0f6b6f..3a54514 100644
--- a/apps/forum/models.py
+++ b/apps/forum/models.py
@@ -28,8 +28,10 @@ class CategoryManager(models.Manager):
class Category(models.Model):
- title = models.CharField(max_length=120)
+ name = models.CharField(max_length=120)
slug = models.SlugField()
+ description = models.CharField(max_length=350)
+ color_rgb = models.CharField(max_length=20, blank=True)
date_created = models.DateTimeField(auto_now=False, auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True, auto_now_add=False)
@@ -44,8 +46,11 @@ class Category(models.Model):
objects = CategoryManager()
- def __unicode__(self):
- return self.title
+ def __str__(self):
+ return self.name
+
+ def get_absolute_url(self):
+ return reverse("forum:category-detail", kwargs={'slug': self.slug})
class TopicManager(models.Manager):
@@ -62,10 +67,9 @@ class TopicManager(models.Manager):
class Topic(models.Model):
-
category = models.ForeignKey(Category, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='topic_user')
- last_post_userj= models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='topic_last_post_user', blank=True, null=True)
+ last_post_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='topic_last_post_user', blank=True, null=True)
highest_post = models.ForeignKey('Post', on_delete=models.CASCADE, related_name='topic_highest_post', blank=True, null=True)
title = models.CharField(max_length=255)
@@ -119,9 +123,9 @@ class Post(models.Model):
('reply', 'reply'),
)
post_type = models.CharField(max_length=60, choices=POST_TYPE_CHOICES)
- post_body_text = models.TextField(blank=True, null=False)
- post_body_html = models.TextField(blank=True, null=True)
- post_body_json = models.TextField(blank=True, null=True)
+ body_text = models.TextField(blank=True, null=False)
+ body_html = models.TextField(blank=True, null=True)
+ body_json = models.TextField(blank=True, null=True)
date_created = models.DateTimeField(auto_now=False, auto_now_add=True, blank=True)
date_updated = models.DateTimeField(auto_now=True, auto_now_add=False, blank=True)
@@ -142,4 +146,4 @@ class Post(models.Model):
verbose_name_plural = "Posts"
def __str__(self):
- return '%s - %s' % (self.raw, self.topic.title)
+ return '%s - %s' % (self.topic.title, self.id)
diff --git a/apps/forum/templatetags/__init__.py b/apps/forum/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/forum/templatetags/__init__.py
diff --git a/apps/forum/templatetags/timesinceabbr.py b/apps/forum/templatetags/timesinceabbr.py
new file mode 100644
index 0000000..eee2726
--- /dev/null
+++ b/apps/forum/templatetags/timesinceabbr.py
@@ -0,0 +1,107 @@
+import calendar
+import datetime
+
+from django.utils.html import avoid_wrapping
+from django.utils.timezone import is_aware, utc
+from django.utils.translation import gettext, ngettext_lazy
+
+from django import template
+register = template.Library()
+
+TIME_STRINGS = {
+ 'year': ngettext_lazy('%d Y', '%d y'),
+ 'month': ngettext_lazy('%d M', '%d M'),
+ 'week': ngettext_lazy('%d W', '%d w'),
+ 'day': ngettext_lazy('%d d', '%d d'),
+ 'hour': ngettext_lazy('%d h', '%d h'),
+ 'minute': ngettext_lazy('%d m', '%d m'),
+}
+
+TIMESINCE_CHUNKS = (
+ (60 * 60 * 24 * 365, 'year'),
+ (60 * 60 * 24 * 30, 'month'),
+ (60 * 60 * 24 * 7, 'week'),
+ (60 * 60 * 24, 'day'),
+ (60 * 60, 'hour'),
+ (60, 'minute'),
+)
+
+
+def timesinceabbr(d, now=None, reversed=False, time_strings=None):
+ """
+ Take two datetime objects and return the time between d and now as a nicely
+ formatted string, e.g. "10 minutes". If d occurs after now, return
+ "0 minutes".
+
+ Units used are years, months, weeks, days, hours, and minutes.
+ Seconds and microseconds are ignored. Up to two adjacent units will be
+ displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are
+ possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.
+
+ `time_strings` is an optional dict of strings to replace the default
+ TIME_STRINGS dict.
+
+ Adapted from
+ https://web.archive.org/web/20060617175230/http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
+ """
+ if time_strings is None:
+ time_strings = TIME_STRINGS
+
+ # Convert datetime.date to datetime.datetime for comparison.
+ if not isinstance(d, datetime.datetime):
+ d = datetime.datetime(d.year, d.month, d.day)
+ if now and not isinstance(now, datetime.datetime):
+ now = datetime.datetime(now.year, now.month, now.day)
+
+ now = now or datetime.datetime.now(utc if is_aware(d) else None)
+
+ if reversed:
+ d, now = now, d
+ delta = now - d
+
+ # Deal with leapyears by subtracing the number of leapdays
+ leapdays = calendar.leapdays(d.year, now.year)
+ if leapdays != 0:
+ if calendar.isleap(d.year):
+ leapdays -= 1
+ elif calendar.isleap(now.year):
+ leapdays += 1
+ delta -= datetime.timedelta(leapdays)
+
+ # ignore microseconds
+ since = delta.days * 24 * 60 * 60 + delta.seconds
+ if since <= 0:
+ # d is in the future compared to now, stop processing.
+ return avoid_wrapping(gettext('0 minutes'))
+ for i, (seconds, name) in enumerate(TIMESINCE_CHUNKS):
+ count = since // seconds
+ if count != 0:
+ break
+ result = avoid_wrapping(time_strings[name] % count)
+ if i + 1 < len(TIMESINCE_CHUNKS):
+ # Now get the second item
+ seconds2, name2 = TIMESINCE_CHUNKS[i + 1]
+ count2 = (since - (seconds * count)) // seconds2
+ if count2 != 0:
+ result += gettext(', ') + avoid_wrapping(time_strings[name2] % count2)
+ return result
+
+
+def timeuntil(d, now=None, time_strings=None):
+ """
+ Like timesince, but return a string measuring the time until the given time.
+ """
+ return timesinceabbr(d, now, reversed=True, time_strings=time_strings)
+
+
+@register.filter("timesinceabbr", is_safe=False)
+def timesince_filter(value, arg=None):
+ """Format a date as the time since that date (i.e. "4 days, 6 hours")."""
+ if not value:
+ return ''
+ try:
+ if arg:
+ return timesinceabbr(value, arg)
+ return timesinceabbr(value)
+ except (ValueError, TypeError):
+ return ''
diff --git a/apps/forum/urls.py b/apps/forum/urls.py
index 79e2e0d..3cfd250 100644
--- a/apps/forum/urls.py
+++ b/apps/forum/urls.py
@@ -2,11 +2,13 @@ from django.urls import path
from .views import (
TopicListView,
+ TopicDetailView,
)
app_name = "forum"
urlpatterns = [
- path(r't/', TopicListView.as_view(), name='topic-list',),
- path(r'', TopicListView.as_view(), name='topic-redirect',),
+ path(r'', TopicListView.as_view(), name='topic-list',),
+ path(r'c/<str:slug>', TopicListView.as_view(), name='category-detail',),
+ path(r't/<str:slug>/<int:pk>', TopicDetailView.as_view(), name='topic-detail',),
]
diff --git a/apps/forum/views.py b/apps/forum/views.py
index bc7cc74..1540157 100644
--- a/apps/forum/views.py
+++ b/apps/forum/views.py
@@ -17,3 +17,17 @@ from utils.views import LoggedInViewWithUser
class TopicListView(LoggedInViewWithUser, ListView):
model = Topic
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context['category_list'] = Category.objects.all()
+ return context
+
+
+class TopicDetailView(LoggedInViewWithUser, DetailView):
+ model = Topic
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context['category_list'] = Category.objects.all()
+ return context