From 16f99c994f6b772506dc0a8871cd1f7e53b9a58f Mon Sep 17 00:00:00 2001 From: luxagraf Date: Thu, 6 Dec 2018 07:10:35 -0600 Subject: Added forum app and templates --- apps/forum/__init__.py | 0 apps/forum/admin.py | 18 + apps/forum/migrations/0001_initial.py | 109 +++ apps/forum/migrations/__init__.py | 0 apps/forum/models.py | 145 ++++ apps/forum/urls.py | 12 + apps/forum/views.py | 19 + design/templates/forum/topic_list.html | 1247 ++++++++++++++++++++++++++++++++ 8 files changed, 1550 insertions(+) create mode 100644 apps/forum/__init__.py create mode 100644 apps/forum/admin.py create mode 100644 apps/forum/migrations/0001_initial.py create mode 100644 apps/forum/migrations/__init__.py create mode 100644 apps/forum/models.py create mode 100644 apps/forum/urls.py create mode 100644 apps/forum/views.py create mode 100644 design/templates/forum/topic_list.html diff --git a/apps/forum/__init__.py b/apps/forum/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/forum/admin.py b/apps/forum/admin.py new file mode 100644 index 0000000..9fddd4e --- /dev/null +++ b/apps/forum/admin.py @@ -0,0 +1,18 @@ +from django.contrib import admin + +from .models import Topic, Category, Post + + +@admin.register(Topic) +class TopicAdmin(admin.ModelAdmin): + pass + + +@admin.register(Category) +class CategoryAdmin(admin.ModelAdmin): + pass + + +@admin.register(Post) +class PostAdmin(admin.ModelAdmin): + pass diff --git a/apps/forum/migrations/0001_initial.py b/apps/forum/migrations/0001_initial.py new file mode 100644 index 0000000..0785014 --- /dev/null +++ b/apps/forum/migrations/0001_initial.py @@ -0,0 +1,109 @@ +# Generated by Django 2.1.2 on 2018-12-02 16:38 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=120)), + ('slug', models.SlugField()), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('topic_count', models.PositiveIntegerField(default=0)), + ('topics_year', models.PositiveIntegerField(default=0)), + ('topics_month', models.PositiveIntegerField(default=0)), + ('topics_week', models.PositiveIntegerField(default=0)), + ], + options={ + 'verbose_name_plural': 'Categories', + }, + ), + migrations.CreateModel( + name='Post', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('post_type', models.CharField(choices=[('post', 'post'), ('reply', 'reply')], max_length=60)), + ('post_body_text', models.TextField(blank=True)), + ('post_body_html', models.TextField(blank=True, null=True)), + ('post_body_json', models.TextField(blank=True, null=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('date_delete', models.DateTimeField(blank=True, null=True)), + ('reply_count', models.PositiveIntegerField(default=0)), + ('quote_count', models.PositiveIntegerField(default=0)), + ('like_count', models.PositiveIntegerField(default=0)), + ('bookmark_count', models.PositiveIntegerField(default=0)), + ('spam_count', models.PositiveIntegerField(default=0)), + ('reads', models.PositiveIntegerField(default=0)), + ('inappropriate_count', models.PositiveIntegerField(default=0)), + ('score', models.IntegerField(default=0)), + ('vote_count', models.IntegerField(default=0)), + ('last_editor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='post_last_editor', to=settings.AUTH_USER_MODEL)), + ('reply_below_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='post_reply_below', to='forum.Post')), + ('reply_to_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='post_reply_to', to='forum.Post')), + ('reply_to_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='post_reply_to_user', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name_plural': 'Posts', + }, + ), + migrations.CreateModel( + name='Topic', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255)), + ('slug', models.SlugField()), + ('date_last_posted', models.DateTimeField(auto_now=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('date_deleted', models.DateTimeField(blank=True, null=True)), + ('date_bumped', models.DateTimeField(blank=True, null=True)), + ('views', models.PositiveIntegerField(default=0)), + ('posts_count', models.PositiveIntegerField(default=0)), + ('reply_count', models.PositiveIntegerField(default=0)), + ('like_count', models.PositiveIntegerField(default=0)), + ('bookmark_count', models.PositiveIntegerField(default=0)), + ('star_count', models.PositiveIntegerField(default=0)), + ('moderator_posts_count', models.PositiveIntegerField(default=0)), + ('vote_count', models.PositiveIntegerField(default=0)), + ('spam_count', models.PositiveIntegerField(default=0)), + ('illegal_count', models.PositiveIntegerField(default=0)), + ('inappropriate_count', models.PositiveIntegerField(default=0)), + ('visible', models.BooleanField(default=True)), + ('closed', models.BooleanField(default=False)), + ('pinned', models.BooleanField(default=False)), + ('archived', models.BooleanField(default=False)), + ('has_best_of', models.BooleanField(default=False)), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Category')), + ('highest_post', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='topic_highest_post', to='forum.Post')), + ('last_post_userj', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='topic_last_post_user', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='topic_user', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name_plural': 'Topics', + }, + ), + migrations.AddField( + model_name='post', + name='topic', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='forum.Topic'), + ), + migrations.AddField( + model_name='post', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='post_user', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/apps/forum/migrations/__init__.py b/apps/forum/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/forum/models.py b/apps/forum/models.py new file mode 100644 index 0000000..d0f6b6f --- /dev/null +++ b/apps/forum/models.py @@ -0,0 +1,145 @@ +from django.db import models +from django.contrib import auth +from django.urls import reverse +from django.conf import settings + + +class CategoryManager(models.Manager): + + # create category + def create_category(self, title, slug=''): + + if slug == '': + slug = title.lower().replace(' ', '-') + + category = self.create(title=title, slug=slug) + + return category + + # get or create + def get_or_create(self, title): + try: + category = Category.objects.get(title=title) + except Category.DoesNotExist: + return (self.create_category(title), True) + + return (category, False) + + +class Category(models.Model): + + title = models.CharField(max_length=120) + slug = models.SlugField() + + date_created = models.DateTimeField(auto_now=False, auto_now_add=True) + date_updated = models.DateTimeField(auto_now=True, auto_now_add=False) + + topic_count = models.PositiveIntegerField(default=0) + topics_year = models.PositiveIntegerField(default=0) + topics_month = models.PositiveIntegerField(default=0) + topics_week = models.PositiveIntegerField(default=0) + + class Meta: + verbose_name_plural = "Categories" + + objects = CategoryManager() + + def __unicode__(self): + return self.title + + +class TopicManager(models.Manager): + + # create category + def create_topic(self, title, category, user, slug=''): + + if slug == '': + slug = title.lower().replace(' ', '-') + + topic = self.create(title=title, slug=slug, category=category, user=user) + + return topic + + +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) + highest_post = models.ForeignKey('Post', on_delete=models.CASCADE, related_name='topic_highest_post', blank=True, null=True) + + title = models.CharField(max_length=255) + slug = models.SlugField() + + date_last_posted = models.DateTimeField(auto_now=True, auto_now_add=False, blank=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) + date_deleted = models.DateTimeField(blank=True, null=True) + date_bumped = models.DateTimeField(blank=True, null=True) + + views = models.PositiveIntegerField(default=0) + posts_count = models.PositiveIntegerField(default=0) + reply_count = models.PositiveIntegerField(default=0) + like_count = models.PositiveIntegerField(default=0) + bookmark_count = models.PositiveIntegerField(default=0) + star_count = models.PositiveIntegerField(default=0) + moderator_posts_count = models.PositiveIntegerField(default=0) + vote_count = models.PositiveIntegerField(default=0) + spam_count = models.PositiveIntegerField(default=0) + illegal_count = models.PositiveIntegerField(default=0) + inappropriate_count = models.PositiveIntegerField(default=0) + + visible = models.BooleanField(default=True) + closed = models.BooleanField(default=False) + pinned = models.BooleanField(default=False) + archived = models.BooleanField(default=False) + has_best_of = models.BooleanField(default=False) + + objects = TopicManager() + + class Meta: + verbose_name_plural = "Topics" + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse('forum:topic-detail', kwargs={"slug": self.slug, "pk": self.pk}) + + +class Post(models.Model): + topic = models.ForeignKey(Topic, on_delete=models.CASCADE) + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='post_user') + reply_to_post = models.ForeignKey('self', on_delete=models.CASCADE, related_name='post_reply_to', blank=True, null=True) + reply_to_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='post_reply_to_user', blank=True, null=True) + reply_below_post = models.ForeignKey('self', on_delete=models.CASCADE, related_name='post_reply_below', blank=True, null=True) + last_editor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='post_last_editor', blank=True, null=True) + POST_TYPE_CHOICES = ( + ('post', 'post'), + ('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) + + 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) + date_delete = models.DateTimeField(blank=True, null=True) + + reply_count = models.PositiveIntegerField(default=0) + quote_count = models.PositiveIntegerField(default=0) + like_count = models.PositiveIntegerField(default=0) + bookmark_count = models.PositiveIntegerField(default=0) + spam_count = models.PositiveIntegerField(default=0) + reads = models.PositiveIntegerField(default=0) + inappropriate_count = models.PositiveIntegerField(default=0) + + score = models.IntegerField(default=0) + vote_count = models.IntegerField(default=0) + + class Meta: + verbose_name_plural = "Posts" + + def __str__(self): + return '%s - %s' % (self.raw, self.topic.title) diff --git a/apps/forum/urls.py b/apps/forum/urls.py new file mode 100644 index 0000000..79e2e0d --- /dev/null +++ b/apps/forum/urls.py @@ -0,0 +1,12 @@ +from django.urls import path + +from .views import ( + TopicListView, +) + +app_name = "forum" + +urlpatterns = [ + path(r't/', TopicListView.as_view(), name='topic-list',), + path(r'', TopicListView.as_view(), name='topic-redirect',), +] diff --git a/apps/forum/views.py b/apps/forum/views.py new file mode 100644 index 0000000..bc7cc74 --- /dev/null +++ b/apps/forum/views.py @@ -0,0 +1,19 @@ +from django.views.generic import CreateView, ListView, UpdateView, DeleteView +from django.views.generic.detail import DetailView +from django.views.generic.base import View, RedirectView +from django.shortcuts import get_object_or_404, render, redirect +from django.urls import reverse, reverse_lazy + +from rest_framework import viewsets +from rest_framework.response import Response +from rest_framework.decorators import list_route +from rest_framework import permissions + +#from .serializers import NoteSerializer, NotebookSerializer +from .models import Topic, Category, Post +#from .forms import NoteForm, NotebookForm +from utils.views import LoggedInViewWithUser + + +class TopicListView(LoggedInViewWithUser, ListView): + model = Topic diff --git a/design/templates/forum/topic_list.html b/design/templates/forum/topic_list.html new file mode 100644 index 0000000..89a165e --- /dev/null +++ b/design/templates/forum/topic_list.html @@ -0,0 +1,1247 @@ +{% extends 'base.html' %} +{% block content %} +
+
+

Forum

+ +

Welcome to the Note forums. Ask questions, show others your workflow, post tips and tricks. There's even a Lounge where you can post on anything you want (nearly, be sure to read the Note forum guidelines).

+

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.

+
+
+ + + + + + + + + + + + + {% for object in object_list %} + + + + {% endfor %} +
TopicCategoryUsersRepliesViewsActivity
+
+{% endblock %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TopicCategoryUsersRepliesViewsActivity
Meta + + + + + + + + + 22 + +3741d
Meta + + + + + + + + 5 + +6.2kMay 31
Processing + + + + + + + + + 12 + +1041m
Software + + + + + + 4 + +711h
Processing + + + + + + + + + 17 + +4281h
Processing + + + + + + + + + 12 + +1032h
Processing + + + + + + + + + 35 + +4422h
G'MIC + + + + + + + + + 30 + +6353h
RawTherapee + + + + + + 2 + +975h
Processing + + + + + + + + + 19 + +6985h
Processing + + + + + + + + + 33 + +5977h
Processing + + + + + + + + + 40 + +7897h
RawTherapee + + + + + + 1 + +817h
Rapid Photo Downloader + + + + + + + + + 25 + +47410h
Processing + + + + + + + + + 17 + +36211h
Rapid Photo Downloader + + + + + + + 4 + +9116h
G'MIC + + + + + + + + 11 + +12116h
RawTherapee + + + + + + + + 7 + +11916h
G'MIC + + + + + + 3 + +8717h
Software + + + + + + + 2 + +6718h
Processing + + + + + + + + + 14 + +18820h
Software + + + + + 0 + +3121h
Processing + + + + + + + + + 8 + +9921h
G'MIC + + + + + + + 9 + +18022h
Natron + + + + + 0 + +271d
RawTherapee + + + + + + + + + 35 + +7831d
Natron + + + + + + + + + 33 + +2.1k1d
darktable + + + + + 0 + +761d
Natron + + + + + + 2 + +481d
Software + + + + + + 1 + +4091d
+ + + + + + + + + + + + + + + + + +{% block extra %} +{% if login_form %} + +{% 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%} -- cgit v1.2.3-70-g09d2