Skip to content

Commit 1abfcae

Browse files
authored
Merge branch 'IEEE-NITK:main' into blogs
2 parents 7619fef + f3f8cd1 commit 1abfcae

40 files changed

Lines changed: 2715 additions & 29 deletions

corpus/corpus/decorators.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
from accounts.models import ExecutiveMember
2-
from config.models import ModuleConfiguration
1+
from functools import wraps
2+
33
from django.contrib import messages
44
from django.shortcuts import redirect
55

6+
from accounts.models import ExecutiveMember
7+
from config.models import ModuleConfiguration
8+
69

710
def module_enabled(module_name):
811
def decorator(view_func):
@@ -77,4 +80,22 @@ def wrapper(request, *args, **kwargs):
7780

7881
return decorator
7982

83+
def ensure_view_current_envision():
84+
def decorator(view_func):
85+
@wraps(view_func)
86+
def wrapper(request, *args, **kwargs):
87+
config = ModuleConfiguration.objects.get(module_name="virtual_expo").module_config
88+
89+
try:
90+
ExecutiveMember.objects.get(user=request.user.id)
91+
exec_member = True
92+
except ExecutiveMember.DoesNotExist:
93+
exec_member = False
94+
95+
can_view_current_envision = exec_member or config.get(
96+
"view_current_envision")
97+
kwargs['can_view_current_envision '] = can_view_current_envision
98+
return view_func(request, *args, **kwargs)
99+
return wrapper
100+
return decorator
80101

corpus/corpus/settings.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"farewell.apps.FarewellConfig",
6868
"virtual_expo.apps.VirtualExpoConfig",
6969
"blog",
70+
"smp.apps.SmpConfig",
7071
]
7172

7273
MIDDLEWARE = [
@@ -271,31 +272,34 @@
271272
},
272273
],
273274
"toolbar": "DefaultToolbarConfig",
274-
"removeDialogTabs": ";".join([
275-
"image:advanced",
276-
"image:Link",
277-
"link:upload",
278-
"table:advanced",
279-
"tableProperties:advanced",
280-
]),
275+
"removeDialogTabs": ";".join(
276+
[
277+
"image:advanced",
278+
"image:Link",
279+
"link:upload",
280+
"table:advanced",
281+
"tableProperties:advanced",
282+
]
283+
),
281284
"linkShowTargetTab": False,
282285
"linkShowAdvancedTab": False,
283286
"height": "250px",
284287
"width": "auto",
285288
"forcePasteAsPlainText": True,
286289
"mathJaxClass": "mathjax-latex",
287290
"mathJaxLib": "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS_SVG",
288-
"extraPlugins": ",".join([
289-
"mathjax",
290-
"codesnippet",
291-
"image2",
292-
"uploadimage",
293-
"embed",
294-
"uploadimage",
295-
"tableresize",
296-
]),
291+
"extraPlugins": ",".join(
292+
[
293+
"mathjax",
294+
"codesnippet",
295+
"image2",
296+
"uploadimage",
297+
"embed",
298+
"uploadimage",
299+
"tableresize",
300+
]
301+
),
297302
"filebrowserUploadUrl": "/ckeditor/upload/?responseType=json",
298303
"filebrowserBrowseUrl": "/ckeditor/browse/",
299304
}
300305
}
301-

corpus/corpus/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@
4848
path("blog/", include("blog.urls")),
4949
path("athenaeum/", include("athenaeum.urls")),
5050
path("newsletter/", include("newsletter.urls")),
51+
path("smp/", include("smp.urls")),
5152
]
5253

5354
if settings.DEBUG:
54-
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
55+
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

corpus/smp/__init__.py

Whitespace-only changes.

corpus/smp/admin.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.contrib import admin
2+
from smp.models import Program
3+
from smp.models import ProgramMember
4+
from smp.models import Submission
5+
from smp.models import Upload
6+
7+
# Register your models here.
8+
admin.site.register(Program)
9+
admin.site.register(ProgramMember)
10+
admin.site.register(Upload)
11+
admin.site.register(Submission)

corpus/smp/admin_urls.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from django.urls import path
2+
from smp import admin_views as views
3+
4+
urlpatterns = [
5+
path("dashboard/", views.dashboard, name="smp_admin_dashboard"),
6+
path(
7+
"program/<int:program_id>/add_members/",
8+
views.add_members,
9+
name="smp_admin_add_members",
10+
),
11+
path("<int:program_id>/manage/", views.manage, name="smp_admin_manage"),
12+
]

corpus/smp/admin_views.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
from accounts.models import ExecutiveMember
2+
from accounts.models import User
3+
from config.models import SIG
4+
from django.contrib import messages
5+
from django.contrib.auth.decorators import login_required
6+
from django.db import IntegrityError
7+
from django.db.models import Count
8+
from django.shortcuts import get_object_or_404
9+
from django.shortcuts import redirect
10+
from django.shortcuts import render
11+
from smp.forms import AdminProgramMemberForm
12+
from smp.forms import ProgramFilterForm
13+
from smp.forms import ProgramForm
14+
from smp.models import Program
15+
from smp.models import ProgramMember
16+
17+
from corpus.decorators import ensure_group_membership
18+
19+
20+
@login_required
21+
@ensure_group_membership(group_names=["smp_coordinator"])
22+
def dashboard(request):
23+
programs = Program.objects.all().order_by("-pk")
24+
25+
if request.method == "POST":
26+
program_id = int(request.POST.get("program_id"))
27+
action = request.POST.get("action")
28+
program = get_object_or_404(Program, pk=program_id)
29+
30+
if action == "hide_program":
31+
if not program.hide_program:
32+
program.hide_program = True
33+
program.save()
34+
messages.success(request, "Program has been hidden.")
35+
elif action == "show_program":
36+
if program.hide_program:
37+
program.hide_program = False
38+
program.save()
39+
messages.success(request, "Program is now visible.")
40+
elif action == "delete_program":
41+
program.delete()
42+
messages.success(request, "Program has been deleted.")
43+
44+
return redirect("smp_admin_dashboard")
45+
46+
form = ProgramFilterForm(request.GET)
47+
if form.is_valid():
48+
try:
49+
sig = int(form.cleaned_data.get("sig"))
50+
if sig == -1:
51+
programs = programs.annotate(
52+
sig_count=Count(
53+
"programmember__member__executivemember__sig", distinct=True
54+
)
55+
).filter(sig_count__gte=2)
56+
elif sig != 0:
57+
sig_obj = SIG.objects.filter(pk=sig).first()
58+
if sig_obj:
59+
programs = programs.annotate(
60+
sig_count=Count(
61+
"programmember__member__executivemember__sig", distinct=True
62+
)
63+
).filter(
64+
sig_count=1, programmember__member__executivemember__sig=sig_obj
65+
)
66+
except (ValueError, TypeError):
67+
pass
68+
69+
programs = programs.distinct()
70+
args = {"programs": programs, "form": form}
71+
72+
return render(request, "smp/admin/dashboard.html", args)
73+
74+
75+
@login_required
76+
@ensure_group_membership(group_names=["smp_coordinator"])
77+
def add_members(request, program_id):
78+
program = Program.objects.get(pk=program_id)
79+
mentors = program.mentors()
80+
mentees = program.mentees()
81+
82+
form = AdminProgramMemberForm(initial={"program": program})
83+
84+
if request.method == "POST":
85+
if "add" in request.POST:
86+
form = AdminProgramMemberForm(request.POST)
87+
form.instance.program = program
88+
if form.is_valid():
89+
member = form.cleaned_data["member"]
90+
member_type = form.cleaned_data["member_type"]
91+
92+
if member_type == "Mentor":
93+
if not ExecutiveMember.objects.filter(user=member).exists():
94+
messages.error(
95+
request, "Only Executive Members can be added as mentors."
96+
)
97+
return redirect("smp_admin_add_members", program_id=program.id)
98+
99+
try:
100+
form.save()
101+
except IntegrityError:
102+
messages.error(request, "Member already added to the program.")
103+
return redirect("smp_admin_add_members", program_id=program.id)
104+
105+
messages.success(request, "Member added to program.")
106+
return redirect("smp_admin_add_members", program_id=program.id)
107+
elif "edit" in request.POST:
108+
program_id = int(request.POST.get("program_id"))
109+
member_id = int(request.POST.get("member_id"))
110+
program = Program.objects.get(pk=program_id)
111+
member = User.objects.get(pk=member_id)
112+
113+
try:
114+
program_member = ProgramMember.objects.get(
115+
program=program, member=member
116+
)
117+
program_member.delete()
118+
except ProgramMember.DoesNotExist:
119+
messages.error(request, "Member does not exist for this program.")
120+
return redirect("smp_admin_add_members", program_id=program.id)
121+
122+
messages.success(request, "Members edited in program.")
123+
return redirect("smp_admin_add_members", program_id=program.id)
124+
125+
args = {
126+
"form": form,
127+
"mentors": mentors,
128+
"mentees": mentees,
129+
"program": program,
130+
}
131+
132+
return render(request, "smp/admin/add_members.html", args)
133+
134+
135+
@login_required
136+
@ensure_group_membership(group_names=["smp_coordinator"])
137+
def manage(request, program_id):
138+
program = Program.objects.get(pk=program_id)
139+
form = ProgramForm(instance=program)
140+
141+
if request.method == "POST":
142+
form = ProgramForm(request.POST, request.FILES, instance=program)
143+
if form.is_valid():
144+
form.save()
145+
messages.success(request, "Program updated successfully!")
146+
return redirect("smp_admin_dashboard")
147+
148+
is_smp_coordinator = request.user.groups.filter(name="smp_coordinator").exists()
149+
150+
args = {
151+
"program": program,
152+
"form": form,
153+
"admin": is_smp_coordinator,
154+
}
155+
156+
return render(request, "smp/mentors/edit_program.html", args)

corpus/smp/apps.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class SmpConfig(AppConfig):
5+
default_auto_field = "django.db.models.BigAutoField"
6+
name = "smp"

corpus/smp/forms.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from accounts.models import User
2+
from config.models import SIG
3+
from django import forms
4+
from smp.models import Program
5+
from smp.models import ProgramMember
6+
from smp.models import Submission
7+
from smp.models import Upload
8+
9+
from corpus.forms import CorpusForm
10+
from corpus.forms import CorpusModelForm
11+
12+
13+
class ProgramFilterForm(CorpusForm):
14+
sig = forms.ChoiceField(choices=[])
15+
year = forms.ChoiceField(choices=[], required=False)
16+
17+
def __init__(self, *args, **kwargs):
18+
super(ProgramFilterForm, self).__init__(*args, **kwargs)
19+
20+
sig_choices = [(0, "All SIGs"), (-1, "Inter-SIG")] + list(
21+
SIG.objects.values_list("id", "name")
22+
)
23+
year_choices = [(0, "All Years")] + [
24+
(x, x)
25+
for x in list(Program.objects.values_list("year", flat=True).distinct())
26+
]
27+
28+
self.fields["sig"].choices = sig_choices
29+
self.fields["year"].choices = year_choices
30+
31+
32+
class ProgramForm(CorpusModelForm):
33+
class Meta:
34+
model = Program
35+
fields = [
36+
"title",
37+
"abstract",
38+
"thumbnail",
39+
"year",
40+
"description",
41+
"hide_program",
42+
]
43+
44+
45+
class ProgramMemberForm(CorpusModelForm):
46+
class Meta:
47+
model = ProgramMember
48+
fields = ["member"]
49+
50+
def __init__(self, *args, **kwargs):
51+
super().__init__(*args, **kwargs)
52+
executive_users = User.objects.filter(executivemember__isnull=False).distinct()
53+
self.fields["member"].queryset = executive_users
54+
55+
56+
class UploadForm(CorpusModelForm):
57+
class Meta:
58+
model = Upload
59+
fields = ["title", "upload_type", "content"]
60+
61+
62+
class SubmissionForm(CorpusModelForm):
63+
class Meta:
64+
model = Submission
65+
fields = ["title", "link"]
66+
67+
68+
class AdminProgramMemberForm(CorpusModelForm):
69+
class Meta:
70+
model = ProgramMember
71+
fields = ["member", "member_type"]

corpus/smp/mentor_urls.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from django.urls import path
2+
from smp import mentor_views as views
3+
4+
urlpatterns = [
5+
path("dashboard/", views.dashboard, name="smp_mentors_dashboard"),
6+
path("program/new/", views.new_program, name="smp_mentors_new_program"),
7+
path(
8+
"program/<int:program_id>/edit/",
9+
views.edit_program,
10+
name="smp_mentors_edit_program",
11+
),
12+
path(
13+
"program/<int:program_id>/add_members/",
14+
views.add_members,
15+
name="smp_mentors_add_members",
16+
),
17+
path(
18+
"program/<int:program_id>/upload/",
19+
views.uploads,
20+
name="smp_mentors_add_upload",
21+
),
22+
]

0 commit comments

Comments
 (0)