diff --git a/.travis.yml b/.travis.yml index 3da72c7..684881a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,12 @@ git: install: - pip install pipenv - - pipenv install + - pipenv install --dev script: + - pycodestyle $(git ls-files '*.py') + - pydocstyle $(git ls-files '*.py') + - pyflakes $(git ls-files '*.py') - ./manage.py makemigrations website - ./manage.py migrate - ./manage.py test diff --git a/Pipfile b/Pipfile index c53574e..e133923 100644 --- a/Pipfile +++ b/Pipfile @@ -1,17 +1,16 @@ [[source]] - url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" - [packages] - django = ">=2.2.3" gunicorn = "*" - [dev-packages] +pyflakes = "*" +pydocstyle = "*" +pycodestyle = "*" [requires] python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index 946ec61..1481c5a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2740fee59d1787915703e4a13b1b10e906290b1ad847f2a63fc4649369cc0a5e" + "sha256": "c5767b856fefd1eec5615246f9eeb6a81b4e8f6535ef89823c0a99781066e6b5" }, "pipfile-spec": 6, "requires": { @@ -47,5 +47,36 @@ "version": "==0.3.0" } }, - "develop": {} + "develop": { + "pycodestyle": { + "hashes": [ + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + ], + "index": "pypi", + "version": "==2.5.0" + }, + "pydocstyle": { + "hashes": [ + "sha256:58c421dd605eec0bce65df8b8e5371bb7ae421582cdf0ba8d9435ac5b0ffc36a" + ], + "index": "pypi", + "version": "==4.0.0" + }, + "pyflakes": { + "hashes": [ + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + ], + "index": "pypi", + "version": "==2.1.1" + }, + "snowballstemmer": { + "hashes": [ + "sha256:4f781f26a15a550146d357181b1c894d82c7e9af4bc80de8626e03a76c36b555", + "sha256:9f3b9ffe0809d174f7047e121431acf99c89a7040f0ca84f94ba53a498e6d0c9" + ], + "version": "==1.9.0" + } + } } diff --git a/website/models.py b/website/models.py index 5ff840d..e5e2d9e 100644 --- a/website/models.py +++ b/website/models.py @@ -5,7 +5,7 @@ from django.db.models.signals import post_save from django.dispatch import receiver from django.utils.text import slugify - +import sys class CustomUser(AbstractUser): """ @@ -63,9 +63,27 @@ class Event(models.Model): An event can contain multiple workshops (as long as the workshops are within the event period. + + Three types of events exist. + UNSW info days: No support needed. Students and volunteers can't sign up + School_based_events: volunteer support + UNSW_events: Volunteers and students support needed """ name = models.CharField(max_length=100) + SCHOOL = 'SE' + UNI_INFO = 'UIE' + UNI = 'UE' + + EVENT_TYPES = ( + (SCHOOL, 'School'), + (UNI_INFO, 'Uni_Info'), + (UNI, 'Uni'), + ) + event_types = models.CharField(max_length = 3, + choices = EVENT_TYPES, + default = UNI, + ) start_date = models.DateField() finish_date = models.DateField() owner = models.ForeignKey(Volunteer, on_delete=models.SET_NULL, null=True) @@ -74,10 +92,20 @@ class Event(models.Model): period = models.TextField(verbose_name='availability period') slug = models.SlugField(default='event', unique=False) # url name of event + def __str__(self): """Return a string representation of an event.""" return self.name + def hasWorkshops(self): + if self.event_types == self.UNI_INFO: + #print(self.event_types) + #print(self.UNI_INFO) + #sys.stdout.flush() + return False + else: + return True + def save(self, *args, **kwargs): """Override save to update slug.""" self.slug = slugify(self.name) diff --git a/website/templates/website/event.html b/website/templates/website/event.html index 9d7dbfe..528934d 100644 --- a/website/templates/website/event.html +++ b/website/templates/website/event.html @@ -8,16 +8,18 @@

{{ event.name }}

- {% if perms.website.change_event %} + {% if perms.website.change_event and event.hasWorkshops%} Available Volunteers {% endif %}
{% if user.is_staff %}

+ {% if event.hasWorkshops%} Create Workshop + {% endif %} Send status email @@ -32,7 +34,7 @@

Event Details

Description

{{ event.description }}

- + {% if event.hasWorkshops%}

Workshop Schedule

@@ -46,6 +48,7 @@

Workshop Schedule

{% endif %} + {% if workshops %} {% for workshop in workshops %} @@ -67,10 +70,10 @@

Workshop Schedule

{% endif %} {% else %} - - {% endif %} + + {% endif %} - + {% endif %} @@ -78,8 +81,9 @@

Workshop Schedule

{% else %}

To be confirmed

{% endif %} + {% endif %}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/website/templates/website/event_create.html b/website/templates/website/event_create.html index 51e2012..5928d70 100644 --- a/website/templates/website/event_create.html +++ b/website/templates/website/event_create.html @@ -6,7 +6,9 @@ {% block content %} {{ block.super }}
-

Create event

+
+

Create Event

+
{% csrf_token %} @@ -37,7 +39,7 @@

Create event

-
+
{{ form.start_date.label_tag }} {% if form.start_date.errors %} {{ form.start_date|add_attrs:"is-invalid" }} @@ -54,7 +56,7 @@

Create event

-
+
{{ form.finish_date.label_tag }} {% if form.finish_date.errors %} {{ form.finish_date|add_attrs:"is-invalid" }} @@ -71,7 +73,7 @@

Create event

-
+
@@ -93,6 +95,25 @@

Create event

+
+ +
+ {% if event_form.event_types.errors %} + {{ event_form.event_types|add_attrs:"is-invalid" }} + {% for error in event_form.event_types.errors %} +
+ {{ error }} +
+ {% endfor %} + {% else %} + {{ event_form.event_types }} + {% endif %} +
+ + {{ event_form.event_types.help_text }} + +
+
diff --git a/website/tests.py b/website/tests.py index 5e33e26..570b2f4 100644 --- a/website/tests.py +++ b/website/tests.py @@ -128,6 +128,7 @@ def test_event_create_valid(self): 'name': 'Intro to Python', 'start_date': '2018-01-01', 'finish_date': '2018-04-30', + 'event_types': 'UIE', 'owner': '1', 'description': 'introduction to Python', 'prerequisite': 'Nil', @@ -135,8 +136,11 @@ def test_event_create_valid(self): 'slug': 'Intro-to-Python' } form = EventForm(data=form_data) + form.is_valid() + print(form.errors) self.assertTrue(form.is_valid()) + def test_event_create_invalid_dates(self): form_data = { 'name': 'Intro to Python', @@ -183,6 +187,7 @@ def setUp(self): 'start_date': '2018-10-31', 'finish_date': '2018-11-08', 'owner': '1', + 'event_types':'UE', 'description': 'introduction to Python', 'prerequisite': 'Nil', 'period': 'period', diff --git a/website/views.py b/website/views.py index c398212..0a855e2 100644 --- a/website/views.py +++ b/website/views.py @@ -64,7 +64,6 @@ class EventPage(DetailView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - # add event workshops to context and display first workshop location workshops = Workshop.objects \ .filter(event=context['event']) \ @@ -86,13 +85,14 @@ def get(self, request, event_id, slug): # check if url is valid event = get_object_or_404(Event, pk=event_id) if event.slug != slug: - return redirect('website:event_page', event_id=event.pk, + return redirect('website:event_page', event_id=event.pk, slug=event.slug) return super().get(request, event_id, slug) def post(self, request, event_id, slug): - if request.user.is_authenticated: + event = get_object_or_404(Event, pk=event_id) + if request.user.is_authenticated and event.hasWorkshops: # check if user in list of available volunteers for a workshop volunteer = Volunteer.objects.get(user=request.user) workshop_id = request.POST.get("workshop_id") @@ -138,7 +138,7 @@ def get(self, request, event_id, slug): # check if url is valid event = get_object_or_404(Event, pk=event_id) if event.slug != slug: - return redirect('website:registration', event_id=event.pk, + return redirect('website:registration', event_id=event.pk, slug=event.slug) return super().get(request, event_id, slug) @@ -148,7 +148,7 @@ def get_success_url(self): class EventCreate(CreateView): """ - Render and show an event creation form. The form allows for the creation + Render and show an event creation form. The form allows for the creation of new events. Only staff members can access and see this page. Args: @@ -166,8 +166,8 @@ def get_success_url(self): class VolunteerStatusEmailPreview(View): """ Render and show an email preview page, and should be shown after assigning - volunteers to workshops in an event. If a POST request is sent, an email - will be sent to the listed volunteers whether they are assigned, on a + volunteers to workshops in an event. If a POST request is sent, an email + will be sent to the listed volunteers whether they are assigned, on a waitlist or declined. Only staff members can access and see this page. Args: @@ -204,8 +204,8 @@ def post(self, request, event_id, slug): class EventAssignVolunteers(View): """ - Render and show a volunteer assignment page. The page shows a series of - forms allowing a staff member to assign volunteers to workshops for a + Render and show a volunteer assignment page. The page shows a series of + forms allowing a staff member to assign volunteers to workshops for a particular event. Only staff members can access and see this page. Args: @@ -239,7 +239,7 @@ def get(self, request, event_id, slug): def post(self, request, event_id, slug): if 'workshop_id' in request.POST: - workshop = get_object_or_404(Workshop, + workshop = get_object_or_404(Workshop, pk=request.POST['workshop_id']) post_form = VolunteerAssignForm(request.POST, @@ -248,13 +248,13 @@ def post(self, request, event_id, slug): if post_form.is_valid(): post_form.save() - return redirect('website:assign_volunteers', - event_id=event_id, + return redirect('website:assign_volunteers', + event_id=event_id, slug=slug) class WorkshopCreate(CreateView): """ - Render and show a workshop creation form page. The page shows a form + Render and show a workshop creation form page. The page shows a form allowing a staff member to create a new workshop for a particular event. Only staff members can access and see this page. @@ -300,7 +300,7 @@ class AboutView(TemplateView): #@login_required #def user_profile(request): # """ -# Render and show the user's profile page. Requires that the user is logged +# Render and show the user's profile page. Requires that the user is logged # in. # NOTE: this is minimally implemented and is currently not used #