From c0f0519c05f4407bd3a30bafa078aa4185483041 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Sat, 24 Mar 2018 00:00:38 -0400 Subject: [PATCH] Add event comments, move photos to the sidebar. Fixes #26 --- events/admin.py | 8 +- events/forms.py | 7 +- events/migrations/0020_add_event_comments.py | 47 +++++++++ events/models/events.py | 21 ++++ events/views.py | 18 +++- get_together/settings.py | 1 + .../get_together/events/show_event.html | 96 ++++++++++++++----- get_together/urls.py | 1 + get_together/views/events.py | 4 +- 9 files changed, 173 insertions(+), 30 deletions(-) create mode 100644 events/migrations/0020_add_event_comments.py diff --git a/events/admin.py b/events/admin.py index 7bd6586..01c1966 100644 --- a/events/admin.py +++ b/events/admin.py @@ -5,7 +5,7 @@ from django.utils.safestring import mark_safe from .models.locale import Language, Continent, Country, SPR, City from .models.profiles import UserProfile, Organization, Team, Member, Category, Topic from .models.search import Searchable -from .models.events import Place, Event, EventPhoto, CommonEvent, Attendee +from .models.events import Place, Event, EventComment, EventPhoto, CommonEvent, Attendee admin.site.register(Language) admin.site.register(Continent) @@ -60,12 +60,18 @@ class EventAdmin(admin.ModelAdmin): admin.site.register(Event, EventAdmin) class EventPhotoAdmin(admin.ModelAdmin): + raw_id_fields = ('event',) list_display = ('title', 'event', 'view') def view(self, photo): return mark_safe('' % (photo.src.url, photo.thumbnail.url)) view.short_description = 'Photo' admin.site.register(EventPhoto, EventPhotoAdmin) +class EventCommentAdmin(admin.ModelAdmin): + raw_id_fields = ('event', 'author') + list_display = ('event', 'author', 'status', 'created_time') +admin.site.register(EventComment, EventCommentAdmin) + class CommonEventAdmin(admin.ModelAdmin): raw_id_fields = ('place', 'city', 'spr', 'country') list_display = ('__str__', 'participant_count', 'organization', 'start_time', 'country', 'spr', 'city') diff --git a/events/forms.py b/events/forms.py index e5476b8..af7af1d 100644 --- a/events/forms.py +++ b/events/forms.py @@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.models import User from .models.profiles import Team, UserProfile -from .models.events import Event, CommonEvent, Place, EventPhoto +from .models.events import Event, EventComment ,CommonEvent, Place, EventPhoto from datetime import time from time import strptime, strftime @@ -201,6 +201,11 @@ class UploadEventPhotoForm(forms.ModelForm): model = EventPhoto fields = ['src', 'title', 'caption'] +class EventCommentForm(forms.ModelForm): + class Meta: + model = EventComment + fields = ['body'] + class NewPlaceForm(forms.ModelForm): class Meta: model = Place diff --git a/events/migrations/0020_add_event_comments.py b/events/migrations/0020_add_event_comments.py new file mode 100644 index 0000000..8141028 --- /dev/null +++ b/events/migrations/0020_add_event_comments.py @@ -0,0 +1,47 @@ +# Generated by Django 2.0 on 2018-03-24 02:55 + +import datetime +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0019_add_org_slug'), + ] + + operations = [ + migrations.CreateModel( + name='EventComment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('body', models.TextField()), + ('created_time', models.DateTimeField(db_index=True, default=datetime.datetime.now)), + ('status', models.SmallIntegerField(choices=[(-1, 'Removed'), (0, 'Pending'), (1, 'Approved')], db_index=True, default=1)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='eventcomment', + name='author', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.UserProfile'), + ), + migrations.AddField( + model_name='eventcomment', + name='event', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.Event'), + ), + migrations.AddField( + model_name='eventcomment', + name='parent', + field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='events.EventComment'), + ), + ] diff --git a/events/models/events.py b/events/models/events.py index 9ac8093..64211d3 100644 --- a/events/models/events.py +++ b/events/models/events.py @@ -5,6 +5,7 @@ from django.utils.translation import ugettext_lazy as _ from django.shortcuts import reverse from rest_framework import serializers +from mptt.models import MPTTModel, TreeForeignKey from imagekit.models import ImageSpecField from imagekit.processors import ResizeToFill @@ -198,6 +199,26 @@ class EventPhoto(models.Model): format='JPEG', options={'quality': 60}) +class EventComment(MPTTModel): + REMOVED=-1 + PENDING=0 + APPROVED=1 + + STATUSES = [ + (REMOVED, _("Removed")), + (PENDING, _("Pending")), + (APPROVED, _("Approved")), + ] + author = models.ForeignKey(UserProfile, on_delete=models.CASCADE) + event = models.ForeignKey(Event, related_name='comments', on_delete=models.CASCADE) + body = models.TextField() + created_time = models.DateTimeField(default=datetime.datetime.now, db_index=True) + status = models.SmallIntegerField(choices=STATUSES, default=APPROVED, db_index=True) + parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True, on_delete=models.SET_NULL) + + def __str__(self): + return '%s at %s' % (self.author, self.created_time) + class CommonEvent(models.Model): name = models.CharField(max_length=150, verbose_name=_('Event Name')) organization = models.ForeignKey(Organization, null=True, blank=True, on_delete=models.CASCADE) diff --git a/events/views.py b/events/views.py index 861d015..43b15c5 100644 --- a/events/views.py +++ b/events/views.py @@ -7,9 +7,10 @@ from rest_framework.decorators import api_view, throttle_classes from rest_framework.response import Response from .models.search import Searchable, SearchableSerializer -from .models.events import Event, Place, PlaceSerializer, Attendee +from .models.events import Event, EventComment, Place, PlaceSerializer, Attendee from .models.locale import Country ,CountrySerializer, SPR, SPRSerializer, City, CitySerializer from .models.profiles import Team, UserProfile, Member +from .forms import EventCommentForm import simplejson @@ -126,3 +127,18 @@ def attend_event(request, event_id): messages.add_message(request, messages.SUCCESS, message=_("We'll see you there!")) return redirect(event.get_absolute_url()) +def comment_event(request, event_id): + event = Event.objects.get(id=event_id) + if request.user.is_anonymous: + messages.add_message(request, messages.WARNING, message=_("You must be logged in to comment.")) + return redirect(event.get_absolute_url()) + + if request.method == 'POST': + new_comment = EventComment(author=request.user.profile, event=event) + comment_form = EventCommentForm(request.POST, instance=new_comment) + if comment_form.is_valid(): + new_comment = comment_form.save() + return redirect(event.get_absolute_url()+'#comment-%s'%new_comment.id) + + return redirect(event.get_absolute_url()) + diff --git a/get_together/settings.py b/get_together/settings.py index 230837a..c51a411 100644 --- a/get_together/settings.py +++ b/get_together/settings.py @@ -46,6 +46,7 @@ INSTALLED_APPS = [ 'social_django', 'imagekit', 'imagekit_cropper', + 'mptt', 'get_together', 'events', diff --git a/get_together/templates/get_together/events/show_event.html b/get_together/templates/get_together/events/show_event.html index 89393d5..b75c8f4 100644 --- a/get_together/templates/get_together/events/show_event.html +++ b/get_together/templates/get_together/events/show_event.html @@ -18,9 +18,9 @@ position: relative; } .gt-profile .gt-profile-badges { - position: absolute; + position: relative; top: 16px; - left: 6px; + left: -42px; } .table td, .table th { border-top: none; @@ -69,10 +69,76 @@ {% endif %} -
+ +
+
+ +
+
+

Comments

+
+
+ {% load mptt_tags %} +
    + {% recursetree event.comments.all %} +
    +
    +
    +
    + + {% for badge in node.author.user.account.badges.all %}{% endfor %} + {{node.author}} +
    + {{ node.created_time }} +
    +
    +
    +
    +

    {{ node.body }}

    +
    +
    + {% if not node.is_leaf_node %} +
      + {{ children }} +
    + {% endif %} +
    + {% endrecursetree %} + {% if can_edit_event %} +
    +
    + {% csrf_token %} + {{ comment_form.body }} +
    +
    +
    + {% endif %} +
+
+
+ + +
-

Photos


+

Attendees ({{attendee_list.count}})


+
+ {% for attendee in attendee_list %} +
+
+ + {% for badge in attendee.user.user.account.badges.all %}{% endfor %} +
+
+ {{attendee.user}} + {{ attendee.status_name }}
+ {% if attendee.role > 0 %}{{ attendee.role_name }}{% endif %} +
+
+
+ {% endfor %} +
+

Photos

{% for photo in event.photos.all %} @@ -98,28 +164,6 @@ {% endif %}
- -
-
-
-

Attendees ({{attendee_list.count}})


-
- {% for attendee in attendee_list %} -
-
- - {% for badge in attendee.user.user.account.badges.all %}{% endfor %} -
-
- {{attendee.user}} - {{ attendee.status_name }}
- {% if attendee.role > 0 %}{{ attendee.role_name }}{% endif %} -
-
-
- {% endfor %} -
-
{% endblock %} diff --git a/get_together/urls.py b/get_together/urls.py index 6a875da..3066286 100644 --- a/get_together/urls.py +++ b/get_together/urls.py @@ -65,6 +65,7 @@ urlpatterns = [ path('events//+delete/', views.delete_event, name='delete-event'), path('events//+add_place/', views.add_place_to_event, name='add-place'), path('events//+share/', views.share_event, name='share-event'), + path('events//+comment/', event_views.comment_event, name='comment-event'), path('events//+photo/', views.add_event_photo, name='add-event-photo'), path('events///', views.show_event, name='show-event'), diff --git a/get_together/views/events.py b/get_together/views/events.py index 3335ee8..227bc99 100644 --- a/get_together/views/events.py +++ b/get_together/views/events.py @@ -7,7 +7,7 @@ from django.shortcuts import render, redirect, reverse from django.http import HttpResponse, JsonResponse from events.models.profiles import Team, Organization, UserProfile, Member -from events.forms import TeamEventForm, NewTeamEventForm, DeleteEventForm, NewPlaceForm, UploadEventPhotoForm, NewCommonEventForm +from events.forms import TeamEventForm, NewTeamEventForm, DeleteEventForm, EventCommentForm, NewPlaceForm, UploadEventPhotoForm, NewCommonEventForm from events.models.events import Event, CommonEvent, EventPhoto, Place, Attendee @@ -35,9 +35,11 @@ def events_list_all(request, *args, **kwargs): def show_event(request, event_id, event_slug): event = Event.objects.get(id=event_id) + comment_form = EventCommentForm() context = { 'team': event.team, 'event': event, + 'comment_form': comment_form, 'is_attending': request.user.profile in event.attendees.all(), 'attendee_list': Attendee.objects.filter(event=event), 'can_edit_event': request.user.profile.can_edit_event(event),