From 5b9343d77d8321e44d1ffc60769c651771dc38dd Mon Sep 17 00:00:00 2001 From: luxagraf Date: Sun, 13 Jan 2019 11:42:01 -0600 Subject: Refactored Javascript, started on forums --- apps/forum/admin.py | 2 + apps/forum/forms.py | 13 +++ apps/forum/migrations/0002_category_description.py | 19 ++++ apps/forum/migrations/0003_auto_20190110_1405.py | 18 ++++ apps/forum/migrations/0004_category_color_rgb.py | 18 ++++ apps/forum/migrations/0005_auto_20190110_2023.py | 18 ++++ apps/forum/migrations/0006_auto_20190111_1002.py | 28 +++++ apps/forum/models.py | 22 ++-- apps/forum/templatetags/__init__.py | 0 apps/forum/templatetags/timesinceabbr.py | 107 +++++++++++++++++++ apps/forum/urls.py | 6 +- apps/forum/views.py | 14 +++ design/sass/_forum.scss | 70 +++++++++++++ design/sass/_header.scss | 4 +- design/sass/_notes.scss | 5 +- design/sass/screenv1.scss | 1 + design/templates/accounts/change-settings.html | 7 -- design/templates/base.html | 3 +- design/templates/forum/topic_detail.html | 114 +++++++++++++++++++++ design/templates/forum/topic_list.html | 86 ++++++++++++---- design/templates/notes/notebook_detail.html | 4 + design/templates/notes/notes_list.html | 2 + design/templates/notes/notes_list_by_tag.html | 71 +++++++++++++ scripts/src/account-edit.js | 8 +- scripts/src/forum-categories.js | 15 +++ scripts/src/note-list.js | 36 ++++--- scripts/src/notebook-edit.js | 34 +++--- 27 files changed, 651 insertions(+), 74 deletions(-) create mode 100644 apps/forum/forms.py create mode 100644 apps/forum/migrations/0002_category_description.py create mode 100644 apps/forum/migrations/0003_auto_20190110_1405.py create mode 100644 apps/forum/migrations/0004_category_color_rgb.py create mode 100644 apps/forum/migrations/0005_auto_20190110_2023.py create mode 100644 apps/forum/migrations/0006_auto_20190111_1002.py create mode 100644 apps/forum/templatetags/__init__.py create mode 100644 apps/forum/templatetags/timesinceabbr.py create mode 100644 design/sass/_forum.scss create mode 100644 design/templates/forum/topic_detail.html create mode 100644 design/templates/notes/notes_list_by_tag.html create mode 100644 scripts/src/forum-categories.js 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 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/', TopicListView.as_view(), name='category-detail',), + path(r't//', 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 diff --git a/design/sass/_forum.scss b/design/sass/_forum.scss new file mode 100644 index 0000000..cedae2d --- /dev/null +++ b/design/sass/_forum.scss @@ -0,0 +1,70 @@ +.topic-list { + table-layout: fixed; + border-collapse: collapse; + th:first-of-type, td:first-of-type { + padding-left: 10px; + } + tr { + border-bottom: 1px solid #e9e9e9; + &:hover { + background-color: darken(#fff, 1.5); + } + } + td { + width: 100%; + border: none; + } + a { + color: $body_font_color; + text-decoration: none; + } + .title { + @include fontsize(20); + @include fancy_sans; + color: #2a2a2a; + } + .category { + @include fontsize(12); + @include fancy_sans_bold; + text-transform: uppercase; + letter-spacing: 1px; + } + .num { + text-align: center; + } + .topic-users { width: 80px;} + .topic-posts, .topic-views { width: 20px; } + .topic-age { width: 40px;} +} +.topic-container { + max-width: 70%; + position: relative; + flex:1; + order: 2; + background: #fff; + z-index: 4; + margin: 3rem auto 0; + h1 { + @include fancy_sans_bold; + @include fontsize(28); + color: #2a2a2a; + line-height: 1; + margin: 0; + } + h2 { + @include fontsize(14); + margin: 0 0 1rem 0; + a { + color: $body_font_color; + text-decoration: none; + } + } + .topic-header { + border-bottom: 1px solid lighten($body_font_light, 20); + margin: 0 0 2rem 0; + } +} +#post-list { + list-style-type: none; + padding: 0; +} diff --git a/design/sass/_header.scss b/design/sass/_header.scss index 1214f9a..12fb641 100644 --- a/design/sass/_header.scss +++ b/design/sass/_header.scss @@ -27,8 +27,8 @@ header { margin: 3px 0 0 0; width: 60px; height: 60px; - background: #fff url('/media/img/logo-sm.svg') no-repeat; - //background: #fff url('/media/img/logo-blk.svg') no-repeat; + //background: #fff url('/media/img/logo-sm.svg') no-repeat; + background: #fff url('/media/img/logo-blk.svg') no-repeat; //background: #fff url('/media/img/logo-org.svg') no-repeat; background-size: 60px 60px; text-align: center; diff --git a/design/sass/_notes.scss b/design/sass/_notes.scss index df25c3c..eca3aaf 100644 --- a/design/sass/_notes.scss +++ b/design/sass/_notes.scss @@ -1,3 +1,6 @@ +.color{ + height: .5rem; +} main { width: 100%; display: flex ; @@ -84,7 +87,7 @@ main { font-weight: normal; overflow: hidden; white-space: nowrap; - color: darken($body_font_color, 10); + color: #2a2a2a; } .notebook { padding-right: 8px; diff --git a/design/sass/screenv1.scss b/design/sass/screenv1.scss index b55f9d9..768d748 100644 --- a/design/sass/screenv1.scss +++ b/design/sass/screenv1.scss @@ -9,3 +9,4 @@ @import "_forms.scss"; @import "_modal.scss"; @import "_notes.scss"; +@import "_forum.scss"; diff --git a/design/templates/accounts/change-settings.html b/design/templates/accounts/change-settings.html index a6e6ea6..e14a1e3 100644 --- a/design/templates/accounts/change-settings.html +++ b/design/templates/accounts/change-settings.html @@ -22,12 +22,5 @@ {% endblock %} diff --git a/design/templates/base.html b/design/templates/base.html index e02719b..cdbed90 100644 --- a/design/templates/base.html +++ b/design/templates/base.html @@ -18,7 +18,7 @@ {% block jsinclude %}{%endblock%} - +
+ {% block color %}{%endblock%}
{%comment%}