diff --git a/events/admin.py b/events/admin.py index be22307..d0375c4 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, EventComment, EventPhoto, CommonEvent, Attendee +from .models.events import Place, Event, EventComment, EventSeries, EventPhoto, CommonEvent, Attendee admin.site.register(Language) admin.site.register(Continent) @@ -81,6 +81,15 @@ class CommonEventAdmin(admin.ModelAdmin): participant_count.short_description = 'Participants' admin.site.register(CommonEvent, CommonEventAdmin) +class EventSeriesAdmin(admin.ModelAdmin): + raw_id_fields = ('place', 'team') + list_display = ('__str__', 'instance_count', 'team', 'start_time', 'last_time') + ordering = ('-last_time',) + def instance_count(self, series): + return series.instances.all().count() + instance_count.short_description = 'Instances' +admin.site.register(EventSeries, EventSeriesAdmin) + class MemberAdmin(admin.ModelAdmin): list_display = ('__str__', 'role') list_filter = ('role', 'team') diff --git a/events/forms.py b/events/forms.py index cf4d68e..832adaf 100644 --- a/events/forms.py +++ b/events/forms.py @@ -7,7 +7,7 @@ from django.utils import timezone from django.contrib.auth.models import User from .models.locale import Country, SPR, City from .models.profiles import Team, UserProfile -from .models.events import Event, EventComment ,CommonEvent, Place, EventPhoto +from .models.events import Event, EventComment ,CommonEvent, EventSeries, Place, EventPhoto import pytz from datetime import time @@ -167,7 +167,7 @@ class DeleteTeamForm(forms.Form): class TeamEventForm(forms.ModelForm): class Meta: model = Event - fields = ['name', 'start_time', 'end_time', 'summary', 'place', 'web_url', 'announce_url', 'tags'] + fields = ['name', 'start_time', 'end_time', 'summary', 'web_url', 'announce_url', 'tags'] widgets = { 'place': Lookup(source=Place), 'start_time': DateTimeWidget, @@ -191,7 +191,7 @@ class TeamEventForm(forms.ModelForm): class NewTeamEventForm(forms.ModelForm): class Meta: model = Event - fields = ['name', 'start_time', 'end_time', 'recurrences', 'summary'] + fields = ['name', 'start_time', 'end_time', 'summary'] widgets = { 'start_time': DateTimeWidget, 'end_time': DateTimeWidget @@ -214,6 +214,18 @@ class NewTeamEventForm(forms.ModelForm): class DeleteEventForm(forms.Form): confirm = forms.BooleanField(label="Yes, delete event", required=True) +class EventSeriesForm(forms.ModelForm): + class Meta: + model = EventSeries + fields = ['name', 'start_time', 'end_time', 'recurrences', 'summary'] + widgets = { + 'start_time': TimeWidget, + 'end_time': TimeWidget + } + +class DeleteEventSeriesForm(forms.Form): + confirm = forms.BooleanField(label="Yes, delete series", required=True) + class UploadEventPhotoForm(forms.ModelForm): class Meta: model = EventPhoto diff --git a/events/migrations/0021_add_event_recurrence.py b/events/migrations/0021_add_event_recurrence.py deleted file mode 100644 index 8643a36..0000000 --- a/events/migrations/0021_add_event_recurrence.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 2.0 on 2018-03-26 03:16 - -from django.db import migrations, models -import django.db.models.deletion -import recurrence.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('events', '0020_add_event_comments'), - ] - - operations = [ - migrations.AddField( - model_name='event', - name='recurrences', - field=recurrence.fields.RecurrenceField(null=True), - ), - migrations.AlterField( - model_name='eventcomment', - name='event', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='events.Event'), - ), - migrations.AlterField( - model_name='userprofile', - name='tz', - field=models.CharField(choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Asmera', 'Africa/Asmera'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Timbuktu', 'Africa/Timbuktu'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/ComodRivadavia', 'America/Argentina/ComodRivadavia'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Atka', 'America/Atka'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Buenos_Aires', 'America/Buenos_Aires'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Catamarca', 'America/Catamarca'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Coral_Harbour', 'America/Coral_Harbour'), ('America/Cordoba', 'America/Cordoba'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Ensenada', 'America/Ensenada'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fort_Wayne', 'America/Fort_Wayne'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Indianapolis', 'America/Indianapolis'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Jujuy', 'America/Jujuy'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Knox_IN', 'America/Knox_IN'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Louisville', 'America/Louisville'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Mendoza', 'America/Mendoza'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montreal', 'America/Montreal'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Acre', 'America/Porto_Acre'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Rosario', 'America/Rosario'), ('America/Santa_Isabel', 'America/Santa_Isabel'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Shiprock', 'America/Shiprock'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Virgin', 'America/Virgin'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/South_Pole', 'Antarctica/South_Pole'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Ashkhabad', 'Asia/Ashkhabad'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Calcutta', 'Asia/Calcutta'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Chongqing', 'Asia/Chongqing'), ('Asia/Chungking', 'Asia/Chungking'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Dacca', 'Asia/Dacca'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Harbin', 'Asia/Harbin'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Istanbul', 'Asia/Istanbul'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kashgar', 'Asia/Kashgar'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Katmandu', 'Asia/Katmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macao', 'Asia/Macao'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Rangoon', 'Asia/Rangoon'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Saigon', 'Asia/Saigon'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Tel_Aviv', 'Asia/Tel_Aviv'), ('Asia/Thimbu', 'Asia/Thimbu'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ujung_Pandang', 'Asia/Ujung_Pandang'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Ulan_Bator', 'Asia/Ulan_Bator'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faeroe', 'Atlantic/Faeroe'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Jan_Mayen', 'Atlantic/Jan_Mayen'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/ACT', 'Australia/ACT'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Canberra', 'Australia/Canberra'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/LHI', 'Australia/LHI'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/NSW', 'Australia/NSW'), ('Australia/North', 'Australia/North'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Queensland', 'Australia/Queensland'), ('Australia/South', 'Australia/South'), ('Australia/Sydney', 'Australia/Sydney'), ('Australia/Tasmania', 'Australia/Tasmania'), ('Australia/Victoria', 'Australia/Victoria'), ('Australia/West', 'Australia/West'), ('Australia/Yancowinna', 'Australia/Yancowinna'), ('Brazil/Acre', 'Brazil/Acre'), ('Brazil/DeNoronha', 'Brazil/DeNoronha'), ('Brazil/East', 'Brazil/East'), ('Brazil/West', 'Brazil/West'), ('CET', 'CET'), ('CST6CDT', 'CST6CDT'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Canada/Saskatchewan', 'Canada/Saskatchewan'), ('Canada/Yukon', 'Canada/Yukon'), ('Chile/Continental', 'Chile/Continental'), ('Chile/EasterIsland', 'Chile/EasterIsland'), ('Cuba', 'Cuba'), ('EET', 'EET'), ('EST', 'EST'), ('EST5EDT', 'EST5EDT'), ('Egypt', 'Egypt'), ('Eire', 'Eire'), ('Etc/GMT', 'Etc/GMT'), ('Etc/GMT+0', 'Etc/GMT+0'), ('Etc/GMT+1', 'Etc/GMT+1'), ('Etc/GMT+10', 'Etc/GMT+10'), ('Etc/GMT+11', 'Etc/GMT+11'), ('Etc/GMT+12', 'Etc/GMT+12'), ('Etc/GMT+2', 'Etc/GMT+2'), ('Etc/GMT+3', 'Etc/GMT+3'), ('Etc/GMT+4', 'Etc/GMT+4'), ('Etc/GMT+5', 'Etc/GMT+5'), ('Etc/GMT+6', 'Etc/GMT+6'), ('Etc/GMT+7', 'Etc/GMT+7'), ('Etc/GMT+8', 'Etc/GMT+8'), ('Etc/GMT+9', 'Etc/GMT+9'), ('Etc/GMT-0', 'Etc/GMT-0'), ('Etc/GMT-1', 'Etc/GMT-1'), ('Etc/GMT-10', 'Etc/GMT-10'), ('Etc/GMT-11', 'Etc/GMT-11'), ('Etc/GMT-12', 'Etc/GMT-12'), ('Etc/GMT-13', 'Etc/GMT-13'), ('Etc/GMT-14', 'Etc/GMT-14'), ('Etc/GMT-2', 'Etc/GMT-2'), ('Etc/GMT-3', 'Etc/GMT-3'), ('Etc/GMT-4', 'Etc/GMT-4'), ('Etc/GMT-5', 'Etc/GMT-5'), ('Etc/GMT-6', 'Etc/GMT-6'), ('Etc/GMT-7', 'Etc/GMT-7'), ('Etc/GMT-8', 'Etc/GMT-8'), ('Etc/GMT-9', 'Etc/GMT-9'), ('Etc/GMT0', 'Etc/GMT0'), ('Etc/Greenwich', 'Etc/Greenwich'), ('Etc/UCT', 'Etc/UCT'), ('Etc/UTC', 'Etc/UTC'), ('Etc/Universal', 'Etc/Universal'), ('Etc/Zulu', 'Etc/Zulu'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belfast', 'Europe/Belfast'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Nicosia', 'Europe/Nicosia'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Tiraspol', 'Europe/Tiraspol'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('GB', 'GB'), ('GB-Eire', 'GB-Eire'), ('GMT', 'GMT'), ('GMT+0', 'GMT+0'), ('GMT-0', 'GMT-0'), ('GMT0', 'GMT0'), ('Greenwich', 'Greenwich'), ('HST', 'HST'), ('Hongkong', 'Hongkong'), ('Iceland', 'Iceland'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Iran', 'Iran'), ('Israel', 'Israel'), ('Jamaica', 'Jamaica'), ('Japan', 'Japan'), ('Kwajalein', 'Kwajalein'), ('Libya', 'Libya'), ('MET', 'MET'), ('MST', 'MST'), ('MST7MDT', 'MST7MDT'), ('Mexico/BajaNorte', 'Mexico/BajaNorte'), ('Mexico/BajaSur', 'Mexico/BajaSur'), ('Mexico/General', 'Mexico/General'), ('NZ', 'NZ'), ('NZ-CHAT', 'NZ-CHAT'), ('Navajo', 'Navajo'), ('PRC', 'PRC'), ('PST8PDT', 'PST8PDT'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Johnston', 'Pacific/Johnston'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Ponape', 'Pacific/Ponape'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Samoa', 'Pacific/Samoa'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Truk', 'Pacific/Truk'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('Pacific/Yap', 'Pacific/Yap'), ('Poland', 'Poland'), ('Portugal', 'Portugal'), ('ROC', 'ROC'), ('ROK', 'ROK'), ('Singapore', 'Singapore'), ('Turkey', 'Turkey'), ('UCT', 'UCT'), ('US/Alaska', 'US/Alaska'), ('US/Aleutian', 'US/Aleutian'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/East-Indiana', 'US/East-Indiana'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Indiana-Starke', 'US/Indiana-Starke'), ('US/Michigan', 'US/Michigan'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('US/Pacific-New', 'US/Pacific-New'), ('US/Samoa', 'US/Samoa'), ('UTC', 'UTC'), ('Universal', 'Universal'), ('W-SU', 'W-SU'), ('WET', 'WET'), ('Zulu', 'Zulu')], default='UTC', max_length=32, verbose_name='Timezone'), - ), - ] diff --git a/events/migrations/0025_add_event_series.py b/events/migrations/0025_add_event_series.py new file mode 100644 index 0000000..5deed00 --- /dev/null +++ b/events/migrations/0025_add_event_series.py @@ -0,0 +1,39 @@ +# Generated by Django 2.0 on 2018-04-14 13:30 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import recurrence.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0024_auto_20180404_0504'), + ] + + operations = [ + migrations.CreateModel( + name='EventSeries', + 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')), + ('recurrences', recurrence.fields.RecurrenceField(null=True)), + ('last_time', models.DateTimeField(db_index=True, default=django.utils.timezone.now, help_text='Date and time of the last created instance in this series')), + ('start_time', models.TimeField(db_index=True, help_text='Date and time that the event starts', verbose_name='Start Time')), + ('end_time', models.TimeField(db_index=True, help_text='Date and time that the event ends', verbose_name='End Time')), + ('summary', models.TextField(blank=True, help_text='Summary of the Event', null=True)), + ('created_time', models.DateTimeField(db_index=True, default=django.utils.timezone.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')), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.UserProfile')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='planned_events', to='events.CommonEvent')), + ('place', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='events.Place')), + ('team', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.Team')), + ], + ), + migrations.AddField( + model_name='event', + name='series', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='instances', to='events.EventSeries'), + ), + ] diff --git a/events/models/events.py b/events/models/events.py index 71f873e..9761d72 100644 --- a/events/models/events.py +++ b/events/models/events.py @@ -58,10 +58,10 @@ 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) + series = models.ForeignKey('EventSeries',related_name='instances', null=True, blank=True, on_delete=models.SET_NULL) start_time = models.DateTimeField(help_text=_('Date and time that the event starts'), verbose_name=_('Start Time'), db_index=True) end_time = models.DateTimeField(help_text=_('Date and time that the event ends'), verbose_name=_('End Time'), db_index=True) - recurrences = RecurrenceField(null=True) summary = models.TextField(help_text=_('Summary of the Event'), blank=True, null=True) @@ -291,3 +291,67 @@ class CommonEvent(models.Model): def __str__(self): return self.name +class EventSeries(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='planned_events', null=True, blank=True, on_delete=models.SET_NULL) + + recurrences = RecurrenceField(null=True) + last_time = models.DateTimeField(help_text=_('Date and time of the last created instance in this series'), default=timezone.now, db_index=True) + start_time = models.TimeField(help_text=_('Local time that the event starts'), verbose_name=_('Start Time'), db_index=True) + end_time = models.TimeField(help_text=_('Local time that the event ends'), verbose_name=_('End Time'), db_index=True) + + summary = models.TextField(help_text=_('Summary of the Event'), blank=True, null=True) + + place = models.ForeignKey(Place, blank=True, null=True, on_delete=models.CASCADE) + + 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=timezone.now, db_index=True) + + tags = models.CharField(verbose_name=_("Keyword Tags"), blank=True, null=True, max_length=128) + + def create_next_in_series(self): + next_date = self.recurrences.after(self.last_time, dtstart=self.last_time) + event_tz = pytz.timezone(self.tz) + + next_start = pytz.utc.localize(timezone.make_naive(event_tz.localize(datetime.datetime.combine(next_date.date(), self.start_time)))) + next_end = pytz.utc.localize(timezone.make_naive(event_tz.localize(datetime.datetime.combine(next_date.date(), self.end_time)))) + next_event = Event( + series=self, + team=self.team, + name=self.name, + start_time=next_start, + end_time=next_end, + summary=self.summary, + place=self.place, + created_by=self.created_by, + ) + next_event.save() + self.last_time = next_event.start_time + self.save() + return next_event + + def get_absolute_url(self): + return reverse('show-series', kwargs={'series_id': self.id, 'series_slug': self.slug}) + + def get_full_url(self): + site = Site.objects.get(id=1) + return "https://%s%s" % (site.domain, self.get_absolute_url()) + + @property + def slug(self): + return slugify(self.name) + + @property + def tz(self): + if self.place is not None: + return self.place.tz + elif self.team is not None: + return self.team.tz + else: + return settings.TIME_ZONE + + def __str__(self): + return u'%s by %s at %s' % (self.name, self.team.name, self.start_time) + + diff --git a/events/models/profiles.py b/events/models/profiles.py index 4aafc4c..06b12cc 100644 --- a/events/models/profiles.py +++ b/events/models/profiles.py @@ -98,6 +98,20 @@ class UserProfile(models.Model): return True return False + def can_edit_series(self, series): + try: + if self.user.is_superuser: + return True + except: + return False + if series.created_by == self: + return True + if series.team.owner_profile == self: + return True + if self in series.team.moderators: + return True + return False + def can_edit_event(self, event): try: if self.user.is_superuser: diff --git a/events/templates/events/series_form.html b/events/templates/events/series_form.html new file mode 100644 index 0000000..b9fbed5 --- /dev/null +++ b/events/templates/events/series_form.html @@ -0,0 +1,3 @@ + +{{ series_form }} +
diff --git a/get_together/templates/get_together/events/create_event.html b/get_together/templates/get_together/events/create_event.html index bcf04cc..801a5f7 100644 --- a/get_together/templates/get_together/events/create_event.html +++ b/get_together/templates/get_together/events/create_event.html @@ -5,11 +5,6 @@ gtag('config', '{{settings.GOOGLE_ANALYTICS_ID}}', {'page_path': '/team/+create-event/'}); {% endblock %} -{% block styles %} - - -{% endblock %} - {% block content %}

Plan a {{team.name}} get together

{% if event.parent %}

As part of {{ event.parent.name }}

{% endif %} diff --git a/get_together/templates/get_together/events/delete_series.html b/get_together/templates/get_together/events/delete_series.html new file mode 100644 index 0000000..eee1997 --- /dev/null +++ b/get_together/templates/get_together/events/delete_series.html @@ -0,0 +1,15 @@ +{% extends "get_together/base.html" %} + +{% block content %} +

Confirm deletion

+Are you sure you want to delete {{series.name}}? +
+{% csrf_token %} +
+{{ delete_form }} +
+ +
+
+{% endblock %} + diff --git a/get_together/templates/get_together/events/edit_event.html b/get_together/templates/get_together/events/edit_event.html index d8c7146..23a4b21 100644 --- a/get_together/templates/get_together/events/edit_event.html +++ b/get_together/templates/get_together/events/edit_event.html @@ -1,4 +1,5 @@ {% extends "get_together/base.html" %} +{% load static %} {% block content %}

Updating {{event.name}}

diff --git a/get_together/templates/get_together/events/edit_series.html b/get_together/templates/get_together/events/edit_series.html new file mode 100644 index 0000000..1420591 --- /dev/null +++ b/get_together/templates/get_together/events/edit_series.html @@ -0,0 +1,52 @@ +{% extends "get_together/base.html" %} +{% load static %} + +{% block meta %} + + + +{% endblock %} + +{% block content %} +

Updating {{series.name}}

+
+{% csrf_token %} +{% include "events/series_form.html" %} +
+ +
+Delete +{% endblock %} + +{% block javascript %} + +{% endblock %} diff --git a/get_together/templates/get_together/events/show_event.html b/get_together/templates/get_together/events/show_event.html index 8f47b47..7f1fb55 100644 --- a/get_together/templates/get_together/events/show_event.html +++ b/get_together/templates/get_together/events/show_event.html @@ -54,9 +54,19 @@ Part of:{{ event.parent.name }} {% endif %} + {% if event.series %} + + Repeats: + {% for rule in event.series.recurrences.rrules %} + {{rule.to_text|capfirst}} + {% endfor %} + + + {% endif %} Time:{{ event.local_start_time }} - {{ event.local_end_time }} - + + Place: {% if event.place %} {{ event.place.name }} @@ -75,9 +85,6 @@ {% endif %} -
-
-

Comments

diff --git a/get_together/templates/get_together/events/show_series.html b/get_together/templates/get_together/events/show_series.html new file mode 100644 index 0000000..43862ee --- /dev/null +++ b/get_together/templates/get_together/events/show_series.html @@ -0,0 +1,108 @@ +{% extends "get_together/base.html" %} +{% load markup static tz %} + +{% block add_to_title %} | {{series.name}}{% endblock %} + +{% block meta %} + + + + + {% if series.team.category %} + + {% else %} + + {% endif %} +{% endblock %} + +{% block styles %} + + +{% endblock %} + +{% block content %} +
+
+
+

{{ series.name }} + {% if can_edit_event %} + Edit Series + {% endif %} +

+

Hosted by {{ team.name }}

+
+ +

{{ series.summary|markdown }}

+ + + {% if series.parent %} + + + + {% endif %} + + + + + + + + + + {% if series.web_url %} + + + + {% endif %} +
Part of:{{ series.parent.name }}
Repeats: + {% for rule in series.recurrences.rrules %} + {{rule.to_text|capfirst}} + {% endfor %} +
Time:{{ series.start_time }} - {{ series.end_time }}
Place: + {% if series.place %} + {{ series.place.name }} + {% if can_edit_event %}Change{% endif %} + {% elif can_edit_event %} + No place selected yet. + {% else %} + No place selected yet. + {% endif %} +
Website:{{ series.web_url }}
+ +
+
+ +
+ +
+
+
+

Instances


+
+ {% for instance in instances %} +
+
+
+
+ {{instance.local_start_time.date}} +
{{ instance.name }} +
+
+
+ {% endfor %} +
+
+
+
+{% endblock %} + diff --git a/get_together/urls.py b/get_together/urls.py index 1846889..9db7b63 100644 --- a/get_together/urls.py +++ b/get_together/urls.py @@ -71,6 +71,9 @@ urlpatterns = [ 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'), + path('series//+edit/', views.edit_series, name='edit-series'), + path('series//+delete/', views.delete_series, name='delete-series'), + path('series///', views.show_series, name='show-series'), path('org//', views.show_org, name='show-org'), path('org//+create-event/', views.create_common_event, name='create-common-event'), diff --git a/get_together/views/events.py b/get_together/views/events.py index ec298b2..20ee8fe 100644 --- a/get_together/views/events.py +++ b/get_together/views/events.py @@ -7,9 +7,19 @@ from django.shortcuts import render, redirect, reverse from django.http import HttpResponse, JsonResponse from django.utils import timezone -from events.models.events import Event, CommonEvent, EventPhoto, Place, Attendee +from events.models.events import Event, CommonEvent, EventSeries, EventPhoto, Place, Attendee from events.models.profiles import Team, Organization, UserProfile, Member -from events.forms import TeamEventForm, NewTeamEventForm, DeleteEventForm, EventCommentForm, NewPlaceForm, UploadEventPhotoForm, NewCommonEventForm +from events.forms import ( + TeamEventForm, + NewTeamEventForm, + DeleteEventForm, + EventSeriesForm, + DeleteEventSeriesForm, + EventCommentForm, + NewPlaceForm, + UploadEventPhotoForm, + NewCommonEventForm + ) from events import location import datetime @@ -49,6 +59,16 @@ def show_event(request, event_id, event_slug): } return render(request, 'get_together/events/show_event.html', context) +def show_series(request, series_id, series_slug): + series = EventSeries.objects.get(id=series_id) + context = { + 'team': series.team, + 'series': series, + 'instances': series.instances.all().order_by('-start_time'), + 'can_edit_event': request.user.profile.can_create_event(series.team), + } + return render(request, 'get_together/events/show_series.html', context) + @login_required def create_event_team_select(request): teams = request.user.profile.moderating @@ -226,6 +246,68 @@ def delete_event(request, event_id): else: return redirect('home') +def edit_series(request, series_id): + series = EventSeries.objects.get(id=series_id) + + if not request.user.profile.can_edit_series(series): + messages.add_message(request, messages.WARNING, message=_('You can not make changes to this event.')) + return redirect(series.get_absolute_url()) + + if request.method == 'GET': + form = EventSeriesForm(instance=series) + + context = { + 'team': series.team, + 'series': series, + 'series_form': form, + } + return render(request, 'get_together/events/edit_series.html', context) + elif request.method == 'POST': + form = EventSeriesForm(request.POST,instance=series) + if form.is_valid: + new_series = form.save() + return redirect(new_series.get_absolute_url()) + else: + context = { + 'team': event.team, + 'series': series, + 'series_form': form, + } + return render(request, 'get_together/events/edit_series.html', context) + else: + return redirect('home') + +def delete_series(request, series_id): + series = EventSeries.objects.get(id=series_id) + if not request.user.profile.can_edit_series(series): + messages.add_message(request, messages.WARNING, message=_('You can not make changes to this event.')) + return redirect(series.get_absolute_url()) + + if request.method == 'GET': + form = DeleteEventSeriesForm() + + context = { + 'team': series.team, + 'series': series, + 'delete_form': form, + } + return render(request, 'get_together/events/delete_series.html', context) + elif request.method == 'POST': + form = DeleteEventSeriesForm(request.POST) + if form.is_valid() and form.cleaned_data['confirm']: + team_id = series.team_id + series.delete() + return redirect('show-team', team_id) + else: + context = { + 'team': series.team, + 'series': series, + 'delete_form': form, + } + return render(request, 'get_together/events/delete_series.html', context) + else: + return redirect('home') + def show_common_event(request, event_id, event_slug): event = CommonEvent.objects.get(id=event_id) context = {