From 555ccf3fababce70cf55acaf71ec92d20e9f51a7 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Sat, 17 Mar 2018 15:29:17 -0400 Subject: [PATCH 1/2] Add CommonEvent model --- events/admin.py | 12 ++- events/migrations/0017_add_common_events.py | 82 +++++++++++++++++++++ events/models/events.py | 31 ++++++++ events/models/profiles.py | 6 +- 4 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 events/migrations/0017_add_common_events.py diff --git a/events/admin.py b/events/admin.py index 3a2d94f..ce32236 100644 --- a/events/admin.py +++ b/events/admin.py @@ -5,7 +5,8 @@ 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, Attendee +from .models.events import Place, Event, EventPhoto, CommonEvent, Attendee +from .models.events import Place, Event, CommonEvent, Attendee admin.site.register(Language) admin.site.register(Continent) @@ -66,6 +67,15 @@ class EventPhotoAdmin(admin.ModelAdmin): view.short_description = 'Photo' admin.site.register(EventPhoto, EventPhotoAdmin) +class CommonEventAdmin(admin.ModelAdmin): + raw_id_fields = ('place', 'city', 'spr', 'country') + list_display = ('__str__', 'participant_count', 'organization', 'start_time', 'country', 'spr', 'city') + ordering = ('-start_time',) + def participant_count(self, event): + return event.participating_events.all().count() + participant_count.short_description = 'Participants' +admin.site.register(CommonEvent, CommonEventAdmin) + class MemberAdmin(admin.ModelAdmin): list_display = ('__str__', 'role') list_filter = ('role', 'team') diff --git a/events/migrations/0017_add_common_events.py b/events/migrations/0017_add_common_events.py new file mode 100644 index 0000000..38c3818 --- /dev/null +++ b/events/migrations/0017_add_common_events.py @@ -0,0 +1,82 @@ +# Generated by Django 2.0 on 2018-03-12 18:57 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0016_make_searchable_uri_unique'), + ] + + operations = [ + migrations.CreateModel( + name='CommonEvent', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=150, verbose_name='Event Name')), + ('start_time', models.DateTimeField(db_index=True, help_text='Local date and time that the event starts', verbose_name='Local Start Time')), + ('end_time', models.DateTimeField(db_index=True, help_text='Local date and time that the event ends', verbose_name='Local End Time')), + ('summary', models.TextField(blank=True, help_text='Summary of the Event', null=True)), + ('web_url', models.URLField(blank=True, help_text='URL for the event', null=True, verbose_name='Website')), + ('announce_url', models.URLField(blank=True, help_text='URL for the announcement', null=True, verbose_name='Announcement')), + ('created_time', models.DateTimeField(db_index=True, default=datetime.datetime.now, help_text='the date and time when the event was created')), + ('tags', models.CharField(blank=True, max_length=128, null=True, verbose_name='Keyword Tags')), + ('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='events.Category')), + ('city', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='events.City')), + ('country', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='events.Country')), + ], + ), + migrations.AddField( + model_name='organization', + name='owner_profile', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owned_orgs', to='events.UserProfile'), + ), + migrations.AlterField( + model_name='team', + name='organization', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='teams', to='events.Organization'), + ), + migrations.AlterField( + model_name='team', + name='owner_profile', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owned_teams', to='events.UserProfile'), + ), + migrations.AddField( + model_name='commonevent', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.UserProfile'), + ), + migrations.AddField( + model_name='commonevent', + name='organization', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='events.Organization'), + ), + migrations.AddField( + model_name='commonevent', + name='parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sub_events', to='events.CommonEvent'), + ), + migrations.AddField( + model_name='commonevent', + name='place', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='events.Place'), + ), + migrations.AddField( + model_name='commonevent', + name='spr', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='events.SPR'), + ), + migrations.AddField( + model_name='commonevent', + name='topics', + field=models.ManyToManyField(blank=True, to='events.Topic'), + ), + migrations.AddField( + model_name='event', + name='parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='participating_events', to='events.CommonEvent'), + ), + ] diff --git a/events/models/events.py b/events/models/events.py index a0d96f4..307a781 100644 --- a/events/models/events.py +++ b/events/models/events.py @@ -55,6 +55,7 @@ class PlaceSerializer(serializers.ModelSerializer): class Event(models.Model): name = models.CharField(max_length=150, verbose_name=_('Event Name')) team = models.ForeignKey(Team, on_delete=models.CASCADE) + parent = models.ForeignKey('CommonEvent', related_name='participating_events', null=True, blank=True, on_delete=models.SET_NULL) start_time = models.DateTimeField(help_text=_('Local date and time that the event starts'), verbose_name=_('Local Start Time'), db_index=True) end_time = models.DateTimeField(help_text=_('Local date and time that the event ends'), verbose_name=_('Local End Time'), db_index=True) @@ -196,3 +197,33 @@ class EventPhoto(models.Model): processors=[ResizeToFill(250, 187)], format='JPEG', options={'quality': 60}) + +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) + parent = models.ForeignKey('CommonEvent', related_name='sub_events', null=True, blank=True, on_delete=models.SET_NULL) + + start_time = models.DateTimeField(help_text=_('Local date and time that the event starts'), verbose_name=_('Local Start Time'), db_index=True) + end_time = models.DateTimeField(help_text=_('Local date and time that the event ends'), verbose_name=_('Local End Time'), db_index=True) + summary = models.TextField(help_text=_('Summary of the Event'), blank=True, null=True) + + country = models.ForeignKey(Country, null=True, blank=True, on_delete=models.SET_NULL) + spr = models.ForeignKey(SPR, null=True, blank=True, on_delete=models.SET_NULL) + city = models.ForeignKey(City, null=True, blank=True, on_delete=models.SET_NULL) + place = models.ForeignKey(Place, blank=True, null=True, on_delete=models.SET_NULL) + + web_url = models.URLField(verbose_name=_('Website'), help_text=_('URL for the event'), max_length=200, blank=True, null=True) + announce_url = models.URLField(verbose_name=_('Announcement'), help_text=_('URL for the announcement'), max_length=200, blank=True, null=True) + + created_by = models.ForeignKey(UserProfile, on_delete=models.CASCADE) + created_time = models.DateTimeField(help_text=_('the date and time when the event was created'), default=datetime.datetime.now, db_index=True) + + category = models.ForeignKey('Category', on_delete=models.SET_NULL, blank=False, null=True) + topics = models.ManyToManyField('Topic', blank=True) + tags = models.CharField(verbose_name=_("Keyword Tags"), blank=True, null=True, max_length=128) + + def __str__(self): + return self.name + + +>>>>>>> Add CommonEvent model diff --git a/events/models/profiles.py b/events/models/profiles.py index 3afc3a7..8a350a4 100644 --- a/events/models/profiles.py +++ b/events/models/profiles.py @@ -156,12 +156,14 @@ class Organization(models.Model): name = models.CharField(max_length=256, null=False, blank=False) site = models.ForeignKey(Site, on_delete=models.CASCADE) + owner_profile = models.ForeignKey(UserProfile, related_name='owned_orgs', blank=False, null=True, on_delete=models.SET_NULL) + def __str__(self): return u'%s' % (self.name) class Team(models.Model): name = models.CharField(_("Team Name"), max_length=256, null=False, blank=False) - organization = models.ForeignKey(Organization, null=True, blank=True, on_delete=models.CASCADE) + organization = models.ForeignKey(Organization, related_name='teams', null=True, blank=True, on_delete=models.CASCADE) description = models.TextField(help_text=_('Team Description'), blank=True, null=True) @@ -174,7 +176,7 @@ class Team(models.Model): created_date = models.DateField(_("Date Created"), null=True, blank=True) - owner_profile = models.ForeignKey(UserProfile, related_name='owner', null=True, on_delete=models.CASCADE) + owner_profile = models.ForeignKey(UserProfile, related_name='owned_teams', null=True, on_delete=models.CASCADE) admin_profiles = models.ManyToManyField(UserProfile, related_name='admins', blank=True) contact_profiles = models.ManyToManyField(UserProfile, related_name='contacts', blank=True) From 3e15d89c43f9178bd37e797d772316a42d408cd8 Mon Sep 17 00:00:00 2001 From: Michael Hall Date: Thu, 22 Mar 2018 00:15:09 -0400 Subject: [PATCH 2/2] Add preliminary support for common events and organizations. Fixes #44, Fixes #45 --- events/admin.py | 1 - events/forms.py | 32 ++++- ...on_events.py => 0018_add_common_events.py} | 15 ++- events/migrations/0019_add_org_slug.py | 19 +++ events/models/events.py | 13 +- events/models/profiles.py | 13 ++ get_together/templates/get_together/base.html | 2 +- .../get_together/events/create_event.html | 3 + .../get_together/events/list_events.html | 5 + .../get_together/events/show_event.html | 15 ++- .../orgs/create_common_event.html | 99 ++++++++++++++++ .../orgs/create_common_event_team_select.html | 41 +++++++ .../get_together/orgs/share_common_event.html | 84 +++++++++++++ .../get_together/orgs/show_common_event.html | 111 ++++++++++++++++++ .../templates/get_together/orgs/show_org.html | 76 ++++++++++++ .../get_together/teams/list_teams.html | 5 + get_together/urls.py | 6 + get_together/views/events.py | 80 +++++++++++-- get_together/views/teams.py | 17 ++- 19 files changed, 615 insertions(+), 22 deletions(-) rename events/migrations/{0017_add_common_events.py => 0018_add_common_events.py} (88%) create mode 100644 events/migrations/0019_add_org_slug.py create mode 100644 get_together/templates/get_together/orgs/create_common_event.html create mode 100644 get_together/templates/get_together/orgs/create_common_event_team_select.html create mode 100644 get_together/templates/get_together/orgs/share_common_event.html create mode 100644 get_together/templates/get_together/orgs/show_common_event.html create mode 100644 get_together/templates/get_together/orgs/show_org.html diff --git a/events/admin.py b/events/admin.py index ce32236..7bd6586 100644 --- a/events/admin.py +++ b/events/admin.py @@ -6,7 +6,6 @@ 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, CommonEvent, Attendee admin.site.register(Language) admin.site.register(Continent) diff --git a/events/forms.py b/events/forms.py index 90010be..e5476b8 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, Place, EventPhoto +from .models.events import Event, CommonEvent, Place, EventPhoto from datetime import time from time import strptime, strftime @@ -245,3 +245,33 @@ class SearchForm(forms.Form): widgets ={ 'city': Lookup(source='/api/cities/', label='name'), } + +class NewCommonEventForm(forms.ModelForm): + class Meta: + model = CommonEvent + fields = [ + 'name', + 'start_time', + 'end_time', + 'summary', + + 'country', + 'spr', + 'city', + 'place', + + 'web_url', + 'announce_url', + + 'category', + 'tags', + ] + widgets ={ + 'country': Lookup(source='/api/countries/', label='name'), + 'spr': Lookup(source='/api/spr/', label='name'), + 'city': Lookup(source='/api/cities/', label='name'), + 'place': Lookup(source='/api/places/', label='name'), + 'start_time': DateTimeWidget, + 'end_time': DateTimeWidget + } + diff --git a/events/migrations/0017_add_common_events.py b/events/migrations/0018_add_common_events.py similarity index 88% rename from events/migrations/0017_add_common_events.py rename to events/migrations/0018_add_common_events.py index 38c3818..1bd9bb4 100644 --- a/events/migrations/0017_add_common_events.py +++ b/events/migrations/0018_add_common_events.py @@ -1,14 +1,15 @@ -# Generated by Django 2.0 on 2018-03-12 18:57 +# Generated by Django 2.0 on 2018-03-21 01:13 import datetime from django.db import migrations, models import django.db.models.deletion +import imagekit.models.fields class Migration(migrations.Migration): dependencies = [ - ('events', '0016_make_searchable_uri_unique'), + ('events', '0017_add_event_images'), ] operations = [ @@ -34,6 +35,11 @@ class Migration(migrations.Migration): name='owner_profile', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owned_orgs', to='events.UserProfile'), ), + migrations.AlterField( + model_name='eventphoto', + name='src', + field=models.ImageField(upload_to='event_photos', verbose_name='Photo'), + ), migrations.AlterField( model_name='team', name='organization', @@ -44,6 +50,11 @@ class Migration(migrations.Migration): name='owner_profile', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owned_teams', to='events.UserProfile'), ), + migrations.AlterField( + model_name='userprofile', + name='avatar', + field=imagekit.models.fields.ProcessedImageField(blank=True, upload_to='avatars', verbose_name='Photo Image'), + ), migrations.AddField( model_name='commonevent', name='created_by', diff --git a/events/migrations/0019_add_org_slug.py b/events/migrations/0019_add_org_slug.py new file mode 100644 index 0000000..6502ddc --- /dev/null +++ b/events/migrations/0019_add_org_slug.py @@ -0,0 +1,19 @@ +# Generated by Django 2.0 on 2018-03-22 03:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0018_add_common_events'), + ] + + operations = [ + migrations.AddField( + model_name='organization', + name='slug', + field=models.CharField(default='slug_required', max_length=256), + preserve_default=False, + ), + ] diff --git a/events/models/events.py b/events/models/events.py index 307a781..9ac8093 100644 --- a/events/models/events.py +++ b/events/models/events.py @@ -222,8 +222,17 @@ class CommonEvent(models.Model): topics = models.ManyToManyField('Topic', blank=True) tags = models.CharField(verbose_name=_("Keyword Tags"), blank=True, null=True, max_length=128) + def get_absolute_url(self): + return reverse('show-common-event', kwargs={'event_id': self.id, 'event_slug': self.slug}) + + def get_full_url(self): + site = self.organization.site + return "https://%s%s" % (site.domain, self.get_absolute_url()) + + @property + def slug(self): + return slugify(self.name) + def __str__(self): return self.name - ->>>>>>> Add CommonEvent model diff --git a/events/models/profiles.py b/events/models/profiles.py index 8a350a4..eac4f02 100644 --- a/events/models/profiles.py +++ b/events/models/profiles.py @@ -107,6 +107,18 @@ class UserProfile(models.Model): return True return False + def can_create_common_event(self, org): + try: + if self.user.is_superuser: + return True + except: + return False + if not self.user_id: + return False + if org.owner_profile == self: + return True + return False + def can_edit_team(self, team): try: if self.user.is_superuser: @@ -154,6 +166,7 @@ AnonymousUser.profile = property(_getAnonProfile) class Organization(models.Model): name = models.CharField(max_length=256, null=False, blank=False) + slug = models.CharField(max_length=256, null=False, blank=False) site = models.ForeignKey(Site, on_delete=models.CASCADE) owner_profile = models.ForeignKey(UserProfile, related_name='owned_orgs', blank=False, null=True, on_delete=models.SET_NULL) diff --git a/get_together/templates/get_together/base.html b/get_together/templates/get_together/base.html index 511d9e3..688bd1d 100644 --- a/get_together/templates/get_together/base.html +++ b/get_together/templates/get_together/base.html @@ -124,7 +124,7 @@ form { {% load flatpages %} {% get_flatpages as flatpages %} -