ankpan18 commited on
Commit
1ae15f5
·
1 Parent(s): 44a720b

made public polling working and also shows result

Browse files
accounts/admin.py CHANGED
@@ -10,8 +10,8 @@ from .forms import UserAdminCreationForm,UserAdminUpdateForm
10
  class MyUserAdmin(admin.ModelAdmin):
11
 
12
  search_fields=('email','username')
13
- #ordering=('-start_date',)
14
- list_display = ('email','username','is_active','is_staff','is_superuser')
15
 
16
  # fieldsets=((None,{'fields':('email','username')}),
17
  # (None,{'fields':('password',)}))
 
10
  class MyUserAdmin(admin.ModelAdmin):
11
 
12
  search_fields=('email','username')
13
+ ordering=('-joining_date',)
14
+ list_display = ('email','username','joining_date','is_active','is_staff','is_superuser')
15
 
16
  # fieldsets=((None,{'fields':('email','username')}),
17
  # (None,{'fields':('password',)}))
accounts/migrations/0003_user_joining_date.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 4.2.3 on 2023-07-27 01:18
2
+
3
+ from django.db import migrations, models
4
+ import django.utils.timezone
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('accounts', '0002_alter_user_is_active'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name='user',
16
+ name='joining_date',
17
+ field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Joining Date'),
18
+ ),
19
+ ]
accounts/models.py CHANGED
@@ -1,4 +1,5 @@
1
  from django.db import models
 
2
  from django.contrib.auth.models import AbstractBaseUser,PermissionsMixin,BaseUserManager
3
 
4
 
@@ -38,6 +39,7 @@ class User(AbstractBaseUser,PermissionsMixin):
38
 
39
  email = models.EmailField(verbose_name="Email Address",primary_key=True,max_length=255,unique=True)
40
  username = models.CharField("Name",max_length=150,unique=False)
 
41
  is_staff = models.BooleanField(default=False)
42
  is_superuser = models.BooleanField(default=False)
43
  is_active = models.BooleanField(default=True)
 
1
  from django.db import models
2
+ from django.utils import timezone
3
  from django.contrib.auth.models import AbstractBaseUser,PermissionsMixin,BaseUserManager
4
 
5
 
 
39
 
40
  email = models.EmailField(verbose_name="Email Address",primary_key=True,max_length=255,unique=True)
41
  username = models.CharField("Name",max_length=150,unique=False)
42
+ joining_date = models.DateTimeField("Joining Date",default=timezone.now)
43
  is_staff = models.BooleanField(default=False)
44
  is_superuser = models.BooleanField(default=False)
45
  is_active = models.BooleanField(default=True)
newdata.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"model": "polls.question", "pk": 1, "fields": {"author": "panthrianuj@gmail.com", "question_text": "What is your age group ?", "pub_date": "2023-07-26T08:45:41Z"}}, {"model": "polls.question", "pk": 2, "fields": {"author": "panthrianuj@gmail.com", "question_text": "who do you love the most?", "pub_date": "2023-07-26T09:44:13Z"}}, {"model": "polls.question", "pk": 3, "fields": {"author": "panthrianuj@gmail.com", "question_text": "which laptop is the best ?", "pub_date": "2023-07-26T16:24:56Z"}}, {"model": "polls.question", "pk": 4, "fields": {"author": "panthriankur@gmail.com", "question_text": "new question ?", "pub_date": "2023-07-28T06:10:51.731Z"}}, {"model": "polls.question", "pk": 8, "fields": {"author": "panthrianuj@gmail.com", "question_text": "dffg", "pub_date": "2023-07-28T09:01:45.976Z"}}, {"model": "polls.question", "pk": 9, "fields": {"author": "panthrianuj@gmail.com", "question_text": "dffg", "pub_date": "2023-07-28T09:02:31.530Z"}}, {"model": "polls.choice", "pk": 1, "fields": {"question": 1, "choice_text": "under 15"}}, {"model": "polls.choice", "pk": 2, "fields": {"question": 1, "choice_text": "16-18"}}, {"model": "polls.choice", "pk": 3, "fields": {"question": 1, "choice_text": "20-24"}}, {"model": "polls.choice", "pk": 4, "fields": {"question": 2, "choice_text": "Friends"}}, {"model": "polls.choice", "pk": 5, "fields": {"question": 2, "choice_text": "Family"}}, {"model": "polls.choice", "pk": 6, "fields": {"question": 3, "choice_text": "Acer"}}, {"model": "polls.choice", "pk": 7, "fields": {"question": 3, "choice_text": "Msi"}}, {"model": "polls.choice", "pk": 8, "fields": {"question": 3, "choice_text": "Hp"}}, {"model": "polls.choice", "pk": 9, "fields": {"question": 3, "choice_text": "Dell"}}, {"model": "polls.choice", "pk": 10, "fields": {"question": 3, "choice_text": "Asus"}}, {"model": "polls.choice", "pk": 11, "fields": {"question": 4, "choice_text": "me"}}, {"model": "polls.choice", "pk": 12, "fields": {"question": 4, "choice_text": "you"}}, {"model": "polls.choice", "pk": 19, "fields": {"question": 8, "choice_text": "{{ choice.choice_text }}"}}, {"model": "polls.choice", "pk": 20, "fields": {"question": 8, "choice_text": "{{ choice.choice_text }}"}}, {"model": "polls.choice", "pk": 21, "fields": {"question": 8, "choice_text": "{{ choice.choice_text }}"}}, {"model": "polls.choice", "pk": 22, "fields": {"question": 9, "choice_text": "{{ choice.choice_text }}"}}, {"model": "polls.choice", "pk": 23, "fields": {"question": 9, "choice_text": "{{ choice.choice_text }}"}}, {"model": "polls.choice", "pk": 24, "fields": {"question": 9, "choice_text": "{{ choice.choice_text }}"}}]
polls/admin.py CHANGED
@@ -1,21 +1,32 @@
1
  from django.contrib import admin
2
- from .models import Question,Choice
3
 
4
 
5
  class ChoiceInline(admin.TabularInline):
6
- # fields=['question_text','pub_date']
7
- model=Choice
8
- extra=2
9
 
10
  class QuestionAdmin(admin.ModelAdmin):
11
- # fields=['question_text','pub_date']
12
-
13
- fieldsets=[("question",{"fields":['question_text']}),
14
- ("Date information",{"fields":['pub_date']})]
15
 
16
  inlines = [ChoiceInline]
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
 
19
  # Register your models here.
20
  admin.site.register(Question,QuestionAdmin)
21
- admin.site.register(Choice)
 
 
1
  from django.contrib import admin
2
+ from .models import Question,Choice,Vote
3
 
4
 
5
  class ChoiceInline(admin.TabularInline):
6
+ fields = ['choice_text']
7
+ model = Choice
8
+ extra = 2
9
 
10
  class QuestionAdmin(admin.ModelAdmin):
11
+ # fields=['question_text','pub_date','author']
 
 
 
12
 
13
  inlines = [ChoiceInline]
14
+
15
+ readonly_fields = ['pub_date']
16
+
17
+
18
+
19
+
20
+ fieldsets = [("question",{"fields":['question_text']}),
21
+ ("Meta data",{"fields":['pub_date','author']})]
22
+
23
+ model = Question
24
+
25
+ def get_changeform_initial_data(self, request):
26
+ return {"author": request.user}
27
 
28
 
29
  # Register your models here.
30
  admin.site.register(Question,QuestionAdmin)
31
+ admin.site.register(Choice)
32
+ admin.site.register(Vote)
polls/forms.py CHANGED
@@ -1,6 +1,7 @@
1
  from django import forms
2
  from django.contrib.auth import get_user_model
3
  from accounts.forms import UserAdminCreationForm,UserAdminUpdateForm
 
4
 
5
  User=get_user_model()
6
 
@@ -12,3 +13,11 @@ class UserSignupForm(UserAdminCreationForm):
12
  class UserLoginForm(forms.Form):
13
  email = forms.EmailField()
14
  password = forms.CharField(widget=forms.PasswordInput)
 
 
 
 
 
 
 
 
 
1
  from django import forms
2
  from django.contrib.auth import get_user_model
3
  from accounts.forms import UserAdminCreationForm,UserAdminUpdateForm
4
+ from .models import Question
5
 
6
  User=get_user_model()
7
 
 
13
  class UserLoginForm(forms.Form):
14
  email = forms.EmailField()
15
  password = forms.CharField(widget=forms.PasswordInput)
16
+
17
+
18
+ class QuestionForm(forms.ModelForm):
19
+ class Meta:
20
+ model=Question
21
+ fields=('question_text','pub_date','author')
22
+
23
+
polls/migrations/0002_question_author.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 4.2.3 on 2023-07-27 01:27
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+ ('polls', '0001_initial'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.AddField(
17
+ model_name='question',
18
+ name='author',
19
+ field=models.ForeignKey(default='panthrianuj@gmail.com', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
20
+ preserve_default=False,
21
+ ),
22
+ ]
polls/migrations/0003_remove_choice_votes_votes.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 4.2.3 on 2023-07-28 06:29
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations, models
5
+ import django.db.models.deletion
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+ ('polls', '0002_question_author'),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.RemoveField(
17
+ model_name='choice',
18
+ name='votes',
19
+ ),
20
+ migrations.CreateModel(
21
+ name='Votes',
22
+ fields=[
23
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24
+ ('choice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.choice')),
25
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
26
+ ],
27
+ ),
28
+ ]
polls/migrations/0004_rename_votes_vote.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 4.2.3 on 2023-07-28 06:32
2
+
3
+ from django.conf import settings
4
+ from django.db import migrations
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
11
+ ('polls', '0003_remove_choice_votes_votes'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.RenameModel(
16
+ old_name='Votes',
17
+ new_name='Vote',
18
+ ),
19
+ ]
polls/models.py CHANGED
@@ -1,10 +1,13 @@
1
  from django.db import models
2
  import datetime
3
  from django.utils import timezone
 
4
 
 
5
  # Create your models here.
6
  class Question(models.Model):
7
 
 
8
  question_text = models.CharField(max_length=300)
9
  pub_date = models.DateTimeField("date published",default=datetime.datetime.now)
10
 
@@ -13,7 +16,11 @@ class Question(models.Model):
13
 
14
  @property
15
  def total_votes(self):
16
- return self.choice_set.aggregate(models.Sum('votes'))['votes__sum']
 
 
 
 
17
  def was_recently_pub(self):
18
  return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
19
 
@@ -22,7 +29,19 @@ class Choice(models.Model):
22
 
23
  question = models.ForeignKey(Question, on_delete=models.CASCADE)
24
  choice_text = models.CharField(max_length=200)
25
- votes = models.IntegerField(default=0)
26
 
27
  def __str__(self):
28
- return self.question.question_text+"-"*5+self.choice_text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from django.db import models
2
  import datetime
3
  from django.utils import timezone
4
+ from django.contrib.auth import get_user_model
5
 
6
+ User=get_user_model()
7
  # Create your models here.
8
  class Question(models.Model):
9
 
10
+ author = models.ForeignKey(User,on_delete=models.CASCADE)
11
  question_text = models.CharField(max_length=300)
12
  pub_date = models.DateTimeField("date published",default=datetime.datetime.now)
13
 
 
16
 
17
  @property
18
  def total_votes(self):
19
+ return len(Vote.objects.filter(choice__question__pk=self.pk))
20
+
21
+ def has_user_voted(self,user):
22
+ return len(Vote.objects.filter(choice__question__pk=self.pk,user=user))>0
23
+
24
  def was_recently_pub(self):
25
  return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
26
 
 
29
 
30
  question = models.ForeignKey(Question, on_delete=models.CASCADE)
31
  choice_text = models.CharField(max_length=200)
 
32
 
33
  def __str__(self):
34
+ return self.question.question_text+"-"*5+self.choice_text
35
+
36
+ @property
37
+ def vote_count(self):
38
+ return len(Vote.objects.filter(choice=self.pk))
39
+ @property
40
+ def vote_percent(self):
41
+ return "{:.2f}".format(((self.vote_count/(self.question.total_votes))*100))
42
+
43
+
44
+
45
+ class Vote(models.Model):
46
+ user = models.ForeignKey(User, on_delete=models.CASCADE)
47
+ choice = models.ForeignKey(Choice, on_delete=models.CASCADE)
polls/static/polls/create.css ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*********************sub header***************************/
2
+ #sub_header{
3
+ font-weight:100;
4
+ padding:40px 40px;
5
+ padding-bottom: 0px;
6
+ }
7
+
8
+
9
+ /*******************main container*******************************/
10
+
11
+ #main_container{
12
+ display: flex;
13
+ flex-direction: column;
14
+ align-items: center;
15
+
16
+ }
17
+
18
+ .question_container{
19
+ width:500px;
20
+
21
+ color:#ffffff;
22
+ background-color: #5B66C6;
23
+
24
+ border-radius: 7px;
25
+ box-shadow: 0px 20px 52px 0px #0000004b;
26
+ overflow: hidden;
27
+ margin-top:40px;
28
+ }
29
+ .question_container:last-child{
30
+ margin-bottom:40px;
31
+ }
32
+
33
+ .question_header{
34
+ padding: 30px 20px;
35
+ display: flex;
36
+ flex-direction: row;
37
+ align-items: center;
38
+ justify-content: space-between;
39
+
40
+ }
41
+
42
+
43
+ .question_meta{
44
+ display: flex;
45
+ flex-direction: column;
46
+ align-items: center;
47
+ justify-content: center;
48
+ margin-right: 30px;
49
+
50
+ font-size: small;
51
+ font-weight: 100;
52
+ }
53
+
54
+ .question_header>#question_text{
55
+ height: 20px;
56
+ width: 60%;
57
+ color:white;
58
+ background-color: #5B66C6;
59
+ border:none;
60
+ outline: none;
61
+ border-bottom:white solid 2px;
62
+
63
+ display: block;
64
+ overflow: hidden;
65
+ resize: none;
66
+ }
67
+ .question_header>#question_text::placeholder{
68
+ color:#dddbdb;
69
+ }
70
+
71
+ .question_header>.right_section{
72
+ display: flex;
73
+ align-items: center;
74
+
75
+ }
76
+ .question_header>.right_section>img{
77
+ fill: white;
78
+ height: 25px;
79
+
80
+
81
+ }
82
+
83
+ .question_container>.form_container{
84
+ box-sizing: border-box;
85
+ padding: 10px 20px;
86
+ width: 100%;
87
+ border-radius: 7px;
88
+
89
+ background-color: white;
90
+
91
+
92
+ display:flex;
93
+ flex-direction: column;
94
+ align-items: center;
95
+
96
+ }
97
+ .choices{
98
+ margin-top: 30px;
99
+ width: 100%;
100
+ }
101
+
102
+ .choice{
103
+ margin: 10px 0;
104
+ padding: 10px 20px;
105
+
106
+ background-color: #5b66c670;
107
+
108
+ border-radius: 3px;
109
+
110
+ display: flex;
111
+ position: relative;
112
+ }
113
+
114
+ .choice_text{
115
+ margin-left: 20px;
116
+ width: 80%;
117
+
118
+ color:white;
119
+ background-color:transparent;
120
+ border:none;
121
+ outline: none;
122
+ border-bottom:white solid 2px;
123
+
124
+ display: block;
125
+ overflow: hidden;
126
+ resize: none;
127
+ }
128
+ .remove_choice_btn{
129
+ position: absolute;
130
+ right:20px;
131
+ color: red;
132
+ /* top:2px; */
133
+ }
134
+ .remove_choice_btn:hover{
135
+ cursor: pointer;
136
+ }
137
+ .create_btn{
138
+ margin: 10px 0;
139
+ border:none;
140
+ outline: none;
141
+
142
+ background-color: #5B66C6;
143
+ color: white;
144
+ padding: 10px 30px;
145
+ border-radius: 8px;
146
+ }
147
+
148
+ .create_btn:hover{
149
+ cursor: pointer;
150
+ }
151
+
152
+
153
+ #add_option{
154
+ color:#5B66C6;
155
+
156
+ }
157
+ #add_option:hover{
158
+ text-decoration:#5B66C6 underline solid 2px;
159
+ cursor: pointer;
160
+ }
polls/static/polls/create.js ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ var tx = document.getElementsByTagName('textarea');
3
+ for (var i = 0; i < tx.length; i++) {
4
+ tx[i].setAttribute('style', 'height:' + (tx[i].scrollHeight) + 'px;overflow-y:hidden;');
5
+ tx[i].addEventListener("input", OnInput, false);
6
+ }
7
+
8
+ function OnInput(e) {
9
+ e.target.style.height = 'auto';
10
+ e.target.style.height = (e.target.scrollHeight) + 'px';
11
+ }
12
+
13
+
14
+ function getCookie(name) {
15
+ let cookieValue = null;
16
+
17
+ if (document.cookie && document.cookie !== '') {
18
+ const cookies = document.cookie.split(';');
19
+ for (let i = 0; i < cookies.length; i++) {
20
+ const cookie = cookies[i].trim();
21
+
22
+ // Does this cookie string begin with the name we want?
23
+ if (cookie.substring(0, name.length + 1) === (name + '=')) {
24
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
25
+
26
+ break;
27
+ }
28
+ }
29
+ }
30
+
31
+ return cookieValue;
32
+ }
33
+ const csrftoken = getCookie('csrftoken');
34
+
35
+
36
+
37
+
38
+
39
+ function number_choices(){
40
+ var i=0;
41
+ var choice_list=document.querySelectorAll(".choices>.choice");
42
+ choice_list.forEach(choice=>{
43
+ i++;
44
+ choice.querySelector("span>span").innerHTML=String.fromCharCode(i+64);
45
+ })
46
+
47
+
48
+ }
49
+
50
+ function create_choice(){
51
+ /*
52
+ <div class="choice">
53
+ <span>
54
+ <span>{{ forloop.counter|add:"64"|stringformat:"c" }}</span>
55
+ <span> -</span>
56
+ </span>
57
+ <span class="choice_text">{{ choice.choice_text }}</span>
58
+ </div>
59
+ */
60
+
61
+ // <div class="remove_choice_btn" onclick="delete_choice()">X</div>
62
+
63
+
64
+ var choices_div=document.querySelector(".choices");
65
+ var choice_div=document.createElement("div");
66
+ choice_div.className="choice";
67
+
68
+
69
+ choice_div.innerHTML=`<span>\
70
+ <span>A</span>\
71
+ <span> -</span>\
72
+ </span>\
73
+ <textarea class="choice_text" oninput="OnInput(event)"></textarea>`;
74
+
75
+ if (choices_div.querySelectorAll(".choice").length>0){
76
+ choice_div.innerHTML+=`<div class="remove_choice_btn" onclick="delete_choice(this)">X</div>`;
77
+ }
78
+
79
+ choices_div.appendChild(choice_div);
80
+
81
+ number_choices();
82
+
83
+
84
+ }
85
+
86
+ function delete_choice(elem){
87
+
88
+ elem.parentNode.remove();
89
+ number_choices();
90
+ }
91
+
92
+
93
+ function validate(){
94
+ if(question_text.value==''){
95
+ question_text.style.borderBottom="2px solid red";
96
+ question_text.focus();
97
+
98
+ return false;
99
+ }
100
+ else{
101
+ question_text.style.removeProperty("border-bottom");
102
+ }
103
+
104
+ choice_list=document.querySelectorAll(".choice");
105
+ var i=0;
106
+ for(i=0;i<choice_list.length;i++){
107
+ choice_text=choice_list[i].querySelector(".choice_text");
108
+
109
+ if(choice_text.value==""){
110
+ choice_text.style.borderBottom="2px solid red";
111
+ choice_text.focus();
112
+ return false
113
+ }
114
+ else{
115
+ choice_text.style.removeProperty("border-bottom");
116
+ }
117
+ }
118
+
119
+ return true;
120
+ }
121
+
122
+
123
+
124
+ function create_question(){
125
+ if(!validate()) return;
126
+
127
+ var data_to_send = {};
128
+
129
+
130
+
131
+
132
+ var choice_text_list=[];
133
+ choice_list=document.querySelectorAll(".choice");
134
+ var i=0;
135
+ for(i=0;i<choice_list.length;i++){
136
+ choice_text=choice_list[i].querySelector(".choice_text");
137
+
138
+ choice_text_list.push(choice_text.value);
139
+
140
+ }
141
+
142
+ // console.log(question_text.value);
143
+ // console.log(choice_text_list);
144
+
145
+ data_to_send["question_text"]=question_text.value;
146
+ data_to_send["choice_text_list"]=choice_text_list;
147
+
148
+ fetch("",{
149
+ method:"POST",
150
+ headers:{
151
+ 'X-CSRFToken': csrftoken
152
+ },
153
+ body:JSON.stringify(data_to_send)
154
+ }).then(res=>res.json()).then(res=>{
155
+ console.log(res);
156
+ if (!res.hasOwnProperty("error_message")){
157
+ window.location.href = res["redirect"];
158
+ }
159
+ });
160
+
161
+ }
162
+
163
+ create_choice();
164
+ create_choice();
polls/static/polls/header.css ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *{
2
+ padding:0px;
3
+ margin: 0px;
4
+ }
5
+ header{
6
+ background-color: #5B66C6;
7
+ color:white;
8
+ height:80px;
9
+ display: flex;
10
+ flex-direction: row;
11
+ align-items: center;
12
+ justify-content: space-between;
13
+ padding: 0 80px;
14
+ }
15
+ header>#app_name{
16
+ font-size: larger;
17
+ }
18
+
19
+ #profile{
20
+ background-color: #00000058;
21
+
22
+ height: 60px;
23
+ aspect-ratio: 1;
24
+ border-radius: 50%;
25
+ position:relative;
26
+ }
27
+ #profile:hover{
28
+ cursor: pointer;
29
+ }
30
+
31
+ #profile>#first_alpha{
32
+ position:absolute;
33
+ top:50%;
34
+ left:50%;
35
+ transform: translate(-50%,-50%);
36
+
37
+ }
38
+
39
+ #profile>#profile_options{
40
+ position: absolute;
41
+ right:0;
42
+ top: 100%;
43
+ margin-top:10px;
44
+
45
+ background-color: #ffffff;
46
+
47
+ width: 180px;
48
+
49
+ box-shadow: 0px 4px 29px 0px #0000004b;
50
+ border-radius: 10px;
51
+
52
+ overflow: hidden;
53
+ }
54
+ #profile_options.hidden{
55
+ display: none;
56
+ }
57
+
58
+ #profile_options>.option{
59
+
60
+ padding: 10px 0;
61
+ color:black;
62
+ border-bottom: #C3C3C3 solid 1px;
63
+ text-decoration: none;
64
+ display: flex;
65
+ flex-direction: column;
66
+ align-items: center;
67
+ }
68
+
69
+ #profile_options>.option:last-child{
70
+ border-bottom:none; /*used to remove border of last option*/
71
+ }
72
+
73
+ #profile_options>.option:hover{
74
+ background-color: gray;
75
+ color:white;
76
+ }
77
+
polls/static/polls/index.css CHANGED
@@ -35,87 +35,13 @@
35
 
36
  /***********************New css*****************************/
37
 
38
-
39
- *{
40
- padding:0px;
41
- margin: 0px;
42
- }
43
-
44
-
45
-
46
-
47
- header{
48
- background-color: #5B66C6;
49
- color:white;
50
- height:80px;
51
- display: flex;
52
- flex-direction: row;
53
- align-items: center;
54
- justify-content: space-between;
55
- padding: 0 80px;
56
- }
57
- header>#app_name{
58
- font-size: larger;
59
- }
60
-
61
- #profile{
62
- background-color: #00000058;
63
-
64
- height: 60px;
65
- aspect-ratio: 1;
66
- border-radius: 50%;
67
- position:relative;
68
- }
69
- #profile:hover{
70
- cursor: pointer;
71
- }
72
-
73
- #profile>#first_alpha{
74
- position:absolute;
75
- top:50%;
76
- left:50%;
77
- transform: translate(-50%,-50%);
78
-
79
- }
80
-
81
- #profile>#profile_options{
82
- position: absolute;
83
- right:0;
84
- top: 100%;
85
- margin-top:10px;
86
-
87
- background-color: #ffffff;
88
-
89
- width: 180px;
90
-
91
- box-shadow: 0px 4px 29px 0px #0000004b;
92
- border-radius: 10px;
93
-
94
- overflow: hidden;
95
- }
96
- #profile_options.hidden{
97
- display: none;
98
- }
99
-
100
- #profile_options>.option{
101
-
102
- padding: 10px 0;
103
- color:black;
104
- border-bottom: #C3C3C3 solid 1px;
105
-
106
- display: flex;
107
- flex-direction: column;
108
- align-items: center;
109
  }
110
 
111
- #profile_options>.option:last-child{
112
- border-bottom:none; /*used to remove border of last option*/
113
- }
114
 
115
- #profile_options>.option:hover{
116
- background-color: gray;
117
- color:white;
118
- }
119
 
120
 
121
 
@@ -141,13 +67,16 @@ header>#app_name{
141
  width:500px;
142
 
143
  color:#ffffff;
144
- background-color: #5B66C6;
145
 
146
  border-radius: 7px;
147
  box-shadow: 0px 20px 52px 0px #0000004b;
148
  overflow: hidden;
149
  margin-top:40px;
150
  }
 
 
 
151
 
152
  .question_header{
153
  padding: 10px 20px;
@@ -169,8 +98,15 @@ header>#app_name{
169
  font-weight: 100;
170
  }
171
 
172
- .question_header>span{
173
  width: 60%;
 
 
 
 
 
 
 
174
  }
175
  .question_header>.right_section{
176
  display: flex;
@@ -207,27 +143,44 @@ header>#app_name{
207
  margin: 10px 0;
208
  padding: 10px 20px;
209
 
210
- background-color: #5b66c670;
211
 
212
  border-radius: 3px;
 
213
  }
214
 
215
  .choice_text{
216
  margin-left: 20px;
 
 
 
 
 
 
 
 
 
 
217
  }
218
 
219
  .choice:hover{
220
- background-color: #5B66C6;
221
  /* color:#C3C3C3; */
222
  cursor: pointer;
223
  }
 
 
 
 
 
 
224
 
225
  .vote_btn{
226
  margin: 10px 0;
227
  border:none;
228
  outline: none;
229
 
230
- background-color: #5B66C6;
231
  color: white;
232
  padding: 10px 30px;
233
  border-radius: 8px;
 
35
 
36
  /***********************New css*****************************/
37
 
38
+ :root{
39
+ --primary-color:#5B66C6;
40
+ --secondary-color:#5b66c670;
41
+ --percentage-color:#7a73ff;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  }
43
 
 
 
 
44
 
 
 
 
 
45
 
46
 
47
 
 
67
  width:500px;
68
 
69
  color:#ffffff;
70
+ background-color: var(--primary-color);
71
 
72
  border-radius: 7px;
73
  box-shadow: 0px 20px 52px 0px #0000004b;
74
  overflow: hidden;
75
  margin-top:40px;
76
  }
77
+ .question_container:last-child{
78
+ margin-bottom:40px;
79
+ }
80
 
81
  .question_header{
82
  padding: 10px 20px;
 
98
  font-weight: 100;
99
  }
100
 
101
+ .question_header>.question_text{
102
  width: 60%;
103
+ color:white;
104
+ background-color: var(--primary-color);
105
+ border:none;
106
+ outline: none;
107
+
108
+ overflow: hidden;
109
+ resize: none;
110
  }
111
  .question_header>.right_section{
112
  display: flex;
 
143
  margin: 10px 0;
144
  padding: 10px 20px;
145
 
146
+ background-color: var(--secondary-color);
147
 
148
  border-radius: 3px;
149
+ display: flex;
150
  }
151
 
152
  .choice_text{
153
  margin-left: 20px;
154
+ width: 70%;
155
+ color:white;
156
+ background-color:transparent;
157
+ border:none;
158
+ outline: none;
159
+ overflow: hidden;
160
+ resize: none;
161
+ }
162
+ .choice_text:hover{
163
+ cursor:pointer;
164
  }
165
 
166
  .choice:hover{
167
+ background-color: var(--primary-color);
168
  /* color:#C3C3C3; */
169
  cursor: pointer;
170
  }
171
+ .choice.active{
172
+ background-color: var(--primary-color);
173
+ }
174
+ /* .choices.result>.choice{
175
+ background: linear-gradient(90deg, var(--percentage-color) 50%, var(--secondary-color) 0%);
176
+ } */
177
 
178
  .vote_btn{
179
  margin: 10px 0;
180
  border:none;
181
  outline: none;
182
 
183
+ background-color: var(--primary-color);
184
  color: white;
185
  padding: 10px 30px;
186
  border-radius: 8px;
polls/static/polls/index.js ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ var tx = document.getElementsByTagName('textarea');
3
+ for (var i = 0; i < tx.length; i++) {
4
+ tx[i].setAttribute('style', 'height:' + (tx[i].scrollHeight) + 'px;overflow-y:hidden;');
5
+ tx[i].addEventListener("input", OnInput, false);
6
+ }
7
+
8
+ function OnInput(e) {
9
+ e.target.style.height = 'auto';
10
+ e.target.style.height = (e.target.scrollHeight) + 'px';
11
+ }
12
+
13
+
14
+ function getCookie(name) {
15
+ let cookieValue = null;
16
+
17
+ if (document.cookie && document.cookie !== '') {
18
+ const cookies = document.cookie.split(';');
19
+ for (let i = 0; i < cookies.length; i++) {
20
+ const cookie = cookies[i].trim();
21
+
22
+ // Does this cookie string begin with the name we want?
23
+ if (cookie.substring(0, name.length + 1) === (name + '=')) {
24
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
25
+
26
+ break;
27
+ }
28
+ }
29
+ }
30
+
31
+ return cookieValue;
32
+ }
33
+ const csrftoken = getCookie('csrftoken');
34
+
35
+
36
+
37
+
38
+
39
+ function select_option(elem){
40
+ elem.parentNode.querySelectorAll(".choice.active").forEach(choice => {
41
+ if (elem!=choice)
42
+ choice.classList.remove("active");
43
+ });
44
+ elem.classList.toggle("active");
45
+ }
46
+
47
+
48
+ function validate(elem){
49
+ var active_choices=elem.querySelectorAll(".choice.active");
50
+ for(var i=0;i<active_choices.length;i++){
51
+ return true;
52
+ }
53
+
54
+ return false;
55
+ }
56
+
57
+ function Vote(elem){
58
+ if(!validate(elem.parentElement)) return;
59
+
60
+ var data_to_send = {};
61
+
62
+
63
+ data_to_send["choice_id"]=elem.parentElement.querySelector('.choice.active').dataset.id;
64
+
65
+ fetch("vote/",{
66
+ method:"POST",
67
+ headers:{
68
+ 'X-CSRFToken': csrftoken
69
+ },
70
+ body:JSON.stringify(data_to_send)
71
+ }).then(res=>res.json()).then(res=>{
72
+ console.log(res);
73
+
74
+ if (res["message"]=="success"){
75
+
76
+ elem.parentElement.querySelectorAll(".choice").forEach(choice=>{
77
+ choice.dataset.percent=res['vote_percent_dict'][choice.dataset.id];
78
+ show_result(choice);
79
+ });
80
+ // update total vote by adding 1
81
+ var total_votes=elem.parentElement.parentElement.querySelector(".total_votes");
82
+ total_votes.innerText=parseInt(total_votes.innerText)+1;
83
+ console.log(total_votes);
84
+
85
+ }
86
+
87
+ });
88
+
89
+
90
+ }
91
+
92
+ document.querySelectorAll(".choices.result>.choice").forEach(choice=>{
93
+ console.log(choice.dataset.percent);
94
+ show_result(choice);
95
+ });
96
+
97
+ function show_result(choice){
98
+ choice.style.background= `linear-gradient(90deg, var(--percentage-color) ${choice.dataset.percent}%, var(--secondary-color) 0%)`;
99
+ choice.innerHTML+=choice.dataset.percent+"%";
100
+ }
polls/static/polls/your_polls.css ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* .questions{
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ }
5
+ .question{
6
+ background-color: rgb(133, 127, 255);
7
+ color: white;
8
+ padding: 4px;
9
+ margin:20px 4px;
10
+ width:140px;
11
+ height: 150px;
12
+ border-radius: 10px;
13
+ position:relative;
14
+ }
15
+ .question>.question_text{
16
+ font: caption;
17
+ margin: 0px;
18
+ padding: 0px;
19
+ margin-bottom: 14px;
20
+ }
21
+ .question:hover{
22
+ cursor: pointer;
23
+ }
24
+
25
+ .total_count{
26
+ font:-webkit-control;
27
+ color: black;
28
+ position:absolute;
29
+ bottom: 5px;
30
+ right: 5px;
31
+ padding: 0;
32
+ margin: 0;
33
+ } */
34
+
35
+
36
+ /***********************New css*****************************/
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+ /*********************sub header***************************/
46
+ #sub_header{
47
+ font-weight:100;
48
+ padding:40px 40px;
49
+ padding-bottom: 0px;
50
+ }
51
+
52
+
53
+ /*******************main container*******************************/
54
+
55
+ #main_container{
56
+ display: flex;
57
+ flex-direction: column;
58
+ align-items: center;
59
+
60
+ }
61
+
62
+ .question_container{
63
+ width:500px;
64
+
65
+ color:#ffffff;
66
+ background-color: #5B66C6;
67
+
68
+ border-radius: 7px;
69
+ box-shadow: 0px 20px 52px 0px #0000004b;
70
+ overflow: hidden;
71
+ margin-top:40px;
72
+ }
73
+ .question_container:last-child{
74
+ margin-bottom:40px;
75
+ }
76
+
77
+ .question_header{
78
+ padding: 10px 20px;
79
+ display: flex;
80
+ flex-direction: row;
81
+ align-items: center;
82
+ justify-content: space-between;
83
+
84
+ }
85
+
86
+ .question_meta{
87
+ display: flex;
88
+ flex-direction: column;
89
+ align-items: center;
90
+ justify-content: center;
91
+ margin-right: 30px;
92
+
93
+ font-size: small;
94
+ font-weight: 100;
95
+ }
96
+
97
+ .question_header>.question_text{
98
+ width: 60%;
99
+ color:white;
100
+ background-color: #5B66C6;
101
+ border:none;
102
+ outline: none;
103
+
104
+ overflow: hidden;
105
+ resize: none;
106
+ }
107
+ .question_header>.right_section{
108
+ display: flex;
109
+ align-items: center;
110
+
111
+ }
112
+ .question_header>.right_section>img{
113
+ fill: white;
114
+ height: 25px;
115
+
116
+
117
+ }
118
+
119
+ .question_container>.form_container{
120
+ box-sizing: border-box;
121
+ padding: 10px 20px;
122
+ width: 100%;
123
+ border-radius: 7px;
124
+
125
+ background-color: white;
126
+
127
+
128
+ display:flex;
129
+ flex-direction: column;
130
+ align-items: center;
131
+
132
+ }
133
+ .choices{
134
+ margin-top: 30px;
135
+ width: 100%;
136
+ }
137
+
138
+ .choice{
139
+ margin: 10px 0;
140
+ padding: 10px 20px;
141
+
142
+ background-color: #5b66c670;
143
+
144
+ border-radius: 3px;
145
+ display: flex;
146
+ }
147
+
148
+ .choice_text{
149
+ margin-left: 20px;
150
+ color:white;
151
+ background-color:transparent;
152
+ border:none;
153
+ outline: none;
154
+ overflow: hidden;
155
+ resize: none;
156
+ }
157
+ .choice_text:hover{
158
+ cursor:pointer;
159
+ }
160
+
161
+ .choice:hover{
162
+ background-color: #5B66C6;
163
+ /* color:#C3C3C3; */
164
+ cursor: pointer;
165
+ }
166
+
167
+ .vote_btn{
168
+ margin: 10px 0;
169
+ border:none;
170
+ outline: none;
171
+
172
+ background-color: #5B66C6;
173
+ color: white;
174
+ padding: 10px 30px;
175
+ border-radius: 8px;
176
+ }
177
+
178
+ .vote_btn:hover{
179
+ cursor: pointer;
180
+ }
polls/static/polls/your_polls.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ var tx = document.getElementsByTagName('textarea');
3
+ for (var i = 0; i < tx.length; i++) {
4
+ tx[i].setAttribute('style', 'height:' + (tx[i].scrollHeight) + 'px;overflow-y:hidden;');
5
+ tx[i].addEventListener("input", OnInput, false);
6
+ }
7
+
8
+ function OnInput(e) {
9
+ e.target.style.height = 'auto';
10
+ e.target.style.height = (e.target.scrollHeight) + 'px';
11
+ }
12
+
13
+
14
+ function getCookie(name) {
15
+ let cookieValue = null;
16
+
17
+ if (document.cookie && document.cookie !== '') {
18
+ const cookies = document.cookie.split(';');
19
+ for (let i = 0; i < cookies.length; i++) {
20
+ const cookie = cookies[i].trim();
21
+
22
+ // Does this cookie string begin with the name we want?
23
+ if (cookie.substring(0, name.length + 1) === (name + '=')) {
24
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
25
+
26
+ break;
27
+ }
28
+ }
29
+ }
30
+
31
+ return cookieValue;
32
+ }
33
+ const csrftoken = getCookie('csrftoken');
34
+
35
+
36
+
37
+ function validate(){
38
+ if(question_text.value==''){
39
+ question_text.style.borderBottom="2px solid red";
40
+ question_text.focus();
41
+
42
+ return false;
43
+ }
44
+ else{
45
+ question_text.style.removeProperty("border-bottom");
46
+ }
47
+
48
+ choice_list=document.querySelectorAll(".choice");
49
+ var i=0;
50
+ for(i=0;i<choice_list.length;i++){
51
+ choice_text=choice_list[i].querySelector(".choice_text");
52
+
53
+ if(choice_text.value==""){
54
+ choice_text.style.borderBottom="2px solid red";
55
+ choice_text.focus();
56
+ return false
57
+ }
58
+ else{
59
+ choice_text.style.removeProperty("border-bottom");
60
+ }
61
+ }
62
+
63
+ return true;
64
+ }
polls/templates/polls/base.html ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ {% load static %}
4
+ <link type="text/css" rel="stylesheet" href="{% static 'polls/header.css' %}">
5
+ {% include 'polls/font.html' %}
6
+
7
+ {% block head %}{% endblock %}
8
+
9
+ </head>
10
+ <body>
11
+ {% include 'polls/header.html' %}
12
+
13
+ {% block body %}{% endblock %}
14
+ <script src="{% static 'polls/header.js' %}"></script>
15
+ </body>
16
+ </html>
polls/templates/polls/create.html ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'polls/base.html' %}
2
+
3
+ {% block head %}
4
+ {% load static %}
5
+ <link type="text/css" rel="stylesheet" href="{% static 'polls/create.css' %}">
6
+ {% endblock %}
7
+
8
+ {% block body %}
9
+
10
+ <h2 id="sub_header">Create Poll</h2>
11
+
12
+
13
+
14
+
15
+ <div id="main_container">
16
+
17
+
18
+ <div class="question_container">
19
+ <div class="question_header">
20
+ <textarea id="question_text" placeholder="New question"></textarea>
21
+
22
+ </div>
23
+ <div class="form_container">
24
+ <div class="choices">
25
+
26
+
27
+ </div>
28
+ <span id="add_option" onclick="create_choice()">Add option</span>
29
+ <button class="create_btn" onclick="create_question()">Create</button>
30
+
31
+ </div>
32
+ </div>
33
+
34
+ </div>
35
+
36
+
37
+ <!-- {% if latest_questions_list %}
38
+
39
+ <div class="questions" >
40
+ {% for question in latest_questions_list %}
41
+
42
+ <div class="question" onclick="window.location.href = `{% url 'polls:detail' question.id %}`;">
43
+ <p class="question_text">{{ question }}</p>
44
+ <p class="total_count">Votes:{{ question.total_votes }}</p>
45
+ </div>
46
+ {% endfor %}
47
+ </div>
48
+
49
+
50
+ {% else %}
51
+ <p>No questions yet</p>
52
+ {% endif %} -->
53
+ <script src="{% static 'polls/create.js' %}"></script>
54
+
55
+ {% endblock %}
polls/templates/polls/header.html ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <header>
2
+ <span id="app_name">Polling App</span>
3
+
4
+ <div id="profile" onclick="toggle_profile_options(event)">
5
+ <span id="first_alpha">{{ request.user }}</span>
6
+
7
+ <div id="profile_options" class="hidden">
8
+ <a class="option" href="{% url 'polls:create' %}">Create Poll</a>
9
+ <a class="option" href="{% url 'polls:your_polls' %}">Your Polls</a>
10
+ <a class="option" href = "{% url 'polls:your_votes' %}">Your Votes</a>
11
+ <a class="option" href = "{% url 'polls:settings' %}">Settings</a>
12
+ <a class="option" href = "{% url 'polls:logout' %}">Log Out</a>
13
+ </div>
14
+
15
+ </div>
16
+ </header>
polls/templates/polls/index.html CHANGED
@@ -1,26 +1,12 @@
1
- <html>
2
- <head>
 
 
3
  {% load static %}
4
  <link type="text/css" rel="stylesheet" href="{% static 'polls/index.css' %}">
5
- {% include 'polls/font.html' %}
6
- </head>
7
- <body>
8
- <header>
9
- <span id="app_name">Polling App</span>
10
-
11
- <div id="profile" onclick="toggle_profile_options(event)">
12
- <span id="first_alpha">{{ request.user }}</span>
13
-
14
- <div id="profile_options" class="hidden">
15
- <div class="option">Create Poll</div>
16
- <div class="option">Your Polls</div>
17
- <div class="option">Your Votes</div>
18
- <div class="option">Settings</div>
19
- <div class="option">Log Out</div>
20
- </div>
21
 
22
- </div>
23
- </header>
24
 
25
  <h2 id="sub_header">Public Polls</h2>
26
 
@@ -32,11 +18,11 @@
32
 
33
  <div class="question_container">
34
  <div class="question_header">
35
- <span>{{ question.question_text }}</span>
36
  <div class="right_section">
37
  <div class="question_meta">
38
  <span>
39
- <span>{{ question.total_votes }}</span>
40
  Votes
41
  </span>
42
 
@@ -50,19 +36,26 @@
50
  </div>
51
  </div>
52
  <div class="form_container">
53
- <div class="choices">
54
 
55
  {% for choice in question.choice_set.all %}
56
- <div class="choice">
 
 
 
 
 
57
  <span>
58
  <span>{{ forloop.counter|add:"64"|stringformat:"c" }}</span>
59
  <span> -</span>
60
  </span>
61
- <span class="choice_text">{{ choice.choice_text }}</span>
 
 
62
  </div>
63
  {% endfor %}
64
  </div>
65
- <button class="vote_btn">Vote</button>
66
 
67
  </div>
68
  </div>
@@ -89,6 +82,5 @@
89
  {% else %}
90
  <p>No questions yet</p>
91
  {% endif %} -->
92
- <script src="{% static 'polls/header.js' %}"></script>
93
- </body>
94
- </html>
 
1
+ {% extends 'polls/base.html' %}
2
+
3
+ {% block head %}
4
+ {% load index %}
5
  {% load static %}
6
  <link type="text/css" rel="stylesheet" href="{% static 'polls/index.css' %}">
7
+ {% endblock %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ {% block body %}
 
10
 
11
  <h2 id="sub_header">Public Polls</h2>
12
 
 
18
 
19
  <div class="question_container">
20
  <div class="question_header">
21
+ <textarea oninput="OnInput(event)" class="question_text" readonly="true">{{ question.question_text }}</textarea>
22
  <div class="right_section">
23
  <div class="question_meta">
24
  <span>
25
+ <span class="total_votes">{{ question.total_votes }}</span>
26
  Votes
27
  </span>
28
 
 
36
  </div>
37
  </div>
38
  <div class="form_container">
39
+ <div class="choices {{ question.has_voted|yesno:'result,' }}">
40
 
41
  {% for choice in question.choice_set.all %}
42
+ <div class="choice" onclick="select_option(this)" data-id="{{ choice.pk }}"
43
+ {% if question.has_voted %}
44
+ data-percent="{{ choice.vote_percent }}"
45
+ {% endif %}
46
+ >
47
+
48
  <span>
49
  <span>{{ forloop.counter|add:"64"|stringformat:"c" }}</span>
50
  <span> -</span>
51
  </span>
52
+ <textarea class="choice_text" oninput="OnInput(event)" readonly="true">{{ choice.choice_text }}</textarea>
53
+
54
+
55
  </div>
56
  {% endfor %}
57
  </div>
58
+ <button class="vote_btn" onclick="Vote(this)">Vote</button>
59
 
60
  </div>
61
  </div>
 
82
  {% else %}
83
  <p>No questions yet</p>
84
  {% endif %} -->
85
+ <script src="{% static 'polls/index.js' %}"></script>
86
+ {% endblock %}
 
polls/templates/polls/your_polls.html ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends 'polls/base.html' %}
2
+
3
+ {% block head %}
4
+ {% load static %}
5
+ <link type="text/css" rel="stylesheet" href="{% static 'polls/index.css' %}">
6
+ {% endblock %}
7
+
8
+ {% block body %}
9
+
10
+ <h2 id="sub_header">Your Polls</h2>
11
+
12
+ {% if latest_questions_list %}
13
+
14
+
15
+ <div id="main_container">
16
+ {% for question in latest_questions_list %}
17
+
18
+ <div class="question_container">
19
+ <div class="question_header">
20
+ <textarea oninput="OnInput(event)" class="question_text" readonly="true">{{ question.question_text }}</textarea>
21
+ <div class="right_section">
22
+ <div class="question_meta">
23
+ <span>
24
+ <span>{{ question.total_votes }}</span>
25
+ Votes
26
+ </span>
27
+
28
+ <span>Results in
29
+ <span>1 hour</span>
30
+ </span>
31
+ </div>
32
+
33
+ <img src="{% static 'polls/arrow-up-right-from-square-solid.svg' %}">
34
+
35
+ </div>
36
+ </div>
37
+ <div class="form_container">
38
+ <div class="choices">
39
+
40
+ {% for choice in question.choice_set.all %}
41
+ <div class="choice">
42
+ <span>
43
+ <span>{{ forloop.counter|add:"64"|stringformat:"c" }}</span>
44
+ <span> -</span>
45
+ </span>
46
+ <textarea class="choice_text" oninput="OnInput(event)" readonly="true">{{ choice.choice_text }}</textarea>
47
+ </div>
48
+ {% endfor %}
49
+ </div>
50
+ <button class="vote_btn">Vote</button>
51
+
52
+ </div>
53
+ </div>
54
+ {% endfor %}
55
+ </div>
56
+
57
+
58
+ {% else %}
59
+ <p>No questions yet</p>
60
+ {% endif %}
61
+ <!-- {% if latest_questions_list %}
62
+
63
+ <div class="questions" >
64
+ {% for question in latest_questions_list %}
65
+
66
+ <div class="question" onclick="window.location.href = `{% url 'polls:detail' question.id %}`;">
67
+ <p class="question_text">{{ question }}</p>
68
+ <p class="total_count">Votes:{{ question.total_votes }}</p>
69
+ </div>
70
+ {% endfor %}
71
+ </div>
72
+
73
+
74
+ {% else %}
75
+ <p>No questions yet</p>
76
+ {% endif %} -->
77
+ <script src="{% static 'polls/index.js' %}"></script>
78
+ {% endblock %}
polls/templatetags/__init__.py ADDED
File without changes
polls/templatetags/index.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from django import template
2
+
3
+ register=template.Library()
4
+
5
+ @register.filter
6
+ def index(indexable,i):
7
+ return indexable[i]
polls/urls.py CHANGED
@@ -8,6 +8,13 @@ urlpatterns = [
8
  path("signup/",views.signup,name="signup"),
9
  path("login/",views.login,name="login"),
10
  path("details/<int:question_id>/",views.detail,name="detail"),
11
- path("vote/<int:question_id>/",views.vote,name="vote"),
12
  path("result/<int:question_id>/",views.result,name="result"),
 
 
 
 
 
 
 
13
  ]
 
8
  path("signup/",views.signup,name="signup"),
9
  path("login/",views.login,name="login"),
10
  path("details/<int:question_id>/",views.detail,name="detail"),
11
+ path("vote/",views.vote,name="vote"),
12
  path("result/<int:question_id>/",views.result,name="result"),
13
+
14
+ path("create/",views.create,name="create"),
15
+ path("your_polls/",views.your_polls,name="your_polls"),
16
+ path("votes/",views.your_votes,name="your_votes"),
17
+ path("settings/",views.settings,name="settings"),
18
+ path("logout/",views.logout,name="logout"),
19
+
20
  ]
polls/views.py CHANGED
@@ -4,7 +4,7 @@ from django.contrib.auth import login as auth_login,logout as auth_logout
4
  from django.contrib.auth import get_user_model
5
  from django.urls import reverse
6
  import json
7
- from .models import Question,Choice
8
  from .forms import UserSignupForm,UserLoginForm
9
 
10
 
@@ -13,7 +13,17 @@ User = get_user_model() # user model
13
  # Create your views here.
14
  def index(request):
15
  latest_questions_list = Question.objects.order_by("-pub_date")[:5]
16
- context={"latest_questions_list":latest_questions_list}
 
 
 
 
 
 
 
 
 
 
17
  return render(request,"polls/index.html",context)
18
 
19
  def detail(request,question_id):
@@ -24,29 +34,36 @@ def detail(request,question_id):
24
 
25
  return render(request,"polls/detail.html",{"question":question})
26
 
27
- def vote(request,question_id):
28
-
29
- question=get_object_or_404(Question,pk=question_id)
30
-
31
-
32
- try:
33
  json_data=json.loads(request.body)
34
  print(json_data)
35
- selected_choice = question.choice_set.get(pk=json_data["choice"])
36
- except(KeyError,Choice.DoesNotExist):
37
- # redirect back to details page with error message
38
- return JsonResponse({
39
-
40
- "error_message":"You didn't select a Choice."
41
- })
42
-
43
- else:
44
- selected_choice.votes += 1
45
- selected_choice.save()
46
- # return HttpResponseRedirect(reverse("polls:result",args=(question_id,)))
47
- return JsonResponse({
48
- "redirect":reverse("polls:result",args=(question_id,)),
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  })
51
 
52
 
@@ -117,4 +134,37 @@ def login(request):
117
  'data':data}
118
  # print(context)
119
 
120
- return render(request,"polls/login.html",context)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from django.contrib.auth import get_user_model
5
  from django.urls import reverse
6
  import json
7
+ from .models import Question,Choice,Vote
8
  from .forms import UserSignupForm,UserLoginForm
9
 
10
 
 
13
  # Create your views here.
14
  def index(request):
15
  latest_questions_list = Question.objects.order_by("-pub_date")[:5]
16
+
17
+
18
+ for q in latest_questions_list:
19
+ q.has_voted=q.has_user_voted(request.user)
20
+
21
+ # print(latest_questions_list[0].has_voted)
22
+
23
+ context={"latest_questions_list":latest_questions_list,
24
+
25
+ }
26
+
27
  return render(request,"polls/index.html",context)
28
 
29
  def detail(request,question_id):
 
34
 
35
  return render(request,"polls/detail.html",{"question":question})
36
 
37
+ def vote(request):
38
+ if request.method=='POST':
 
 
 
 
39
  json_data=json.loads(request.body)
40
  print(json_data)
41
+ choice=get_object_or_404(Choice,pk=json_data['choice_id'])
42
+ # check if already has voted on this question
43
+
44
+ old_vote_on_same_question=Vote.objects.filter(user=request.user,choice__question=choice.question)
45
+
46
+ if len(old_vote_on_same_question)>0:
47
+ return JsonResponse({
48
+ "message":"error",
49
+ 'error_message':"you have already voted !"
50
+ })
 
 
 
 
51
 
52
+
53
+ vote=Vote.objects.create(choice=choice,user=request.user)
54
+ vote.save()
55
+
56
+ # get percentage of each choice for showing result
57
+
58
+ vote_percent_dict={c.pk:c.vote_percent for c in choice.question.choice_set.all()}
59
+
60
+ # print(vote_percent_dict)
61
+
62
+
63
+
64
+ return JsonResponse({
65
+ "message":"success",
66
+ "vote_percent_dict" :vote_percent_dict,
67
  })
68
 
69
 
 
134
  'data':data}
135
  # print(context)
136
 
137
+ return render(request,"polls/login.html",context)
138
+
139
+
140
+ def create(request):
141
+ if request.method=="GET":
142
+ return render(request,'polls/create.html',{})
143
+
144
+ json_data=json.loads(request.body)
145
+ print(json_data)
146
+ question=Question.objects.create(author=request.user,
147
+ question_text=json_data['question_text'])
148
+ question.save()
149
+
150
+ for choice_text in json_data['choice_text_list']:
151
+ choice=Choice.objects.create(question=question,choice_text=choice_text)
152
+ choice.save()
153
+
154
+ return JsonResponse({
155
+
156
+ "redirect":reverse("polls:index")
157
+ })
158
+
159
+ def your_polls(request):
160
+ latest_questions_list = Question.objects.filter(author=request.user).order_by("-pub_date")[:5]
161
+ context={"latest_questions_list":latest_questions_list}
162
+ return render(request,'polls/your_polls.html',context)
163
+
164
+ def your_votes(request):
165
+ pass
166
+ def settings(request):
167
+ pass
168
+ def logout(request):
169
+ auth_logout(request)
170
+ return HttpResponseRedirect(reverse('polls:login'))