thejagstudio commited on
Commit
d5374bf
·
1 Parent(s): e744e38

Add notification app with initial models, views, and admin configuration; remove unused image files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. api/__pycache__/__init__.cpython-313.pyc +0 -0
  2. api/__pycache__/admin.cpython-313.pyc +0 -0
  3. api/__pycache__/apps.cpython-313.pyc +0 -0
  4. api/__pycache__/models.cpython-313.pyc +0 -0
  5. api/__pycache__/urls.cpython-313.pyc +0 -0
  6. api/__pycache__/utils.cpython-313.pyc +0 -0
  7. api/__pycache__/views.cpython-313.pyc +0 -0
  8. api/admin.py +66 -18
  9. api/migrations/0016_pushsubscription.py +26 -0
  10. api/migrations/0017_optionpoll_poll.py +34 -0
  11. api/migrations/0018_rename_participant_poll_participants.py +18 -0
  12. api/migrations/0019_bhajancategory_icon.py +18 -0
  13. api/migrations/0020_alter_bhajan_audio_url.py +18 -0
  14. api/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
  15. api/migrations/__pycache__/0002_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc +0 -0
  16. api/migrations/__pycache__/0003_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc +0 -0
  17. api/migrations/__pycache__/0004_alter_bhajancategory_svg.cpython-313.pyc +0 -0
  18. api/migrations/__pycache__/0005_remove_bhajan_lyrics_en_url_and_more.cpython-313.pyc +0 -0
  19. api/migrations/__pycache__/0006_bhajan_isaudio_bhajan_iseng_bhajan_isger_and_more.cpython-313.pyc +0 -0
  20. api/migrations/__pycache__/0007_remove_bhajancategory_svg.cpython-313.pyc +0 -0
  21. api/migrations/__pycache__/0008_bhajan_bhajanid.cpython-313.pyc +0 -0
  22. api/migrations/__pycache__/0009_event_color_alter_event_created_by_and_more.cpython-313.pyc +0 -0
  23. api/migrations/__pycache__/0010_event_time.cpython-313.pyc +0 -0
  24. api/migrations/__pycache__/0011_delete_message.cpython-313.pyc +0 -0
  25. api/migrations/__pycache__/0012_notification_title.cpython-313.pyc +0 -0
  26. api/migrations/__pycache__/0013_bhagat_profile_image_alter_bhagat_user_type_and_more.cpython-313.pyc +0 -0
  27. api/migrations/__pycache__/0014_rename_address_bhagat_streetname_bhagat_city_and_more.cpython-313.pyc +0 -0
  28. api/migrations/__pycache__/0015_alter_bhagat_phone.cpython-313.pyc +0 -0
  29. api/migrations/__pycache__/0016_pushsubscription.cpython-313.pyc +0 -0
  30. api/migrations/__pycache__/0017_optionpoll_poll.cpython-313.pyc +0 -0
  31. api/migrations/__pycache__/0018_rename_participant_poll_participants.cpython-313.pyc +0 -0
  32. api/migrations/__pycache__/0019_bhajancategory_icon.cpython-313.pyc +0 -0
  33. api/migrations/__pycache__/0020_alter_bhajan_audio_url.cpython-313.pyc +0 -0
  34. api/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  35. api/models.py +56 -11
  36. api/urls.py +21 -15
  37. api/views.py +447 -184
  38. downloads/1.jpg +0 -3
  39. downloads/10.png +0 -0
  40. downloads/100.png +0 -3
  41. downloads/101.png +0 -3
  42. downloads/102.png +0 -3
  43. downloads/103.png +0 -3
  44. downloads/104.png +0 -3
  45. downloads/105.png +0 -3
  46. downloads/106.png +0 -3
  47. downloads/107.png +0 -3
  48. downloads/108.png +0 -3
  49. downloads/109.jpg +0 -0
  50. downloads/11.png +0 -3
api/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (139 Bytes). View file
 
api/__pycache__/admin.cpython-313.pyc ADDED
Binary file (3.6 kB). View file
 
api/__pycache__/apps.cpython-313.pyc ADDED
Binary file (497 Bytes). View file
 
api/__pycache__/models.cpython-313.pyc ADDED
Binary file (11.2 kB). View file
 
api/__pycache__/urls.cpython-313.pyc ADDED
Binary file (2.02 kB). View file
 
api/__pycache__/utils.cpython-313.pyc ADDED
Binary file (2.96 kB). View file
 
api/__pycache__/views.cpython-313.pyc ADDED
Binary file (25.6 kB). View file
 
api/admin.py CHANGED
@@ -1,36 +1,81 @@
1
  from django.contrib import admin
2
- from .models import Bhagat, Event, Attendance, Notification, Region, BhajanCategory, Bhajan
 
 
 
 
 
 
 
 
 
 
 
3
  from import_export.admin import ImportExportModelAdmin
4
 
 
5
  # Register your models here.
6
  class BhagatAdmin(ImportExportModelAdmin):
7
- list_display = ('__str__', 'email', 'region', 'user_type', 'assigned_to')
8
- list_filter = ('region', 'user_type')
9
- search_fields = ('__str__', 'email', 'region', 'user_type', 'assigned_to')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  class RegionAdmin(ImportExportModelAdmin):
12
- list_display = ('name',)
 
13
 
14
  class BhajanCategoryAdmin(ImportExportModelAdmin):
15
- list_display = ('name', 'link')
16
- search_fields = ('name',)
17
-
 
18
  class BhajanAdmin(ImportExportModelAdmin):
19
- list_display = ('title', 'title_guj', 'category', 'lyricsBtn')
20
- search_fields = ('title', 'title_guj', 'category__name')
21
- list_filter = ('category',)
22
  # 'musicPreivew',
23
 
 
24
  class EventAdmin(ImportExportModelAdmin):
25
- list_display = ('title', 'date', 'region', 'is_approved', 'color')
26
- list_filter = ('region', 'is_approved', 'color')
27
- search_fields = ('title', 'date', 'region', 'is_approved', 'color')
28
- list_editable = ('is_approved', 'color')
 
29
 
30
  class NotificationAdmin(ImportExportModelAdmin):
31
- list_display = ('sender', 'title','timestamp', 'notification_type')
32
- list_filter = ('notification_type',)
33
- search_fields = ('sender__first_name', 'title', 'notification_type')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  admin.site.register(Bhagat, BhagatAdmin)
36
  admin.site.register(Region, RegionAdmin)
@@ -38,3 +83,6 @@ admin.site.register(BhajanCategory, BhajanCategoryAdmin)
38
  admin.site.register(Bhajan, BhajanAdmin)
39
  admin.site.register(Event, EventAdmin)
40
  admin.site.register(Notification, NotificationAdmin)
 
 
 
 
1
  from django.contrib import admin
2
+ from .models import (
3
+ Bhagat,
4
+ Event,
5
+ Attendance,
6
+ Notification,
7
+ Region,
8
+ BhajanCategory,
9
+ Bhajan,
10
+ PushSubscription,
11
+ OptionPoll,
12
+ Poll,
13
+ )
14
  from import_export.admin import ImportExportModelAdmin
15
 
16
+
17
  # Register your models here.
18
  class BhagatAdmin(ImportExportModelAdmin):
19
+ list_display = (
20
+ "get_full_name",
21
+ "profileImage",
22
+ "email",
23
+ "region",
24
+ "user_type",
25
+ "assigned_to",
26
+ )
27
+ list_filter = ("region", "user_type")
28
+ search_fields = (
29
+ "get_full_name",
30
+ "email",
31
+ "region",
32
+ "user_type",
33
+ "assigned_to",
34
+ )
35
+
36
 
37
  class RegionAdmin(ImportExportModelAdmin):
38
+ list_display = ("name",)
39
+
40
 
41
  class BhajanCategoryAdmin(ImportExportModelAdmin):
42
+ list_display = ("name", "icon_image", "link")
43
+ search_fields = ("name",)
44
+
45
+
46
  class BhajanAdmin(ImportExportModelAdmin):
47
+ list_display = ("title", "title_guj", "category", "lyricsBtn")
48
+ search_fields = ("title", "title_guj", "category__name")
49
+ list_filter = ("category",)
50
  # 'musicPreivew',
51
 
52
+
53
  class EventAdmin(ImportExportModelAdmin):
54
+ list_display = ("title", "date", "region", "is_approved", "color")
55
+ list_filter = ("region", "is_approved", "color")
56
+ search_fields = ("title", "date", "region", "is_approved", "color")
57
+ list_editable = ("is_approved", "color")
58
+
59
 
60
  class NotificationAdmin(ImportExportModelAdmin):
61
+ list_display = ("sender", "title", "timestamp", "notification_type")
62
+ list_filter = ("notification_type",)
63
+ search_fields = ("sender__first_name", "title", "notification_type")
64
+
65
+
66
+ class PushSubscriptionAdmin(ImportExportModelAdmin):
67
+ list_display = ("user", "endpoint")
68
+
69
+
70
+ class OptionPollAdmin(ImportExportModelAdmin):
71
+ list_display = ("optionText",)
72
+ search_fields = ("optionText",)
73
+
74
+
75
+ class PollAdmin(ImportExportModelAdmin):
76
+ list_display = ("question", "created_by", "created_at")
77
+ search_fields = ("question", "created_by")
78
+
79
 
80
  admin.site.register(Bhagat, BhagatAdmin)
81
  admin.site.register(Region, RegionAdmin)
 
83
  admin.site.register(Bhajan, BhajanAdmin)
84
  admin.site.register(Event, EventAdmin)
85
  admin.site.register(Notification, NotificationAdmin)
86
+ admin.site.register(PushSubscription, PushSubscriptionAdmin)
87
+ admin.site.register(OptionPoll, OptionPollAdmin)
88
+ admin.site.register(Poll, PollAdmin)
api/migrations/0016_pushsubscription.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.1.6 on 2025-02-13 21:48
2
+
3
+ import django.db.models.deletion
4
+ from django.conf import settings
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('api', '0015_alter_bhagat_phone'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='PushSubscription',
17
+ fields=[
18
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+ ('endpoint', models.URLField(max_length=500)),
20
+ ('p256dh', models.CharField(max_length=200)),
21
+ ('auth', models.CharField(max_length=100)),
22
+ ('created_at', models.DateTimeField(auto_now_add=True)),
23
+ ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
24
+ ],
25
+ ),
26
+ ]
api/migrations/0017_optionpoll_poll.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.1.6 on 2025-02-14 17:09
2
+
3
+ import django.db.models.deletion
4
+ from django.conf import settings
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('api', '0016_pushsubscription'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='OptionPoll',
17
+ fields=[
18
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+ ('optionText', models.TextField()),
20
+ ('voters', models.ManyToManyField(blank=True, related_name='options_voters', to=settings.AUTH_USER_MODEL)),
21
+ ],
22
+ ),
23
+ migrations.CreateModel(
24
+ name='Poll',
25
+ fields=[
26
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
27
+ ('question', models.TextField()),
28
+ ('created_at', models.DateTimeField(auto_now_add=True)),
29
+ ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='polls_creator', to=settings.AUTH_USER_MODEL)),
30
+ ('options', models.ManyToManyField(blank=True, related_name='polls_options', to='api.optionpoll')),
31
+ ('participant', models.ManyToManyField(blank=True, related_name='polls_participant', to=settings.AUTH_USER_MODEL)),
32
+ ],
33
+ ),
34
+ ]
api/migrations/0018_rename_participant_poll_participants.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.1.6 on 2025-02-14 17:33
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('api', '0017_optionpoll_poll'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name='poll',
15
+ old_name='participant',
16
+ new_name='participants',
17
+ ),
18
+ ]
api/migrations/0019_bhajancategory_icon.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.1.6 on 2025-02-15 18:50
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('api', '0018_rename_participant_poll_participants'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name='bhajancategory',
15
+ name='icon',
16
+ field=models.URLField(blank=True),
17
+ ),
18
+ ]
api/migrations/0020_alter_bhajan_audio_url.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.1.6 on 2025-02-15 22:46
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('api', '0019_bhajancategory_icon'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name='bhajan',
15
+ name='audio_url',
16
+ field=models.CharField(blank=True, max_length=500),
17
+ ),
18
+ ]
api/migrations/__pycache__/0001_initial.cpython-313.pyc ADDED
Binary file (9.14 kB). View file
 
api/migrations/__pycache__/0002_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc ADDED
Binary file (1.54 kB). View file
 
api/migrations/__pycache__/0003_alter_bhagat_address_alter_bhagat_birthday_and_more.cpython-313.pyc ADDED
Binary file (1.31 kB). View file
 
api/migrations/__pycache__/0004_alter_bhajancategory_svg.cpython-313.pyc ADDED
Binary file (803 Bytes). View file
 
api/migrations/__pycache__/0005_remove_bhajan_lyrics_en_url_and_more.cpython-313.pyc ADDED
Binary file (1.47 kB). View file
 
api/migrations/__pycache__/0006_bhajan_isaudio_bhajan_iseng_bhajan_isger_and_more.cpython-313.pyc ADDED
Binary file (1.13 kB). View file
 
api/migrations/__pycache__/0007_remove_bhajancategory_svg.cpython-313.pyc ADDED
Binary file (709 Bytes). View file
 
api/migrations/__pycache__/0008_bhajan_bhajanid.cpython-313.pyc ADDED
Binary file (784 Bytes). View file
 
api/migrations/__pycache__/0009_event_color_alter_event_created_by_and_more.cpython-313.pyc ADDED
Binary file (1.71 kB). View file
 
api/migrations/__pycache__/0010_event_time.cpython-313.pyc ADDED
Binary file (779 Bytes). View file
 
api/migrations/__pycache__/0011_delete_message.cpython-313.pyc ADDED
Binary file (630 Bytes). View file
 
api/migrations/__pycache__/0012_notification_title.cpython-313.pyc ADDED
Binary file (789 Bytes). View file
 
api/migrations/__pycache__/0013_bhagat_profile_image_alter_bhagat_user_type_and_more.cpython-313.pyc ADDED
Binary file (1.38 kB). View file
 
api/migrations/__pycache__/0014_rename_address_bhagat_streetname_bhagat_city_and_more.cpython-313.pyc ADDED
Binary file (1.3 kB). View file
 
api/migrations/__pycache__/0015_alter_bhagat_phone.cpython-313.pyc ADDED
Binary file (813 Bytes). View file
 
api/migrations/__pycache__/0016_pushsubscription.cpython-313.pyc ADDED
Binary file (1.54 kB). View file
 
api/migrations/__pycache__/0017_optionpoll_poll.cpython-313.pyc ADDED
Binary file (1.99 kB). View file
 
api/migrations/__pycache__/0018_rename_participant_poll_participants.cpython-313.pyc ADDED
Binary file (719 Bytes). View file
 
api/migrations/__pycache__/0019_bhajancategory_icon.cpython-313.pyc ADDED
Binary file (781 Bytes). View file
 
api/migrations/__pycache__/0020_alter_bhajan_audio_url.cpython-313.pyc ADDED
Binary file (790 Bytes). View file
 
api/migrations/__pycache__/__init__.cpython-313.pyc ADDED
Binary file (150 Bytes). View file
 
api/models.py CHANGED
@@ -28,14 +28,21 @@ class Bhagat(AbstractUser):
28
  pincode = models.CharField(max_length=10, null=True)
29
  assigned_to = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_users')
30
  profile_image = models.URLField(blank=True)
31
-
32
  def __str__(self):
33
  return self.first_name + ' ' + self.last_name
34
 
35
  def save(self, *args, **kwargs):
36
- self.set_password(self.password)
 
37
  super().save(*args, **kwargs)
38
 
 
 
 
 
 
 
39
 
40
  class Region(models.Model):
41
  name = models.CharField(max_length=100)
@@ -75,31 +82,36 @@ class Notification(models.Model):
75
  class BhajanCategory(models.Model):
76
  name = models.CharField(max_length=100)
77
  link = models.CharField(max_length=100)
78
-
 
79
  def __str__(self):
80
  return self.name
81
 
 
 
 
 
82
  class Bhajan(models.Model):
83
- bhajanId = models.IntegerField(blank=True,default=0)
84
- title = models.CharField(max_length=500,blank=True)
85
- title_guj = models.CharField(max_length=500,blank=True)
86
  category = models.ForeignKey(BhajanCategory, on_delete=models.CASCADE)
87
  lyrics = models.CharField(max_length=50, blank=True)
88
- audio_url = models.URLField(blank=True)
89
  isEng = models.BooleanField(default=False)
90
  isHnd = models.BooleanField(default=False)
91
  isGer = models.BooleanField(default=False)
92
  isAudio = models.BooleanField(default=False)
93
-
94
  def __str__(self):
95
  return self.title
96
-
97
  def musicPreivew(self):
98
  if self.isAudio:
99
  return mark_safe('<audio controls><source src="https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/%s" type="audio/mpeg"></audio>' % self.audio_url)
100
  else:
101
  return 'No Audio Available'
102
-
103
  def lyricsBtn(self):
104
  # i have four languages in my bhajan so add them all as buttons and show them on click
105
  languages = [["","GUJ"]]
@@ -113,4 +125,37 @@ class Bhajan(models.Model):
113
  for lang in languages:
114
  html += '<li style="padding-bottom:12px"><a href="https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/'+lang[0] + self.lyrics+'" target="_blank" class="import_link">'+(lang[1])+'</a></li>'
115
  html += '</ul>'
116
- return mark_safe(html)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  pincode = models.CharField(max_length=10, null=True)
29
  assigned_to = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_users')
30
  profile_image = models.URLField(blank=True)
31
+
32
  def __str__(self):
33
  return self.first_name + ' ' + self.last_name
34
 
35
  def save(self, *args, **kwargs):
36
+ if not self.password.startswith("pbkdf2_sha256"):
37
+ self.set_password(self.password)
38
  super().save(*args, **kwargs)
39
 
40
+ def profileImage(self):
41
+ return mark_safe('<img src="%s" width="50" height="50" />' % self.profile_image)
42
+
43
+ def get_full_name(self):
44
+ return super().get_full_name()
45
+
46
 
47
  class Region(models.Model):
48
  name = models.CharField(max_length=100)
 
82
  class BhajanCategory(models.Model):
83
  name = models.CharField(max_length=100)
84
  link = models.CharField(max_length=100)
85
+ icon = models.URLField(blank=True)
86
+
87
  def __str__(self):
88
  return self.name
89
 
90
+ def icon_image(self):
91
+ return mark_safe('<img src="%s" width="50" height="50" />' % self.icon)
92
+
93
+
94
  class Bhajan(models.Model):
95
+ bhajanId = models.IntegerField(blank=True, default=0)
96
+ title = models.CharField(max_length=500, blank=True)
97
+ title_guj = models.CharField(max_length=500, blank=True)
98
  category = models.ForeignKey(BhajanCategory, on_delete=models.CASCADE)
99
  lyrics = models.CharField(max_length=50, blank=True)
100
+ audio_url = models.CharField(max_length=500, blank=True)
101
  isEng = models.BooleanField(default=False)
102
  isHnd = models.BooleanField(default=False)
103
  isGer = models.BooleanField(default=False)
104
  isAudio = models.BooleanField(default=False)
105
+
106
  def __str__(self):
107
  return self.title
108
+
109
  def musicPreivew(self):
110
  if self.isAudio:
111
  return mark_safe('<audio controls><source src="https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/%s" type="audio/mpeg"></audio>' % self.audio_url)
112
  else:
113
  return 'No Audio Available'
114
+
115
  def lyricsBtn(self):
116
  # i have four languages in my bhajan so add them all as buttons and show them on click
117
  languages = [["","GUJ"]]
 
125
  for lang in languages:
126
  html += '<li style="padding-bottom:12px"><a href="https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/'+lang[0] + self.lyrics+'" target="_blank" class="import_link">'+(lang[1])+'</a></li>'
127
  html += '</ul>'
128
+ return mark_safe(html)
129
+
130
+
131
+ class PushSubscription(models.Model):
132
+ user = models.ForeignKey(Bhagat, on_delete=models.CASCADE, null=True)
133
+ endpoint = models.URLField(max_length=500)
134
+ p256dh = models.CharField(max_length=200)
135
+ auth = models.CharField(max_length=100)
136
+ created_at = models.DateTimeField(auto_now_add=True)
137
+
138
+
139
+ class OptionPoll(models.Model):
140
+ optionText = models.TextField()
141
+ voters = models.ManyToManyField(Bhagat, related_name="options_voters", blank=True)
142
+
143
+ def __str__(self):
144
+ return self.optionText
145
+
146
+
147
+ class Poll(models.Model):
148
+ question = models.TextField()
149
+ options = models.ManyToManyField(
150
+ OptionPoll, related_name="polls_options", blank=True
151
+ )
152
+ participants = models.ManyToManyField(
153
+ Bhagat, related_name="polls_participant", blank=True
154
+ )
155
+ created_by = models.ForeignKey(
156
+ Bhagat, on_delete=models.CASCADE, related_name="polls_creator"
157
+ )
158
+ created_at = models.DateTimeField(auto_now_add=True)
159
+
160
+ def __str__(self):
161
+ return self.question
api/urls.py CHANGED
@@ -3,19 +3,25 @@ from . import views
3
  from rest_framework_simplejwt.views import TokenRefreshView
4
 
5
  urlpatterns = [
6
- path('login/', views.login, name='login'),
7
- path('logout/', views.logout, name='logout'),
8
- path('get-user-profile/', views.get_user_profile, name='get_user_profile'),
9
- path('profile-updater/', views.profile_updater, name='profile_updater'),
10
- path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
11
-
12
- path('dataEntry/', views.dataEntry, name='dataEntry'),
13
- path('send-notification/', views.send_notification, name='send_notification'),
14
-
15
- path('bhajan-category-list/', views.bhajanCategoryList, name='bhajanCategoryList'),
16
- path('bhajan-detail/<int:id>', views.bhajanDetail, name='bhajanDetail'),
17
- path('event-list/', views.eventList, name='eventList'),
18
- path('notification/', views.notification, name='notification'),
19
-
20
- path('bhakto-list/', views.bhaktoList, name='bhaktoList'),
 
 
 
 
 
 
21
  ]
 
3
  from rest_framework_simplejwt.views import TokenRefreshView
4
 
5
  urlpatterns = [
6
+ path("login/", views.login, name="login"),
7
+ path("logout/", views.logout, name="logout"),
8
+ path("get-user-profile/", views.get_user_profile, name="get_user_profile"),
9
+ path("profile-updater/", views.profile_updater, name="profile_updater"),
10
+ path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
11
+ path("dataEntry/", views.dataEntry, name="dataEntry"),
12
+ path("send-notification/", views.send_notification, name="send_notification"),
13
+ path("bhajan-list/<str:catLink>", views.bhajanList, name="bhajanList"),
14
+ path("bhajan-category-list/", views.bhajanCategoryList, name="bhajanCategoryList"),
15
+ path(
16
+ "bhajan-detail/<str:catLink>/<int:id>", views.bhajanDetail, name="bhajanDetail"
17
+ ),
18
+ path("event-list/", views.eventList, name="eventList"),
19
+ path("bhakto-list/", views.bhaktoList, name="bhaktoList"),
20
+ path("notification/", views.notification, name="notification"),
21
+ path("push-subscription/", views.save_push_subscription, name="push_subscription"),
22
+ path("send-otp/", views.send_otp, name="send_otp"),
23
+ path("verify-otp/", views.verify_otp, name="verify_otp"),
24
+ path("change-password/", views.change_password, name="change_password"),
25
+ path("polls/", views.polls, name="polls"),
26
+ path("poll-voters/<int:id>", views.voterList, name="voterList"),
27
  ]
api/views.py CHANGED
@@ -5,8 +5,20 @@ from django.http import JsonResponse, HttpResponse
5
  from django.views.decorators.http import require_POST
6
  from django.utils import timezone
7
  import json
8
- from .models import Bhagat, Event, Attendance, Notification, Region, BhajanCategory, Bhajan
 
 
 
 
 
 
 
 
 
 
 
9
  from django.conf import settings
 
10
  import requests
11
 
12
  from rest_framework.decorators import api_view, permission_classes
@@ -14,6 +26,7 @@ from rest_framework.permissions import AllowAny
14
  from rest_framework.response import Response
15
  from .utils import jwt_required
16
  from rest_framework_simplejwt.tokens import RefreshToken
 
17
 
18
 
19
  def gCaptchaVerifer(token):
@@ -24,15 +37,15 @@ def gCaptchaVerifer(token):
24
 
25
 
26
  def is_superadmin(user):
27
- return user.user_type == 'superadmin'
28
 
29
 
30
  def is_regionadmin(user):
31
- return user.user_type == 'regionadmin'
32
 
33
 
34
  def is_monitor(user):
35
- return user.user_type == 'monitor'
36
 
37
 
38
  def dataEntry(request):
@@ -57,52 +70,78 @@ def dataEntry(request):
57
 
58
  def bhajanCategoryList(request):
59
  categories = BhajanCategory.objects.all()
60
- bhajans = Bhajan.objects.all()
61
- bhajanArr = []
62
- for bhajan in bhajans:
63
- bhajanArr.append({
64
- "id": bhajan.bhajanId,
65
- "title": bhajan.title,
66
- "title_guj": bhajan.title_guj,
67
- "category": bhajan.category.name,
68
- "lyrics": bhajan.lyrics,
69
- "audio_url": bhajan.audio_url,
70
- "isEng": bhajan.isEng,
71
- "isHnd": bhajan.isHnd,
72
- "isGer": bhajan.isGer,
73
- "isAudio": bhajan.isAudio
74
- })
75
  categoryArr = []
76
  for category in categories:
77
- categoryArr.append({
78
- "name": category.name,
79
- "link": category.link
80
- })
81
- lyricsBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/"
83
- return JsonResponse({"categories": categoryArr, "bhajans": bhajanArr, "lyricsBase": lyricsBase, "audioBase": audioBase})
 
 
 
 
 
 
 
84
 
85
 
86
- def bhajanDetail(request, id):
87
- bhajan = Bhajan.objects.get(bhajanId=id)
88
  if bhajan is None:
89
  return JsonResponse({"error": "Bhajan not found"})
90
  else:
91
- return JsonResponse({
92
- "id": bhajan.bhajanId,
93
- "title": bhajan.title,
94
- "title_guj": bhajan.title_guj,
95
- "category": bhajan.category.name,
96
- "lyrics": bhajan.lyrics,
97
- "audio_url": bhajan.audio_url,
98
- "isEng": bhajan.isEng,
99
- "isHnd": bhajan.isHnd,
100
- "isGer": bhajan.isGer,
101
- "isAudio": bhajan.isAudio,
102
- "lyricsBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/",
103
- "audioBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/"
104
- })
105
- return HttpResponse("Bhajan Detail Page")
 
106
 
107
 
108
  def eventList(request):
@@ -110,34 +149,45 @@ def eventList(request):
110
  eventArr = []
111
  for event in events:
112
  # convert date to Sept 26,2024 | 8:30 - 9:30
113
- dateFormatted = event.date.strftime("%b %d, %Y") + " | " + event.date.strftime("%I:%M %p") + " - " + event.time.strftime("%I:%M %p")
114
- eventArr.append({
115
- "title": event.title,
116
- "description": event.description,
117
- "date": dateFormatted,
118
- "day": int(event.date.strftime("%d")),
119
- "month": int(event.date.strftime("%m")),
120
- "year": int(event.date.strftime("%Y")),
121
- "created_by": event.created_by.__str__(),
122
- "region": event.region.name,
123
- "is_approved": event.is_approved,
124
- "color": event.color
125
- })
 
 
 
 
 
 
 
 
126
  return JsonResponse({"events": eventArr})
127
 
 
128
  @jwt_required()
129
  def notification(request):
130
  notifications = Notification.objects.all()
131
  notificationArr = []
132
  for notification in notifications:
133
- notificationArr.append({
134
- "sender": notification.sender.__str__(),
135
- "category": notification.sender.user_type,
136
- "title": notification.title,
137
- "content": notification.content,
138
- "timestamp": notification.timestamp.strftime("%b %d, %Y | %I:%M %p"),
139
- "notification_type": notification.notification_type
140
- })
 
 
141
  return JsonResponse({"notifications": notificationArr})
142
 
143
 
@@ -145,48 +195,55 @@ def notification(request):
145
  @csrf_exempt
146
  @jwt_required()
147
  def send_notification(request):
148
- if request.method == 'POST':
149
- content = request.POST.get('content')
150
- recipient_type = request.POST.get('recipient_type')
151
- if recipient_type == 'all':
152
- recipients = Bhagat.objects.all()
153
- elif recipient_type == 'monitors':
154
- recipients = Bhagat.objects.filter(user_type='monitor')
155
- elif recipient_type == 'regionadmins':
156
- recipients = Bhagat.objects.filter(user_type='regionadmin')
157
 
158
- notification = Notification.objects.create(sender=request.user, content=content, notification_type='custom')
159
- notification.recipients.set(recipients)
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
- return redirect('notifications')
 
162
 
163
 
164
  def birthday_notifications():
165
  today = timezone.now().date()
166
- birthday_users = Bhagat.objects.filter(birthday__month=today.month, birthday__day=today.day)
 
 
167
  for user in birthday_users:
168
  notification = Notification.objects.create(
169
- sender=Bhagat.objects.get(user_type='superadmin'),
170
  content=f"Happy Birthday to {user.get_full_name()}!",
171
- notification_type='birthday'
172
  )
173
  notification.recipients.set(Bhagat.objects.all())
174
 
175
 
176
  @csrf_exempt
177
  def login(request):
178
- if request.method == 'POST':
179
- username = request.POST.get('username')
180
- password = request.POST.get('password')
181
- captcha_response = request.POST.get('captcha_response')
182
 
183
  # Verify captcha
184
  result = gCaptchaVerifer(captcha_response)
185
  if not result.get("success"):
186
- return JsonResponse({
187
- "error": "Invalid Captcha",
188
- "status": "error"
189
- })
190
 
191
  # Authenticate user
192
  user = Bhagat.objects.filter(username=username).first()
@@ -194,145 +251,131 @@ def login(request):
194
  # Generate tokens
195
  refresh = RefreshToken.for_user(user)
196
 
197
- return JsonResponse({
198
- "status": "success",
199
- "tokens": {
200
- "access_token": str(refresh.access_token),
201
- "refresh_token": str(refresh)
202
- },
203
- "user": {
204
- "id": user.id,
205
- "username": user.username,
206
- "first_name": user.first_name,
207
- "last_name": user.last_name,
208
- "email": user.email,
209
- "phone": user.phone,
210
- "region": user.region.name,
211
- "user_type": user.user_type,
212
- "profile_image": user.profile_image
 
 
213
  }
214
- })
215
-
216
- return JsonResponse({
217
- "error": "Invalid credentials",
218
- "status": "error"
219
- })
220
 
221
- return JsonResponse({
222
- "error": "Invalid Method",
223
- "status": "error"
224
- })
225
 
 
226
 
227
 
228
  @csrf_exempt
229
  @jwt_required()
230
  def logout(request):
231
- if request.method == 'POST':
232
- refresh_token = request.POST.get('refresh_token')
233
  if not refresh_token:
234
- return JsonResponse({
235
- 'error': 'Refresh token is required',
236
- 'status': 'error'
237
- })
238
  else:
239
  try:
240
  refresh = RefreshToken(refresh_token)
241
  refresh.blacklist()
242
- return JsonResponse({
243
- 'status': 'success',
244
- 'message': 'Successfully logged out'
245
- })
246
- except TokenError:
247
- return JsonResponse({
248
- "error": "Invalid token",
249
- "status": "error"
250
- })
251
- return JsonResponse({
252
- "status": "error",
253
- "error": "Invalid Method"
254
- })
255
 
256
 
257
  @jwt_required()
258
  def get_user_profile(request):
259
  try:
260
  user = request.user
261
- return JsonResponse({
262
- "status": "success",
263
- "user": {
264
- "id": user.id,
265
- "username": user.username,
266
- "first_name": user.first_name,
267
- "last_name": user.last_name,
268
- "email": user.email,
269
- "phone": user.phone,
270
- "region": user.region.name,
271
- "user_type": user.user_type,
272
- "profile_image": user.profile_image
 
 
273
  }
274
- })
275
  except Exception as e:
276
- return JsonResponse({
277
- "status": "error",
278
- "error": str(e)
279
- })
280
 
281
  @csrf_exempt
282
  @jwt_required()
283
  def profile_updater(request):
284
- if request.method == 'POST':
285
  try:
286
  user = request.user
287
- first_name = request.POST.get('first_name')
288
  if first_name:
289
  user.first_name = first_name
290
- last_name = request.POST.get('last_name')
291
  if last_name:
292
  user.last_name = last_name
293
- email = request.POST.get('email')
294
  if email:
295
  user.email = email
296
- phone = request.POST.get('phone')
297
  if phone:
298
  user.phone = phone
299
- region_name = request.POST.get('region')
300
  if region_name:
301
  user.region = Region.objects.get(name=region_name)
302
- birth_date = request.POST.get('birth_date')
303
  if birth_date:
304
  user.birthday = birth_date
305
- street_name = request.POST.get('street_name')
306
  if street_name:
307
  user.streetName = street_name
308
- pincode = request.POST.get('pincode')
309
  if pincode:
310
  user.pincode = pincode
311
- city = request.POST.get('city')
312
  if city:
313
  user.city = city
314
- state = request.POST.get('state')
315
  if state:
316
  user.state = state
317
- country = request.POST.get('country')
318
  if country:
319
  user.country = country
320
- profile_image = request.POST.get('profile_image')
321
  if profile_image:
322
  user.profile_image = profile_image
323
  user.save()
324
- return JsonResponse({
325
- "status": "success",
326
- "message": "Profile updated successfully"
327
- })
328
  except Exception as e:
329
- return JsonResponse({
330
- "status": "error",
331
- "error": str(e)
332
- })
333
  else:
334
  user = request.user
335
- data= {
 
336
  "first_name": user.first_name,
337
  "last_name": user.last_name,
338
  "email": user.email,
@@ -344,12 +387,15 @@ def profile_updater(request):
344
  "city": user.city,
345
  "state": user.state,
346
  "country": user.country,
347
- "profile_image": user.profile_image
348
  }
349
- return JsonResponse({
350
- "status": "success",
351
- "user": data
352
- })
 
 
 
353
 
354
 
355
  @jwt_required()
@@ -358,12 +404,229 @@ def bhaktoList(request):
358
  bhaktos = Bhagat.objects.filter(assigned_to=current_user).all()
359
  bhaktoArr = []
360
  for bhakto in bhaktos:
361
- bhaktoArr.append({
362
- "id": bhakto.id,
363
- "first_name": bhakto.first_name,
364
- "last_name": bhakto.last_name,
365
- "region": bhakto.region.name,
366
- "user_type": bhakto.user_type,
367
- "profile_image": bhakto.profile_image
368
- })
369
- return JsonResponse({"bhaktos": bhaktoArr})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  from django.views.decorators.http import require_POST
6
  from django.utils import timezone
7
  import json
8
+ from .models import (
9
+ Bhagat,
10
+ Event,
11
+ Attendance,
12
+ PushSubscription,
13
+ Notification,
14
+ Region,
15
+ BhajanCategory,
16
+ Bhajan,
17
+ OptionPoll,
18
+ Poll,
19
+ )
20
  from django.conf import settings
21
+ from django.core import serializers
22
  import requests
23
 
24
  from rest_framework.decorators import api_view, permission_classes
 
26
  from rest_framework.response import Response
27
  from .utils import jwt_required
28
  from rest_framework_simplejwt.tokens import RefreshToken
29
+ from pywebpush import webpush, WebPushException
30
 
31
 
32
  def gCaptchaVerifer(token):
 
37
 
38
 
39
  def is_superadmin(user):
40
+ return user.user_type == "superadmin"
41
 
42
 
43
  def is_regionadmin(user):
44
+ return user.user_type == "regionadmin"
45
 
46
 
47
  def is_monitor(user):
48
+ return user.user_type == "monitor"
49
 
50
 
51
  def dataEntry(request):
 
70
 
71
  def bhajanCategoryList(request):
72
  categories = BhajanCategory.objects.all()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  categoryArr = []
74
  for category in categories:
75
+ categoryArr.append(
76
+ {"name": category.name, "link": category.link, "icon": category.icon}
77
+ )
78
+ lyricsBase = (
79
+ "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/"
80
+ )
81
+ audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/"
82
+ return JsonResponse(
83
+ {"categories": categoryArr, "lyricsBase": lyricsBase, "audioBase": audioBase}
84
+ )
85
+
86
+
87
+ def bhajanList(request, catLink):
88
+ if catLink == "all-kirtan":
89
+ bhajans = Bhajan.objects.all()
90
+ category = "All Kirtan"
91
+ else:
92
+ bhajans = Bhajan.objects.filter(category__link=catLink)
93
+ category = BhajanCategory.objects.get(link=catLink).name
94
+ bhajanArr = []
95
+ for bhajan in bhajans:
96
+ bhajanArr.append(
97
+ {
98
+ "id": bhajan.bhajanId,
99
+ "title": bhajan.title,
100
+ "title_guj": bhajan.title_guj,
101
+ "lyrics": bhajan.lyrics,
102
+ "audio_url": bhajan.audio_url,
103
+ "isEng": bhajan.isEng,
104
+ "isHnd": bhajan.isHnd,
105
+ "isGer": bhajan.isGer,
106
+ "isAudio": bhajan.isAudio,
107
+ }
108
+ )
109
+
110
+ lyricsBase = (
111
+ "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/"
112
+ )
113
  audioBase = "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/"
114
+ return JsonResponse(
115
+ {
116
+ "bhajans": bhajanArr,
117
+ "lyricsBase": lyricsBase,
118
+ "audioBase": audioBase,
119
+ "category": category,
120
+ }
121
+ )
122
 
123
 
124
+ def bhajanDetail(request, catLink, id):
125
+ bhajan = Bhajan.objects.get(bhajanId=id, category__link=catLink)
126
  if bhajan is None:
127
  return JsonResponse({"error": "Bhajan not found"})
128
  else:
129
+ return JsonResponse(
130
+ {
131
+ "id": bhajan.bhajanId,
132
+ "title": bhajan.title,
133
+ "title_guj": bhajan.title_guj,
134
+ "category": bhajan.category.name,
135
+ "lyrics": bhajan.lyrics,
136
+ "audio_url": bhajan.audio_url,
137
+ "isEng": bhajan.isEng,
138
+ "isHnd": bhajan.isHnd,
139
+ "isGer": bhajan.isGer,
140
+ "isAudio": bhajan.isAudio,
141
+ "lyricsBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/raw/main/HTML Files/",
142
+ "audioBase": "https://huggingface.co/spaces/thejagstudio/MusicStore/resolve/main/Bhajan Audio/",
143
+ }
144
+ )
145
 
146
 
147
  def eventList(request):
 
149
  eventArr = []
150
  for event in events:
151
  # convert date to Sept 26,2024 | 8:30 - 9:30
152
+ dateFormatted = (
153
+ event.date.strftime("%b %d, %Y")
154
+ + " | "
155
+ + event.date.strftime("%I:%M %p")
156
+ + " - "
157
+ + event.time.strftime("%I:%M %p")
158
+ )
159
+ eventArr.append(
160
+ {
161
+ "title": event.title,
162
+ "description": event.description,
163
+ "date": dateFormatted,
164
+ "day": int(event.date.strftime("%d")),
165
+ "month": int(event.date.strftime("%m")),
166
+ "year": int(event.date.strftime("%Y")),
167
+ "created_by": event.created_by.__str__(),
168
+ "region": event.region.name,
169
+ "is_approved": event.is_approved,
170
+ "color": event.color,
171
+ }
172
+ )
173
  return JsonResponse({"events": eventArr})
174
 
175
+
176
  @jwt_required()
177
  def notification(request):
178
  notifications = Notification.objects.all()
179
  notificationArr = []
180
  for notification in notifications:
181
+ notificationArr.append(
182
+ {
183
+ "sender": notification.sender.__str__(),
184
+ "category": notification.sender.user_type,
185
+ "title": notification.title,
186
+ "content": notification.content,
187
+ "timestamp": notification.timestamp.strftime("%b %d, %Y | %I:%M %p"),
188
+ "notification_type": notification.notification_type,
189
+ }
190
+ )
191
  return JsonResponse({"notifications": notificationArr})
192
 
193
 
 
195
  @csrf_exempt
196
  @jwt_required()
197
  def send_notification(request):
198
+ if request.method == "POST":
199
+ content = request.POST.get("content")
200
+ recipient_type = request.POST.get("recipient_type")
 
 
 
 
 
 
201
 
202
+ notification = Notification.objects.create(
203
+ sender=request.user, content=content, notification_type="custom"
204
+ )
205
+
206
+ # Send web push notifications
207
+ subscriptions = PushSubscription.objects.all()
208
+ for subscription in subscriptions:
209
+ send_push_notification(
210
+ subscription,
211
+ {
212
+ "title": "New Notification",
213
+ "content": content,
214
+ "url": "/notifications",
215
+ },
216
+ )
217
 
218
+ return JsonResponse({"status": "success"})
219
+ return JsonResponse({"status": "error"})
220
 
221
 
222
  def birthday_notifications():
223
  today = timezone.now().date()
224
+ birthday_users = Bhagat.objects.filter(
225
+ birthday__month=today.month, birthday__day=today.day
226
+ )
227
  for user in birthday_users:
228
  notification = Notification.objects.create(
229
+ sender=Bhagat.objects.get(user_type="superadmin"),
230
  content=f"Happy Birthday to {user.get_full_name()}!",
231
+ notification_type="birthday",
232
  )
233
  notification.recipients.set(Bhagat.objects.all())
234
 
235
 
236
  @csrf_exempt
237
  def login(request):
238
+ if request.method == "POST":
239
+ username = request.POST.get("username")
240
+ password = request.POST.get("password")
241
+ captcha_response = request.POST.get("captcha_response")
242
 
243
  # Verify captcha
244
  result = gCaptchaVerifer(captcha_response)
245
  if not result.get("success"):
246
+ return JsonResponse({"error": "Invalid Captcha", "status": "error"})
 
 
 
247
 
248
  # Authenticate user
249
  user = Bhagat.objects.filter(username=username).first()
 
251
  # Generate tokens
252
  refresh = RefreshToken.for_user(user)
253
 
254
+ return JsonResponse(
255
+ {
256
+ "status": "success",
257
+ "tokens": {
258
+ "access_token": str(refresh.access_token),
259
+ "refresh_token": str(refresh),
260
+ },
261
+ "user": {
262
+ "id": user.id,
263
+ "username": user.username,
264
+ "first_name": user.first_name,
265
+ "last_name": user.last_name,
266
+ "email": user.email,
267
+ "phone": user.phone,
268
+ "region": user.region.name,
269
+ "user_type": user.user_type,
270
+ "profile_image": user.profile_image,
271
+ },
272
  }
273
+ )
 
 
 
 
 
274
 
275
+ return JsonResponse({"error": "Invalid credentials", "status": "error"})
 
 
 
276
 
277
+ return JsonResponse({"error": "Invalid Method", "status": "error"})
278
 
279
 
280
  @csrf_exempt
281
  @jwt_required()
282
  def logout(request):
283
+ if request.method == "POST":
284
+ refresh_token = request.POST.get("refresh_token")
285
  if not refresh_token:
286
+ return JsonResponse(
287
+ {"error": "Refresh token is required", "status": "error"}
288
+ )
 
289
  else:
290
  try:
291
  refresh = RefreshToken(refresh_token)
292
  refresh.blacklist()
293
+ return JsonResponse(
294
+ {"status": "success", "message": "Successfully logged out"}
295
+ )
296
+ except Exception as e:
297
+ return JsonResponse(
298
+ {"error": "Invalid token | " + str(e), "status": "error"}
299
+ )
300
+ return JsonResponse({"status": "error", "error": "Invalid Method"})
 
 
 
 
 
301
 
302
 
303
  @jwt_required()
304
  def get_user_profile(request):
305
  try:
306
  user = request.user
307
+ return JsonResponse(
308
+ {
309
+ "status": "success",
310
+ "user": {
311
+ "id": user.id,
312
+ "username": user.username,
313
+ "first_name": user.first_name,
314
+ "last_name": user.last_name,
315
+ "email": user.email,
316
+ "phone": user.phone,
317
+ "region": user.region.name,
318
+ "user_type": user.user_type,
319
+ "profile_image": user.profile_image,
320
+ },
321
  }
322
+ )
323
  except Exception as e:
324
+ return JsonResponse({"status": "error", "error": str(e)})
325
+
 
 
326
 
327
  @csrf_exempt
328
  @jwt_required()
329
  def profile_updater(request):
330
+ if request.method == "POST":
331
  try:
332
  user = request.user
333
+ first_name = request.POST.get("first_name")
334
  if first_name:
335
  user.first_name = first_name
336
+ last_name = request.POST.get("last_name")
337
  if last_name:
338
  user.last_name = last_name
339
+ email = request.POST.get("email")
340
  if email:
341
  user.email = email
342
+ phone = request.POST.get("phone")
343
  if phone:
344
  user.phone = phone
345
+ region_name = request.POST.get("region")
346
  if region_name:
347
  user.region = Region.objects.get(name=region_name)
348
+ birth_date = request.POST.get("birth_date")
349
  if birth_date:
350
  user.birthday = birth_date
351
+ street_name = request.POST.get("street_name")
352
  if street_name:
353
  user.streetName = street_name
354
+ pincode = request.POST.get("pincode")
355
  if pincode:
356
  user.pincode = pincode
357
+ city = request.POST.get("city")
358
  if city:
359
  user.city = city
360
+ state = request.POST.get("state")
361
  if state:
362
  user.state = state
363
+ country = request.POST.get("country")
364
  if country:
365
  user.country = country
366
+ profile_image = request.POST.get("profile_image")
367
  if profile_image:
368
  user.profile_image = profile_image
369
  user.save()
370
+ return JsonResponse(
371
+ {"status": "success", "message": "Profile updated successfully"}
372
+ )
 
373
  except Exception as e:
374
+ return JsonResponse({"status": "error", "error": str(e)})
 
 
 
375
  else:
376
  user = request.user
377
+ regions = Region.objects.all()
378
+ data = {
379
  "first_name": user.first_name,
380
  "last_name": user.last_name,
381
  "email": user.email,
 
387
  "city": user.city,
388
  "state": user.state,
389
  "country": user.country,
390
+ "profile_image": user.profile_image,
391
  }
392
+ return JsonResponse(
393
+ {
394
+ "status": "success",
395
+ "regions": [region.name for region in regions],
396
+ "user": data,
397
+ }
398
+ )
399
 
400
 
401
  @jwt_required()
 
404
  bhaktos = Bhagat.objects.filter(assigned_to=current_user).all()
405
  bhaktoArr = []
406
  for bhakto in bhaktos:
407
+ bhaktoArr.append(
408
+ {
409
+ "id": bhakto.id,
410
+ "first_name": bhakto.first_name,
411
+ "last_name": bhakto.last_name,
412
+ "region": bhakto.region.name,
413
+ "user_type": bhakto.user_type,
414
+ "profile_image": bhakto.profile_image,
415
+ }
416
+ )
417
+ return JsonResponse({"bhaktos": bhaktoArr})
418
+
419
+
420
+ @api_view(["POST"])
421
+ @permission_classes([AllowAny])
422
+ def send_otp(request):
423
+ try:
424
+ data = json.loads(request.body)
425
+ phone = data.get("phone")
426
+
427
+ if not phone:
428
+ return JsonResponse(
429
+ {"status": "error", "error": "Phone number is required"}
430
+ )
431
+
432
+ # Check if user exists
433
+ user = Bhagat.objects.filter(phone=phone).first()
434
+ if not user:
435
+ return JsonResponse(
436
+ {"status": "error", "error": "No account found with this phone number"}
437
+ )
438
+
439
+ # Generate dummy OTP (in production, use proper OTP generation and SMS service)
440
+ otp = "123456" # Dummy OTP for testing
441
+ print(f"Generated OTP for {phone}: {otp}") # This simulates sending OTP
442
+
443
+ # In production, store OTP with timestamp in database or cache
444
+ # For now, we'll just return success
445
+ return JsonResponse({"status": "success", "message": "OTP sent successfully"})
446
+
447
+ except Exception as e:
448
+ return JsonResponse({"status": "error", "error": str(e)})
449
+
450
+
451
+ @api_view(["POST"])
452
+ @permission_classes([AllowAny])
453
+ def verify_otp(request):
454
+ try:
455
+ data = json.loads(request.body)
456
+ phone = data.get("phone")
457
+ otp = data.get("otp")
458
+
459
+ if not phone or not otp:
460
+ return JsonResponse(
461
+ {"status": "error", "error": "Phone number and OTP are required"}
462
+ )
463
+
464
+ # For demo purposes, accept any 6-digit OTP
465
+ if otp == "123456": # Dummy verification
466
+ return JsonResponse(
467
+ {"status": "success", "message": "OTP verified successfully"}
468
+ )
469
+
470
+ return JsonResponse({"status": "error", "error": "Invalid OTP"})
471
+
472
+ except Exception as e:
473
+ return JsonResponse({"status": "error", "error": str(e)})
474
+
475
+
476
+ @api_view(["POST"])
477
+ @jwt_required()
478
+ @csrf_exempt
479
+ @permission_classes([AllowAny])
480
+ def change_password(request):
481
+ try:
482
+ data = json.loads(request.body)
483
+ new_password = data.get("new_password")
484
+
485
+ if not new_password:
486
+ return JsonResponse(
487
+ {
488
+ "status": "error",
489
+ "error": "Phone number and new password are required",
490
+ }
491
+ )
492
+
493
+ # Update user's password
494
+ user = request.user
495
+ if not user:
496
+ return JsonResponse({"status": "error", "error": "User not found"})
497
+
498
+ user.password = new_password
499
+ user.save()
500
+
501
+ return JsonResponse(
502
+ {"status": "success", "message": "Password changed successfully"}
503
+ )
504
+
505
+ except Exception as e:
506
+ return JsonResponse({"status": "error", "error": str(e)})
507
+
508
+
509
+ @jwt_required()
510
+ @api_view(["POST"])
511
+ @csrf_exempt
512
+ @permission_classes([AllowAny])
513
+ def save_push_subscription(request):
514
+ try:
515
+ subscription_data = json.loads(request.body)
516
+ user = request.user
517
+ pushUser = PushSubscription.objects.filter(user=user).first()
518
+ if pushUser:
519
+ pushUser.endpoint = subscription_data["endpoint"]
520
+ pushUser.p256dh = subscription_data["keys"]["p256dh"]
521
+ pushUser.auth = subscription_data["keys"]["auth"]
522
+ pushUser.save()
523
+ else:
524
+ PushSubscription.objects.create(
525
+ user=user,
526
+ endpoint=subscription_data["endpoint"],
527
+ p256dh=subscription_data["keys"]["p256dh"],
528
+ auth=subscription_data["keys"]["auth"],
529
+ )
530
+ return JsonResponse({"status": "success"})
531
+ except Exception as e:
532
+ return JsonResponse({"status": "error", "message": str(e)})
533
+
534
+
535
+ def send_push_notification(subscription, message):
536
+ try:
537
+ webpush(
538
+ subscription_info={
539
+ "endpoint": subscription.endpoint,
540
+ "keys": {"p256dh": subscription.p256dh, "auth": subscription.auth},
541
+ },
542
+ data=json.dumps(message),
543
+ vapid_private_key=settings.WEBPUSH_SETTINGS["VAPID_PRIVATE_KEY"],
544
+ vapid_claims={
545
+ "sub": f"mailto:{settings.WEBPUSH_SETTINGS['VAPID_ADMIN_EMAIL']}"
546
+ },
547
+ )
548
+ except WebPushException as e:
549
+ print(f"Web push failed: {e}")
550
+
551
+
552
+ @api_view(["GET", "POST"])
553
+ @jwt_required()
554
+ @csrf_exempt
555
+ @permission_classes([AllowAny])
556
+ def polls(request):
557
+ if request.method == "GET":
558
+ user = request.user
559
+ polls = Poll.objects.filter(participants=user)
560
+ pollArr = []
561
+ for poll in polls:
562
+ tempPoll = {}
563
+ tempPoll["id"] = poll.id
564
+ tempPoll["question"] = poll.question
565
+ tempPoll["options"] = []
566
+ for option in poll.options.all():
567
+ tempOption = {}
568
+ tempOption["id"] = option.id
569
+ tempOption["optionText"] = option.optionText
570
+ tempOption["count"] = option.voters.all().count()
571
+ tempOption["precentage"] = (
572
+ option.voters.all().count() / poll.participants.all().count()
573
+ ) * 100
574
+ tempOption["voters"] = []
575
+ for voter in option.voters.all()[:2]:
576
+ tempOption["voters"].append(
577
+ {
578
+ "id": voter.profile_image,
579
+ "first_name": voter.first_name,
580
+ "last_name": voter.last_name,
581
+ "profile_image": voter.profile_image,
582
+ }
583
+ )
584
+ tempPoll["options"].append(tempOption)
585
+ tempPoll["created_by"] = {
586
+ "id": poll.created_by.profile_image,
587
+ "first_name": poll.created_by.first_name,
588
+ "last_name": poll.created_by.last_name,
589
+ "profile_image": poll.created_by.profile_image,
590
+ }
591
+ tempPoll["created_at"] = poll.created_at
592
+ pollArr.append(tempPoll)
593
+ return JsonResponse({"data": pollArr})
594
+ if request.method == "POST":
595
+ data = json.loads(request.body)
596
+ user = request.user
597
+ poll = Poll.objects.get(id=id)
598
+ option = OptionPoll.objects.get(id=data.get("option"))
599
+ option.votes.add(user)
600
+ return JsonResponse(
601
+ {"status": "success", "message": "Vote submitted successfully"}
602
+ )
603
+
604
+
605
+ @api_view(["GET"])
606
+ @jwt_required()
607
+ @permission_classes([AllowAny])
608
+ def voterList(request, id):
609
+ poll = Poll.objects.filter(participants=user).get(id=id)
610
+ if not poll:
611
+ return JsonResponse(
612
+ {"error": "Poll may not exist or you may not have access to it"}
613
+ )
614
+ else:
615
+ user = request.user
616
+ options = poll.options.all()
617
+ optionsList = []
618
+ for option in options:
619
+ tempOption = {}
620
+ tempOption["id"] = option.id
621
+ tempOption["optionText"] = option.optionText
622
+ tempOption["voters"] = []
623
+ for voter in option.voters.all():
624
+ tempOption["voters"].append(
625
+ {
626
+ "id": voter.profile_image,
627
+ "first_name": voter.first_name,
628
+ "last_name": voter.last_name,
629
+ "profile_image": voter.profile_image,
630
+ }
631
+ )
632
+ return JsonResponse({"data": optionsList})
downloads/1.jpg DELETED

Git LFS Details

  • SHA256: 69bdb2fd55e4c88d905dfb9f63ef7eb8134656b4da7644ef2d5928cbd18f202d
  • Pointer size: 132 Bytes
  • Size of remote file: 2.41 MB
downloads/10.png DELETED
Binary file (835 kB)
 
downloads/100.png DELETED

Git LFS Details

  • SHA256: 6dda40896ee605bcd42a981f5c00ef64b603aa4c5c51953634f2d403d222ba1e
  • Pointer size: 132 Bytes
  • Size of remote file: 3.05 MB
downloads/101.png DELETED

Git LFS Details

  • SHA256: 6543731df314943327c1c94bf1dacc0a440902d694aba759d1453721e3b4d842
  • Pointer size: 132 Bytes
  • Size of remote file: 1.58 MB
downloads/102.png DELETED

Git LFS Details

  • SHA256: 119e7c81a0a754d57cab878af98aed096af735c1bbd09b1b7c829d5b9250ffea
  • Pointer size: 132 Bytes
  • Size of remote file: 1.71 MB
downloads/103.png DELETED

Git LFS Details

  • SHA256: e0f0148cb61fdc0c7da26af9e562135aa33b05bcb3a91431af24336962085953
  • Pointer size: 132 Bytes
  • Size of remote file: 2.01 MB
downloads/104.png DELETED

Git LFS Details

  • SHA256: 8961becfc68a44c83376286770475c64a35fe98f4698e81abe29bdbc84e891c3
  • Pointer size: 132 Bytes
  • Size of remote file: 2.01 MB
downloads/105.png DELETED

Git LFS Details

  • SHA256: 41c05b54b83cfc087fba7690f3b928a2e37f8df400c42e63d8663af06cfee209
  • Pointer size: 132 Bytes
  • Size of remote file: 1.4 MB
downloads/106.png DELETED

Git LFS Details

  • SHA256: 82ca9d736f44f3c8e427385a534213dea82d28adf7a70edbc8ce5ea25631a225
  • Pointer size: 132 Bytes
  • Size of remote file: 1.93 MB
downloads/107.png DELETED

Git LFS Details

  • SHA256: 4c275fb498192252b829928b718d7fdb58fdaa0ba03a601dddc171cbbed7d7f3
  • Pointer size: 132 Bytes
  • Size of remote file: 2.08 MB
downloads/108.png DELETED

Git LFS Details

  • SHA256: cef9b982c3d20b82c0e71c9bd3be5195421d8a5816b8f4032026e3ce0bb4700c
  • Pointer size: 132 Bytes
  • Size of remote file: 2.03 MB
downloads/109.jpg DELETED
Binary file (500 kB)
 
downloads/11.png DELETED

Git LFS Details

  • SHA256: 3331a1427f8656575af1b98bb804b8366bb01d45e83589e066d8a0eeb1eff544
  • Pointer size: 132 Bytes
  • Size of remote file: 1.32 MB