diff options
author | luxagraf <sng@luxagraf.net> | 2019-01-13 11:42:01 -0600 |
---|---|---|
committer | luxagraf <sng@luxagraf.net> | 2019-01-13 11:42:01 -0600 |
commit | 5b9343d77d8321e44d1ffc60769c651771dc38dd (patch) | |
tree | 8bbce1b415fbf2fd4c4ee1a7913ca41d362216ec | |
parent | 261f9df4911f861a71e11eb3f0bfbe1a5a5d12b9 (diff) |
Refactored Javascript, started on forums
27 files changed, 651 insertions, 74 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 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 @@ </form> </main> <script> -if (typeof(document.getElementById('id_photo')) != 'undefined' && document.getElementById('id_photo') != null) { - var input = document.getElementById('id_photo'); - input.fname = document.getElementById('filename'); - input.addEventListener('change', function(e){ - e.target.fname.innerHTML = e.target.value.split("\\")[2]; - }); -} </script> {% 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%} <script async src="/media/js/main.min.js?{%now "u"%}"></script> </head> -<body class="{% block bodyclass %}{% endblock %}"> +<body id="{% block bodyid %}{%endblock%}" class="{% block bodyclass %}{% endblock %}"> <div class="head-wrapper"> <header> <nav class="left"> @@ -73,6 +73,7 @@ </nav> </header> </div> + {% block color %}{%endblock%} <div class="wrapper"> {%comment%}<ul class="breadcrumb" id="breadcrumbs" itemscope itemtype="http://data-vocabulary.org/Breadcrumb"> <li> diff --git a/design/templates/forum/topic_detail.html b/design/templates/forum/topic_detail.html new file mode 100644 index 0000000..3873375 --- /dev/null +++ b/design/templates/forum/topic_detail.html @@ -0,0 +1,114 @@ +{% extends 'base.html' %} +{% load timesinceabbr %} +{% block bodyid %}body-topic{%endblock%} +{% block content %} +<main class="wide"> + <div class="">{% if messages %} + <ul class="messages"> + {% for message in messages %} + <li{% if message.tags %} class="{{ message.tags }}"{% endif %}> + {% if 'safe' in message.tags %}{{ message|safe }}{% else %}{{ message }}{% endif %} + </li> + {% endfor %} + </ul> + {% endif %} + </div> + <article class="topic-container single-col"> + <div class="topic-header"> + <h1>{{object.title}}</h1> + <h2 class="category-name"> + <a class="name" href="{{object.category.get_absolute_url}}"><span class="color-box" style="background-color: {{object.category.color_rgb}}"></span><span class="strong nb-name">{{object.category.name}}</span></a> + </h2> + </div> + <ol id="post-list">{% for post in object.post_set.all %} + <li class="post-list-item"> + <div class="post-header"> + <div class="avatar"><img src="{{post.user.get_avatar_url}}" alt="avatar for {{post.user.username}}" /></div> + <div class="username"> + {{post.user.username}} + </div> + <div class="user-title"> + {{post.user.category}} + </div> + <div class="post-created"> + {{post.date_created|timesinceabbr}} + </div> + </div> + <div class="post-body"> + {{post.body_html}} + </div> + <div class="post-footer"> + + </div> + </li> + {% endfor %}</ol> + + +<table id="" class="topic-list"> + <thead> + <tr> + <th data-sort-order="default" class="default">Topic</th> + <th data-sort-order="users" class="topic-users sortable num"></th> + <th data-sort-order="posts" class="topic-posts sortable num">Replies</th> + <th data-sort-order="views" class="topic-views sortable num">Views</th> + <th data-sort-order="activity" class="topic-age">Activity</th> + </tr> + </thead> + <tbody> + {% for object in object_list %} + <tr id="{{object.id}}" class="topic-list-item"> + <td class="" colspan="1"> + {% if object.statuses%}<div class="topic-statuses"> + <a href="" title="" class="topic-status"><svg class="fa d-icon d-icon-thumbtack svg-icon pinned svg-string" xmlns="http://www.w3.org/2000/svg"><use xlink:href="#thumbtack"></use></svg></a> + </div>{%endif%} + <a href="{{object.get_absolute_url}}" class="title" data-topic-id="{{object.id}}">{{object.title}}</a> + <span class="topic-post-badges"></span> + {% if object.pinned %}<div class="topic-excerpt">{{object.except}} + <a href="/t/lets-use-math-my-nerds/10030">read more</a>{%endif%} + <div class="category"> + <a href="{{object.category.get_absolute_url}}"><span class="color-box" style="background-color: {{object.category.color_rgb}}"></span>{{object.category}}</a> + </div> + </td> + <td class="topic-users"> + {% for user in object.user_set.all %}<a href="{{user.get_forum_url}}"><img alt="avatar for {{user}}" src="{{user.get_avatar_url}}" /></a>{%endfor%} + </td> + <td class="topic-posts center"> + {{object.reply_count}} + </td> + <td class="topic-views center"> + {{object.views}} + </td> + <td class="topic-age center"> + </td> + </tr> + {% endfor %} +</table> + </article> +</main> +{% endblock %} + + + + + + +{% block extra %} +{% if login_form %} +<div class="overlay-content" id="js-overlay-content" style="display: none;"> + {% include 'lib/login.html' with form=login_form %} +</div> +{% endif %} +{%endblock%} +{% block jsdomready %} +{% if login_form %} + // Select your overlay trigger + var trigger = document.querySelector('#overlay-trigger'); + trigger.addEventListener('click', function(e){ + e.preventDefault(); + novicell.overlay.create({ + 'selector': trigger.getAttribute('data-element'), + 'class': 'selector-overlay', + }); + }); +{% endif %} +{%endblock%} diff --git a/design/templates/forum/topic_list.html b/design/templates/forum/topic_list.html index 89a165e..5f933e9 100644 --- a/design/templates/forum/topic_list.html +++ b/design/templates/forum/topic_list.html @@ -1,4 +1,12 @@ {% extends 'base.html' %} +{% block bodyid %}body-forum{%endblock%} +{% block jsinclude %} + <script> + window.nbdata = [ {%spaceless%}{% for object in category_list %} {value: '{{object.get_absolute_url}}', label: '<span class="color-box" style="background-color: {{object.color_rgb}}"></span><span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}' },{%endfor%} {value: '/forum/', label: '<span class="strong nb-name">All Categories</span>', selected: true, },{%endspaceless%} + ] + </script> +<script src="/media/js/choices.min.js"></script> +{%endblock%} {% block content %} <main class="wide"> <div class="single-col"> @@ -8,35 +16,69 @@ <p>The goal is for users of all levels to learn and share with each other, please treat this discussion forum with the same respect you would a public park. Remember to be kind, courteous and forgiving.</p> </span> </div> + <div class=""> + + <div id="list-header"> + <div id="choices-container" class="flex-wrapper"> + <ul class="list dropmenu-list list-style-none notebook-list" id="category-list">{% for object in category_list %} + <li ><a class="name" href="{{object.get_absolute_url}}"><span class="color-box" style="background-color: {{object.color_rgb}}"></span><span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}</a></li> + {%endfor%}</ul> + </div> + </div> + + + + + + + + {% if messages %} + <ul class="messages"> + {% for message in messages %} + <li{% if message.tags %} class="{{ message.tags }}"{% endif %}> + {% if 'safe' in message.tags %}{{ message|safe }}{% else %}{{ message }}{% endif %} + </li> + {% endfor %} + </ul> + {% endif %} + </div> <table id="" class="topic-list"> <thead> <tr> <th data-sort-order="default" class="default">Topic</th> - <th data-sort-order="category" class="category sortable">Category</th> - <th data-sort-order="posters" class="posters">Users</th> - <th data-sort-order="posts" class="posts sortable num">Replies</th> - <th data-sort-order="views" class="views sortable num">Views</th> - <th data-sort-order="activity" class="activity sortable num">Activity</th> + <th data-sort-order="users" class="topic-users sortable num"></th> + <th data-sort-order="posts" class="topic-posts sortable num">Replies</th> + <th data-sort-order="views" class="topic-views sortable num">Views</th> + <th data-sort-order="activity" class="topic-age">Activity</th> </tr> </thead> -<tbody> + <tbody> {% for object in object_list %} - <tr data-topic-id="" id="ember1226" class="topic-list-item category-meta has-excerpt pinned ember-view"> - <td class="main-link clearfix" colspan="1"> - <span class="link-top-line"> - <div class="topic-statuses"> - <a href="" title="This topic is pinned for you; it will display at the top of its category" class="topic-status"><svg class="fa d-icon d-icon-thumbtack svg-icon pinned svg-string" xmlns="http://www.w3.org/2000/svg"><use xlink:href="#thumbtack"></use></svg></a> - </div> - <a href="/t/lets-use-math-my-nerds/10030" class="title raw-link raw-topic-link" data-topic-id="10030">Let’s use math my nerds</a> - <span class="topic-post-badges"></span> - </span> - <div class="topic-excerpt">For a while we had either to render math outside of the forum or using some kind of ascii art for them. But this is over now. We added the offical math plugin to our instance. And yes asciimath is enabled too. -$$ -E=mc… - <a href="/t/lets-use-math-my-nerds/10030">read more</a> - </div> - </td> - </tr> + <tr id="{{object.id}}" class="topic-list-item"> + <td class="" colspan="1"> + {% if object.statuses%}<div class="topic-statuses"> + <a href="" title="" class="topic-status"><svg class="fa d-icon d-icon-thumbtack svg-icon pinned svg-string" xmlns="http://www.w3.org/2000/svg"><use xlink:href="#thumbtack"></use></svg></a> + </div>{%endif%} + <a href="{{object.get_absolute_url}}" class="title" data-topic-id="{{object.id}}">{{object.title}}</a> + <span class="topic-post-badges"></span> + {% if object.pinned %}<div class="topic-excerpt">{{object.except}} + <a href="/t/lets-use-math-my-nerds/10030">read more</a>{%endif%} + <div class="category"> + <a href="{{object.category.get_absolute_url}}"><span class="color-box" style="background-color: {{object.category.color_rgb}}"></span>{{object.category}}</a> + </div> + </td> + <td class="topic-users"> + {% for user in object.user_set.all %}<a href="{{user.get_forum_url}}"><img alt="avatar for {{user}}" src="{{user.get_avatar_url}}" /></a>{%endfor%} + </td> + <td class="topic-posts center"> + {{object.reply_count}} + </td> + <td class="topic-views center"> + {{object.views}} + </td> + <td class="topic-age center"> + </td> + </tr> {% endfor %} </table> </main> diff --git a/design/templates/notes/notebook_detail.html b/design/templates/notes/notebook_detail.html index 49717ca..43ec1df 100644 --- a/design/templates/notes/notebook_detail.html +++ b/design/templates/notes/notebook_detail.html @@ -1,9 +1,13 @@ {% extends 'base.html' %} +{% block bodyid %}body-notebook{%endblock%} {% block extrastyles %} <script async src="/media/js/vanilla-picker.min.js"></script> {% endblock %} +{% block color %} +{% if object.color_rgb %}<div class="color" style="background-color: {{object.color_rgb}}"></div>{%endif%} +{%endblock%} {% block content %} <main> <article class="note-container single-col"> diff --git a/design/templates/notes/notes_list.html b/design/templates/notes/notes_list.html index 0799a1c..5b050b4 100644 --- a/design/templates/notes/notes_list.html +++ b/design/templates/notes/notes_list.html @@ -1,4 +1,6 @@ {% extends 'base.html' %} +{% block bodyid %}body-notebook{%endblock%} + {% block content %} <main> <div class="note-container"> diff --git a/design/templates/notes/notes_list_by_tag.html b/design/templates/notes/notes_list_by_tag.html new file mode 100644 index 0000000..d7cc350 --- /dev/null +++ b/design/templates/notes/notes_list_by_tag.html @@ -0,0 +1,71 @@ +{% extends 'base.html' %} +{% block jsinclude %} + <script> + window.nbdata = [ {%spaceless%}{% for object in notebook_list %} {value: '{{object.get_absolute_url}}', label: '<span class="color-box" style="background-color: {{object.color_rgb}}"></span><span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}' },{%endfor%} {value: '/nb/', label: '<span class="strong nb-name">All Notebooks</span>', selected: true, },{%endspaceless%} + ] + window.tagdata = [ {% for object in tag_list %} {value: '{{object.get_absolute_url}}', label: '{% if object.color_rgb %}<span class="color-box" style="background-color: {{object.color_rgb}}"></span>{%endif%}<span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}' },{%endfor%} {value: '/t/', label: '<span class="strong nb-name">All Tags</span>', selected: true, }, + ] + </script> +<script src="/media/js/choices.min.js"></script> +{%endblock%} +{% block content %} +<main> + <div class="note-container"> + <div class="note-hed-wrapper"> + <h1 class="note-hed">Notes</h1> + {% if messages %} + <ul class="messages"> + {% for message in messages %} + <li{% if message.tags %} class="{{ message.tags }}"{% endif %}> + {% if 'safe' in message.tags %}{{ message|safe }}{% else %}{{ message }}{% endif %} + </li> + {% endfor %} + </ul> + {% endif %} + {% if tag_list|length >= 1%}<h2 class="note-subhed">Tagged with: {% for tag in tag%}<a href="{{tag.slug}}">{{tag.name}}</a>{%endfor%}</h2>{%endif%} + <div id="choices-container" class="flex-wrapper"> + <ul class="list dropmenu-list list-style-none notebook-list" id="notebook-list">{% for object in notebook_list %} + <li ><a class="name" href="{{object.get_absolute_url}}"><span class="color-box" style="background-color: {{object.color_rgb}}"></span><span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}</a></li> + {%endfor%}</ul> + <ul class="list dropmenu-list list-style-none notebook-list" id="tags-list">{% for object in tag_list %} + <li><a href="{{object.get_absolute_url}}">{% if object.color_rgb %}<span class="color-box" style="background-color: {{object.color_rgb}}"></span>{%endif%}<span class="strong nb-name">{{object.name}}</span> x {{object.note_count}}</a></li> + {%endfor%}</ul> + </div> + </div> + {%comment%} <label for="choices-single-default">Default</label> +<select class="form-control" data-trigger name="choices-single-default" id="choices-single-default" placeholder="This is a search placeholder"> +<option placeholder>This is a placeholder</option> + {% for object in notebook_list %} + <option value="{{object.name}}" id="">{{object.name}}</option> + {% endfor %} +</select>{%endcomment%} + + <ul class="list-note-preview">{% for object in object_list %} + {% include "notes/partials/note_list.html" with object=object %} + {% endfor %}</ul> + </div>{% if tags|length >= 1%} + {%comment%}<aside class="note-list-container"> + <div class="svg-wrapper"><svg class="svg-icon-arrow"> + <svg viewBox="0 0 16 13" id="shape-double-arrow" width="100%" height="100%"><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="square"><g id="Showing-post-info" transform="translate(-297.000000, -105.000000)" stroke="currentColor"><g transform="translate(305.000000, 111.500000) scale(-1, 1) rotate(-180.000000) translate(-305.000000, -111.500000) translate(297.000000, 105.000000)"><path d="M2.20710678,6.5 L6.85355339,1.85355339 L7.20710678,1.5 L6.5,0.792893219 L6.14644661,1.14644661 L1.14644661,6.14644661 L1.05805826,6.23483496 L0.792893219,6.5 L1.14644661,6.85355339 L6.14644661,11.8535534 L6.5,12.2071068 L7.20710678,11.5 L6.85355339,11.1464466 L2.20710678,6.5 Z" id="Combined-Shape"></path><path d="M10.2071068,6.5 L14.8535534,1.85355339 L15.2071068,1.5 L14.5,0.792893219 L14.1464466,1.14644661 L9.14644661,6.14644661 L9.05805826,6.23483496 L8.79289322,6.5 L9.14644661,6.85355339 L14.1464466,11.8535534 L14.5,12.2071068 L15.2071068,11.5 L14.8535534,11.1464466 L10.2071068,6.5 Z" id="Combined-Shape"></path></g></g></g></svg> + </svg></div> + <div class=""> + <ul class="list-note-preview">{% for obj in notes_list %} + <li> + <a href="{{obj.get_absolute_url}}"> + <h4>{{obj.title}}</h4> + <div class="note-preview">{{obj.body_text|truncatewords:12}}</div> + </a> + </li> + {% endfor %}</ul> + </div> + </aside>{%endcomment%} + {%else%} + <!--<div class="balance-container-left"> + </div>--> + {%endif%} + <!--<div class="balance-container"> + </div>--> +</main> +{% endblock %} +{% block jsdomready %} +{% endblock %} diff --git a/scripts/src/account-edit.js b/scripts/src/account-edit.js index c9d3e9a..b592666 100644 --- a/scripts/src/account-edit.js +++ b/scripts/src/account-edit.js @@ -1 +1,7 @@ -getElementById('FileField').value = getElementById('file-upload-wrapper').value; +if (typeof(document.getElementById('id_photo')) != 'undefined' && document.getElementById('id_photo') != null) { + var input = document.getElementById('id_photo'); + input.fname = document.getElementById('filename'); + input.addEventListener('change', function(e){ + e.target.fname.innerHTML = e.target.value.split("\\")[2]; + }); +} diff --git a/scripts/src/forum-categories.js b/scripts/src/forum-categories.js new file mode 100644 index 0000000..b389d43 --- /dev/null +++ b/scripts/src/forum-categories.js @@ -0,0 +1,15 @@ +document.addEventListener("DOMContentLoaded", function () { + if (typeof(document.getElementById('body-forum')) != 'undefined' && document.getElementById('body-forum') != null) { + if (typeof(document.getElementById('choices-container')) != 'undefined' && document.getElementById('choices-container') != null) { + console.log(document.getElementById('category-list')); + console.log('firing'); + initChoicesMenu({ + data: window.nbdata, + wrapper_classes: ['choices-wrapper', 'choices-wrapper-notebooks'], + replace_el: document.getElementById('category-list'), + choices_name: "choices-category", + choices_id: "choices-category" + }); + } + } +}); diff --git a/scripts/src/note-list.js b/scripts/src/note-list.js index 2b82da1..cd5b58d 100644 --- a/scripts/src/note-list.js +++ b/scripts/src/note-list.js @@ -21,19 +21,23 @@ function initChoicesMenu(obj) { choices_holder.addEventListener('choice', choicePageChanger); } -if (typeof(document.getElementById('choices-container')) != 'undefined' && document.getElementById('choices-container') != null) { - initChoicesMenu({ - data: window.nbdata, - wrapper_classes: ['choices-wrapper', 'choices-wrapper-notebooks'], - replace_el: document.getElementById('notebook-list'), - choices_name: "choices-notebooks", - choices_id: "choices-notebooks" - }); - initChoicesMenu({ - data: window.tagdata, - wrapper_classes: ['choices-wrapper', 'choices-wrapper-tags'], - replace_el: document.getElementById('tags-list'), - choices_name: "choices-tags", - choices_id: "choices-tags" - }); -} +document.addEventListener("DOMContentLoaded", function () { + if (typeof(document.getElementById('body-notebook')) != 'undefined' && document.getElementById('body-notebook') != null) { + if (typeof(document.getElementById('choices-container')) != 'undefined' && document.getElementById('choices-container') != null) { + initChoicesMenu({ + data: window.nbdata, + wrapper_classes: ['choices-wrapper', 'choices-wrapper-notebooks'], + replace_el: document.getElementById('notebook-list'), + choices_name: "choices-notebooks", + choices_id: "choices-notebooks" + }); + initChoicesMenu({ + data: window.tagdata, + wrapper_classes: ['choices-wrapper', 'choices-wrapper-tags'], + replace_el: document.getElementById('tags-list'), + choices_name: "choices-tags", + choices_id: "choices-tags" + }); + } + } +}); diff --git a/scripts/src/notebook-edit.js b/scripts/src/notebook-edit.js index 7d0aa8f..a6ba689 100644 --- a/scripts/src/notebook-edit.js +++ b/scripts/src/notebook-edit.js @@ -17,8 +17,12 @@ function initNotebookEditor() { document.getElementById('btn-js-hide').classList.add('hide'); btn.classList.remove('hide'); + btn.isHidden = true; btn.addEventListener('click', function(e){ e.preventDefault(); + e.target.textContent = e.target.isHidden ? 'Save' : 'Edit'; + e.target.isHidden = !e.target.isHidden; + e.target.classList.toggle('save'); edit_notebook(title, form, picker, fname, window.url); }, false); } @@ -68,6 +72,7 @@ function initMultiNotebookEditor(notebooks){ btn.isHidden = true; function clickHandler(e) { e.preventDefault(); + console.log(e.target.textContent); e.target.textContent = e.target.isHidden ? 'Save' : 'Edit'; e.target.isHidden = !e.target.isHidden; e.target.classList.toggle('save'); @@ -131,16 +136,19 @@ function notebookCallback(title, request) { console.log('server error'); } } -if (typeof(document.getElementById('nb-edit-form')) != 'undefined' && document.getElementById('nb-edit-form') != null) { - initNotebookEditor(); -} -if (typeof(document.getElementById('nb-create-form')) != 'undefined' && document.getElementById('nb-create-form') != null && document.getElementById('nb-list-home') !== null) { - var newnotebook = document.getElementById('notebook-wrapper'); - newnotebook.classList.add('hide'); - var notebookAddForm = document.getElementById('nb-create-form'); - var btn = document.getElementById('add_id_notebook'); - addNotebookModal(notebookAddForm, btn); - var create_form = document.getElementById('nb-create-form'); - activatePicker(create_form, create_form.getElementsByTagName('fieldset')['color-picker']); - initMultiNotebookEditor(document.getElementsByClassName('nb-list-item')); -} + +document.addEventListener("DOMContentLoaded", function () { + if (typeof(document.getElementById('nb-edit-form')) != 'undefined' && document.getElementById('nb-edit-form') != null) { + initNotebookEditor(); + } + if (typeof(document.getElementById('nb-create-form')) != 'undefined' && document.getElementById('nb-create-form') != null && document.getElementById('nb-list-home') !== null) { + var newnotebook = document.getElementById('notebook-wrapper'); + newnotebook.classList.add('hide'); + var notebookAddForm = document.getElementById('nb-create-form'); + var btn = document.getElementById('add_id_notebook'); + addNotebookModal(notebookAddForm, btn); + var create_form = document.getElementById('nb-create-form'); + activatePicker(create_form, create_form.getElementsByTagName('fieldset')['color-picker']); + initMultiNotebookEditor(document.getElementsByClassName('nb-list-item')); + } +}); |