From f0ddd5712896cf4f04210f161a812cc7d7aad6e4 Mon Sep 17 00:00:00 2001 From: Miguel Angel G Date: Mon, 18 May 2020 03:42:43 -0500 Subject: [PATCH 1/5] Add support to link one poll to multiple hackathons --- app/dashboard/admin.py | 7 +- .../migrations/0110_auto_20200518_0839.py | 38 ++++++++ app/dashboard/models.py | 11 ++- .../dashboard/hackathon/onboard.html | 89 +++++++++++++++---- app/dashboard/views.py | 37 ++++---- app/economy/models.py | 8 +- 6 files changed, 139 insertions(+), 51 deletions(-) create mode 100644 app/dashboard/migrations/0110_auto_20200518_0839.py diff --git a/app/dashboard/admin.py b/app/dashboard/admin.py index 9aac2881ad4..459c0007244 100644 --- a/app/dashboard/admin.py +++ b/app/dashboard/admin.py @@ -427,8 +427,7 @@ class OptionsInline(admin.TabularInline): class PollsAdmin(admin.ModelAdmin): - list_display = ['id', 'title', 'active', 'hackathon', 'created_on'] - raw_id_fields = ['hackathon'] + list_display = ['id', 'title', 'active'] search_fields = ['title'] inlines = [QuestionInline] @@ -447,8 +446,8 @@ class OptionsAdmin(admin.ModelAdmin): class AnswersAdmin(admin.ModelAdmin): - list_display = ['id', 'user', 'question', 'open_response', 'choice'] - raw_id_fields = ['user', 'question', 'choice'] + list_display = ['id', 'user', 'question', 'open_response', 'choice', 'checked', 'hackathon'] + raw_id_fields = ['user', 'question', 'choice', 'hackathon'] unique_together = ('user', 'question', 'choice') diff --git a/app/dashboard/migrations/0110_auto_20200518_0839.py b/app/dashboard/migrations/0110_auto_20200518_0839.py new file mode 100644 index 00000000000..2ad294e3c13 --- /dev/null +++ b/app/dashboard/migrations/0110_auto_20200518_0839.py @@ -0,0 +1,38 @@ +# Generated by Django 2.2.4 on 2020-05-18 08:39 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('dashboard', '0109_auto_20200518_0220'), + ] + + operations = [ + migrations.AddField( + model_name='answer', + name='checked', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='answer', + name='hackathon', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='dashboard.HackathonEvent'), + ), + migrations.RemoveField( + model_name='poll', + name='hackathon', + ), + migrations.AddField( + model_name='poll', + name='hackathon', + field=models.ManyToManyField(to='dashboard.HackathonEvent'), + ), + migrations.AlterField( + model_name='question', + name='question_type', + field=models.CharField(choices=[('SINGLE_CHOICE', 'Single Choice'), ('MULTIPLE_CHOICE', 'Multiple Choices'), ('OPEN', 'Open')], max_length=50), + ), + ] diff --git a/app/dashboard/models.py b/app/dashboard/models.py index 25fbb5b223c..238f987c3c5 100644 --- a/app/dashboard/models.py +++ b/app/dashboard/models.py @@ -4903,7 +4903,7 @@ class TribeMember(SuperModel): max_length=20, blank=True ) - + @property def mutual_follow(self): return TribeMember.objects.filter(profile=self.org, org=self.profile).exists() @@ -4918,17 +4918,18 @@ def mutual_following(self): tribe_following = Subquery(TribeMember.objects.filter(org=self.profile).values_list('profile', flat=True)) return TribeMember.objects.filter(org__in=tribe_following, profile=self.org).exclude(org=self.org) - + class Poll(SuperModel): title = models.CharField(max_length=350, blank=True, null=True) active = models.BooleanField(default=False) - hackathon = models.ForeignKey(HackathonEvent, on_delete=models.SET_NULL, null=True, blank=True) + hackathon = models.ManyToManyField(HackathonEvent) + class Question(SuperModel): TYPE_QUESTIONS = ( ('SINGLE_CHOICE', 'Single Choice'), - ('MUTIPLE_CHOICE', 'Multiple Choices'), + ('MULTIPLE_CHOICE', 'Multiple Choices'), ('OPEN', 'Open'), ) poll = models.ForeignKey(Poll, on_delete=models.CASCADE, null=True, blank=True) @@ -4952,3 +4953,5 @@ class Answer(SuperModel): question = models.ForeignKey(Question, on_delete=models.CASCADE) open_response = models.CharField(max_length=350, blank=True, null=True) choice = models.ForeignKey(Option, on_delete=models.CASCADE, null=True, blank=True) + checked = models.BooleanField(default=False) + hackathon = models.ForeignKey(HackathonEvent, null=True, on_delete=models.CASCADE) diff --git a/app/dashboard/templates/dashboard/hackathon/onboard.html b/app/dashboard/templates/dashboard/hackathon/onboard.html index 62d73bb16d3..0687c7f6784 100644 --- a/app/dashboard/templates/dashboard/hackathon/onboard.html +++ b/app/dashboard/templates/dashboard/hackathon/onboard.html @@ -72,9 +72,6 @@ } @media screen and (min-width: 598px) { - .options { - grid-template-columns: repeat(2, 1fr); - } } @@ -312,38 +309,54 @@

How does the Hackathon w -
+
+
-
@@ -373,8 +386,8 @@

{{ question.text }}

}); } else { $('#questions-form').modal('show'); - $('#send_poll').unbind('click') - $('#send_poll').on('click', function () { + $('#poll-submit').unbind('click') + $('#poll-submit').on('click', function () { const poll = $('#hackathon-poll').serializeArray(); const url = '/register_hackathon/'; @@ -424,6 +437,48 @@

{{ question.text }}

}, 1000); } + const poll_manager = $('#poll_container').carousel({ + interval: false + }) + + $('[data-slide="next"]').click(function (e) { + e.preventDefault(); + const fieldset = $('fieldset.active'); + + console.log(fieldset) + if (fieldset.data('rstep') === 1) { + $("#poll-prev").removeClass('d-none') + $("#poll-next").addClass('d-none') + $('#poll-empty').addClass('d-none') + $('#poll-submit').removeClass('d-none') + } else { + $("#poll-prev").removeClass('d-none') + $("#poll-next").removeClass('d-none') + $('#poll-empty').addClass('d-none') + $('#poll-submit').addClass('d-none') + } + poll_manager.carousel('next'); + }) + + $('[data-slide="prev"]').click(function (e) { + e.preventDefault(); + const fieldset = $('fieldset.active'); + + console.log(fieldset) + if (fieldset.data('step') === 1) { + $("#poll-prev").addClass('d-none') + $("#poll-next").removeClass('d-none') + $('#poll-empty').removeClass('d-none') + $('#poll-submit').addClass('d-none') + } else { + $("#poll-prev").removeClass('d-none') + $("#poll-next").removeClass('d-none') + $('#poll-empty').addClass('d-none') + $('#poll-submit').addClass('d-none') + } + poll_manager.carousel('prev'); + }) + diff --git a/app/dashboard/views.py b/app/dashboard/views.py index db5a8427cfd..e14b134c659 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -4014,16 +4014,24 @@ def hackathon_registration(request): set_questions = {} for entry in poll: question = get_object_or_404(Question, id=int(entry['name'])) - option = get_object_or_404(Option, id=int(entry['value'])) - Answer.objects.get_or_create(user=request.user, question=question, choice=option) - - values = set_questions.get(entry['name'], []) or [] - values.append(int(entry['value'])) - set_questions[entry['name']] = values + if question.question_type == 'SINGLE_CHOICE': + answer, status = Answer.objects.get_or_create(user=request.user, question=question, hackathon=hackathon_event) + answer.checked = entry['value'] == 'on' + answer.save() + elif question.question_type == 'MULTIPLE_CHOICE': + option = get_object_or_404(Option, id=int(entry['value'])) + Answer.objects.get_or_create(user=request.user, question=question, choice=option, hackathon=hackathon_event) + values = set_questions.get(entry['name'], []) or [] + values.append(int(entry['value'])) + set_questions[entry['name']] = values + else: + answer, status = Answer.objects.get_or_create(user=request.user, question=question, hackathon=hackathon_event) + answer.open_response = entry['value'] + answer.save() for (question, choices) in set_questions.items(): - Answer.objects.exclude(user=request.user, question__id=int(question), choice__in=choices).delete() + Answer.objects.filter(user=request.user, question__id=int(question)).exclude(choice__in=choices).delete() except Exception as e: logger.error('Error while saving registration', e) @@ -4042,22 +4050,7 @@ def hackathon_registration(request): user_email_hash = hashlib.md5(email.encode('utf')).hexdigest() - try: - client.lists.members.create_or_update(settings.MAILCHIMP_LIST_ID_HACKERS, user_email_hash, mailchimp_data) - client.lists.members.tags.update( - settings.MAILCHIMP_LIST_ID_HACKERS, - user_email_hash, - { - 'tags': [ - {'name': hackathon, 'status': 'active'}, - ], - } - ) - print('pushed_to_list') - except Exception as e: - logger.error(f"error in record_action: {e}") - pass if referer and '/issue/' in referer and is_safe_url(referer, request.get_host()): messages.success(request, _(f'You have successfully registered to {hackathon_event.name}. Happy hacking!')) diff --git a/app/economy/models.py b/app/economy/models.py index e91a1791c24..88f20695da8 100644 --- a/app/economy/models.py +++ b/app/economy/models.py @@ -64,12 +64,12 @@ def default(self, obj): def get_time(): """Get the local time.""" - return localtime(timezone.now()) + return timezone.now() def get_0_time(): """Get the local time.""" - return localtime(timezone.datetime(1970, 1, 1).replace(tzinfo=pytz.utc)) + return timezone.datetime(1970, 1, 1).replace(tzinfo=pytz.utc) class SuperModel(models.Model): @@ -80,8 +80,8 @@ class Meta: abstract = True - created_on = models.DateTimeField(null=False, default=get_time, db_index=True) - modified_on = models.DateTimeField(null=False, default=get_time) + created_on = models.DateTimeField(null=True, default=get_time, db_index=True) + modified_on = models.DateTimeField(null=True, default=get_time) def save(self, update=True, *args, **kwargs): """Override the SuperModel save to optionally handle modified_on logic.""" From 54aa9c33cd3147ee89b8d3768f07691540fcf62f Mon Sep 17 00:00:00 2001 From: Miguel Angel G Date: Mon, 18 May 2020 20:47:48 -0500 Subject: [PATCH 2/5] Rollback temporal changes --- app/dashboard/views.py | 15 +++++++++++++++ app/economy/models.py | 8 ++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/app/dashboard/views.py b/app/dashboard/views.py index e14b134c659..16a10da9475 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -4050,7 +4050,22 @@ def hackathon_registration(request): user_email_hash = hashlib.md5(email.encode('utf')).hexdigest() + try: + client.lists.members.create_or_update(settings.MAILCHIMP_LIST_ID_HACKERS, user_email_hash, mailchimp_data) + client.lists.members.tags.update( + settings.MAILCHIMP_LIST_ID_HACKERS, + user_email_hash, + { + 'tags': [ + {'name': hackathon, 'status': 'active'}, + ], + } + ) + print('pushed_to_list') + except Exception as e: + logger.error(f"error in record_action: {e}") + pass if referer and '/issue/' in referer and is_safe_url(referer, request.get_host()): messages.success(request, _(f'You have successfully registered to {hackathon_event.name}. Happy hacking!')) diff --git a/app/economy/models.py b/app/economy/models.py index 88f20695da8..e91a1791c24 100644 --- a/app/economy/models.py +++ b/app/economy/models.py @@ -64,12 +64,12 @@ def default(self, obj): def get_time(): """Get the local time.""" - return timezone.now() + return localtime(timezone.now()) def get_0_time(): """Get the local time.""" - return timezone.datetime(1970, 1, 1).replace(tzinfo=pytz.utc) + return localtime(timezone.datetime(1970, 1, 1).replace(tzinfo=pytz.utc)) class SuperModel(models.Model): @@ -80,8 +80,8 @@ class Meta: abstract = True - created_on = models.DateTimeField(null=True, default=get_time, db_index=True) - modified_on = models.DateTimeField(null=True, default=get_time) + created_on = models.DateTimeField(null=False, default=get_time, db_index=True) + modified_on = models.DateTimeField(null=False, default=get_time) def save(self, update=True, *args, **kwargs): """Override the SuperModel save to optionally handle modified_on logic.""" From 5cce1c0ff5fb2d9000cd6355df43a4b0eda66547 Mon Sep 17 00:00:00 2001 From: Miguel Angel G Date: Mon, 18 May 2020 20:51:12 -0500 Subject: [PATCH 3/5] Remove unnecesary query --- app/dashboard/templates/dashboard/hackathon/onboard.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/dashboard/templates/dashboard/hackathon/onboard.html b/app/dashboard/templates/dashboard/hackathon/onboard.html index 0687c7f6784..5230245807c 100644 --- a/app/dashboard/templates/dashboard/hackathon/onboard.html +++ b/app/dashboard/templates/dashboard/hackathon/onboard.html @@ -70,9 +70,6 @@ .modal-header, .modal-body, .modal-footer { border: none; } - - @media screen and (min-width: 598px) { - } From cd95eee0b215c24ba02a5847d23277dd81ddf267 Mon Sep 17 00:00:00 2001 From: Miguel Angel G Date: Mon, 18 May 2020 21:27:39 -0500 Subject: [PATCH 4/5] Fix migration --- ...{0110_auto_20200518_0839.py => 0109_auto_20200519_0226.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename app/dashboard/migrations/{0110_auto_20200518_0839.py => 0109_auto_20200519_0226.py} (91%) diff --git a/app/dashboard/migrations/0110_auto_20200518_0839.py b/app/dashboard/migrations/0109_auto_20200519_0226.py similarity index 91% rename from app/dashboard/migrations/0110_auto_20200518_0839.py rename to app/dashboard/migrations/0109_auto_20200519_0226.py index 2ad294e3c13..af45ea4f45a 100644 --- a/app/dashboard/migrations/0110_auto_20200518_0839.py +++ b/app/dashboard/migrations/0109_auto_20200519_0226.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2.4 on 2020-05-18 08:39 +# Generated by Django 2.2.4 on 2020-05-19 02:26 from django.db import migrations, models import django.db.models.deletion @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ('dashboard', '0109_auto_20200518_0220'), + ('dashboard', '0108_auto_20200513_0353'), ] operations = [ From 26eb9b605d452cc7669bf51662b7603d3ac0bcb8 Mon Sep 17 00:00:00 2001 From: Miguel Angel G Date: Mon, 18 May 2020 23:36:59 -0500 Subject: [PATCH 5/5] Add fixes to overwrite questions --- .../templates/dashboard/hackathon/onboard.html | 14 ++++++-------- app/dashboard/views.py | 12 ++++++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/dashboard/templates/dashboard/hackathon/onboard.html b/app/dashboard/templates/dashboard/hackathon/onboard.html index 5230245807c..e436e96ddfe 100644 --- a/app/dashboard/templates/dashboard/hackathon/onboard.html +++ b/app/dashboard/templates/dashboard/hackathon/onboard.html @@ -315,8 +315,8 @@

How does the Hackathon w
{% if question.question_type == 'SINGLE_CHOICE' %}
- - + +
{% elif question.question_type == 'MULTIPLE_CHOICE' %}
@@ -324,8 +324,8 @@

{{ forloop.counter }}. {{ que
{% for option in question.option_set.all %}
- - + +
{% endfor %}
@@ -345,8 +345,8 @@

{{ question.text }}

< Previous
- Submit - + Submit + Next > @@ -442,7 +442,6 @@

{{ question.text }}

e.preventDefault(); const fieldset = $('fieldset.active'); - console.log(fieldset) if (fieldset.data('rstep') === 1) { $("#poll-prev").removeClass('d-none') $("#poll-next").addClass('d-none') @@ -461,7 +460,6 @@

{{ question.text }}

e.preventDefault(); const fieldset = $('fieldset.active'); - console.log(fieldset) if (fieldset.data('step') === 1) { $("#poll-prev").addClass('d-none') $("#poll-next").removeClass('d-none') diff --git a/app/dashboard/views.py b/app/dashboard/views.py index 97591017718..057a5a52821 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -4019,22 +4019,26 @@ def hackathon_registration(request): question = get_object_or_404(Question, id=int(entry['name'])) if question.question_type == 'SINGLE_CHOICE': - answer, status = Answer.objects.get_or_create(user=request.user, question=question, hackathon=hackathon_event) + answer, status = Answer.objects.get_or_create(user=request.user, question=question, + hackathon=hackathon_event) answer.checked = entry['value'] == 'on' answer.save() elif question.question_type == 'MULTIPLE_CHOICE': option = get_object_or_404(Option, id=int(entry['value'])) - Answer.objects.get_or_create(user=request.user, question=question, choice=option, hackathon=hackathon_event) + Answer.objects.get_or_create(user=request.user, question=question, choice=option, + hackathon=hackathon_event) values = set_questions.get(entry['name'], []) or [] values.append(int(entry['value'])) set_questions[entry['name']] = values else: - answer, status = Answer.objects.get_or_create(user=request.user, question=question, hackathon=hackathon_event) + answer, status = Answer.objects.get_or_create(user=request.user, question=question, + hackathon=hackathon_event) answer.open_response = entry['value'] answer.save() for (question, choices) in set_questions.items(): - Answer.objects.filter(user=request.user, question__id=int(question)).exclude(choice__in=choices).delete() + Answer.objects.filter(user=request.user, question__id=int(question), + hackathon=hackathon_event).exclude(choice__in=choices).delete() except Exception as e: logger.error('Error while saving registration', e)