summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--workshop_app/forms.py25
-rw-r--r--workshop_app/models.py2
-rw-r--r--workshop_app/templates/workshop_app/add_workshop_type.html50
-rw-r--r--workshop_app/templates/workshop_app/base.html12
-rw-r--r--workshop_app/templates/workshop_app/edit_workshop_type.html110
-rw-r--r--workshop_app/templates/workshop_app/workshop_type_details.html33
-rw-r--r--workshop_app/templates/workshop_app/workshop_type_list.html60
-rw-r--r--workshop_app/urls.py8
-rw-r--r--workshop_app/views.py64
9 files changed, 291 insertions, 73 deletions
diff --git a/workshop_app/forms.py b/workshop_app/forms.py
index 95b0ce1..46049f0 100644
--- a/workshop_app/forms.py
+++ b/workshop_app/forms.py
@@ -3,7 +3,8 @@ from string import punctuation, digits
from django import forms
from django.utils import timezone
-from .models import (Profile, Workshop, department_choices, title, source, states, Comment)
+from .models import (Profile, Workshop, Comment, department_choices, title, source, states, WorkshopType,
+ AttachmentFile)
try:
from string import letters
@@ -192,3 +193,25 @@ class CommentsForm(forms.ModelForm):
'class': 'form-check-input',
})
}
+
+
+class WorkshopTypeForm(forms.ModelForm):
+ def __init__(self, *args, **kwargs):
+ super(WorkshopTypeForm, self).__init__(*args, **kwargs)
+ for field in self.visible_fields():
+ field.field.widget.attrs['class'] = 'form-control'
+ field.field.widget.attrs['placeholder'] = field.label
+ field.field.widget.attrs['rows'] = 6
+
+ class Meta:
+ model = WorkshopType
+ exclude = []
+
+
+class AttachmentFileForm(forms.ModelForm):
+ def __init__(self, *args, **kwargs):
+ super(AttachmentFileForm, self).__init__(*args, **kwargs)
+
+ class Meta:
+ model = AttachmentFile
+ exclude = ['workshop_type']
diff --git a/workshop_app/models.py b/workshop_app/models.py
index 37f3a31..d690a7e 100644
--- a/workshop_app/models.py
+++ b/workshop_app/models.py
@@ -145,7 +145,7 @@ class WorkshopType(models.Model):
class AttachmentFile(models.Model):
- attachments = models.FileField(upload_to=attachments, blank=True,
+ attachments = models.FileField(upload_to=attachments, blank=False,
help_text='Please upload workshop documents one by one, \
ie.workshop schedule, instructions etc. \
Please Note: Name of Schedule file should be similar to \
diff --git a/workshop_app/templates/workshop_app/add_workshop_type.html b/workshop_app/templates/workshop_app/add_workshop_type.html
new file mode 100644
index 0000000..ed28b03
--- /dev/null
+++ b/workshop_app/templates/workshop_app/add_workshop_type.html
@@ -0,0 +1,50 @@
+{% extends 'workshop_app/base.html' %}
+
+{% block title %}
+ Add new Workshop type
+{% endblock %}
+
+{% block content %}
+ <div class="container">
+ <h2 class="text-center m-2">New Workshop Type</h2>
+ <br>
+ <form method="post">
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Workshop Name :</div>
+ <div class="col text-left">
+ <div class="row"><div class="col">{{ form.name }}</div></div>
+ <div class="row m-1 text-danger"><div class="col">{{ form.name.errors }}</div></div>
+ </div>
+
+ </div>
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Duration :</div>
+ <div class="col text-left">
+ <div class="row"><div class="col">{{ form.duration }}</div></div>
+ <div class="row m-1 text-muted"><div class="col">{{ form.duration.help_text }}</div></div>
+ <div class="row m-1 text-danger"><div class="col">{{ form.duration.errors }}</div></div>
+ </div>
+ </div>
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Description :</div>
+ <div class="col text-left">
+ <div class="row"><div class="col">{{ form.description }}</div></div>
+ <div class="row m-1 text-danger"><div class="col">{{ form.description.errors }}</div></div>
+ </div>
+ </div>
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Terms and Conditions :</div>
+ <div class="col text-left">
+ <div class="row"><div class="col">{{ form.terms_and_conditions }}</div></div>
+ <div class="row m-1 text-danger"><div class="col">{{ form.terms_and_conditions.errors }}</div></div>
+ </div>
+ </div>
+
+ <div class="row my-3">
+ <div class="col-12">
+ <button type="submit" class="btn btn-md btn-primary float-right m-3">Create</button>
+ </div>
+ </div>
+ </form>
+ </div>
+{% endblock %} \ No newline at end of file
diff --git a/workshop_app/templates/workshop_app/base.html b/workshop_app/templates/workshop_app/base.html
index 88ee1a1..398c38b 100644
--- a/workshop_app/templates/workshop_app/base.html
+++ b/workshop_app/templates/workshop_app/base.html
@@ -46,17 +46,17 @@
<a class="nav-link" href="{% url 'workshop_status_coordinator' %}">Workshop Status</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/propose_workshop/">Propose Workshop</a>
+ <a class="nav-link" href="{% url 'propose_workshop' %}">Propose Workshop</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/workshop_types/">Workshop Types</a>
+ <a class="nav-link" href="{% url 'workshop_type_list' %}">Workshop Types</a>
</li>
{% elif request.user.profile.position == 'instructor' %}
<li class="nav-item">
<a class="nav-link" href="{% url 'workshop_status_instructor' %}">Workshop Status</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="/workshop_types/">Workshop Types</a>
+ <a class="nav-link" href="{% url 'workshop_type_list' %}">Workshop Types</a>
</li>
{% endif %}
</ul>
@@ -92,9 +92,9 @@
{% endblock %}
<div class="container-fluid" style="margin-bottom: 44px">
-{% block content %}
- <h1>Base Template Content. Please override me</h1>
-{% endblock %}
+ {% block content %}
+ <h1>Base Template Content. Please override me</h1>
+ {% endblock %}
</div>
</body>
diff --git a/workshop_app/templates/workshop_app/edit_workshop_type.html b/workshop_app/templates/workshop_app/edit_workshop_type.html
new file mode 100644
index 0000000..b756f39
--- /dev/null
+++ b/workshop_app/templates/workshop_app/edit_workshop_type.html
@@ -0,0 +1,110 @@
+{% extends 'workshop_app/base.html' %}
+
+{% block title %}
+ Add new Workshop type
+{% endblock %}
+
+{% block extra-dependencies %}
+{% endblock %}
+
+{% block extra-custom-scripts %}
+
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.formset/1.2.2/jquery.formset.js"></script>
+{% endblock %}
+
+{% block content %}
+ <div class="container">
+ <h2 class="text-center m-2">View / Edit Workshop Type</h2>
+ <br>
+ <form method="post" enctype="multipart/form-data">
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Workshop Name :</div>
+ <div class="col text-left">
+ <div class="row">
+ <div class="col">{{ form.name }}</div>
+ </div>
+ <div class="row m-1 text-danger">
+ <div class="col">{{ form.name.errors }}</div>
+ </div>
+ </div>
+
+ </div>
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Duration :</div>
+ <div class="col text-left">
+ <div class="row">
+ <div class="col">{{ form.duration }}</div>
+ </div>
+ <div class="row m-1 text-muted">
+ <div class="col">{{ form.duration.help_text }}</div>
+ </div>
+ <div class="row m-1 text-danger">
+ <div class="col">{{ form.duration.errors }}</div>
+ </div>
+ </div>
+ </div>
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Description :</div>
+ <div class="col text-left">
+ <div class="row">
+ <div class="col">{{ form.description }}</div>
+ </div>
+ <div class="row m-1 text-danger">
+ <div class="col">{{ form.description.errors }}</div>
+ </div>
+ </div>
+ </div>
+ <div class="row my-3">
+ <div class="col-3 font-weight-bold">Terms and Conditions :</div>
+ <div class="col text-left">
+ <div class="row">
+ <div class="col">{{ form.terms_and_conditions }}</div>
+ </div>
+ <div class="row m-1 text-danger">
+ <div class="col">{{ form.terms_and_conditions.errors }}</div>
+ </div>
+ </div>
+ </div>
+
+ <h2 class="text-center m-2">Attachments</h2>
+ {{ form_file.management_form }}
+ {{ form_file.non_form_errors }}
+ {% for form in form_file %}
+ <div class="inline {{ form_file.prefix }} my-4">
+ <div class="row">
+ <div class="col-11">
+ {% for field in form %}
+ <div class="col-6">{{ field }}</div>
+ {% endfor %}
+ </div>
+ {% if form.id.value %}
+ <div class="col-1">
+ <a href="{% url 'delete_attachment_file' form.id.value %}"><button class="btn btn-md btn-danger float-right" type="button">Delete</button></a>
+ </div>
+ {% endif %}
+ </div>
+
+ </div>
+ <hr>
+ {% endfor %}
+ <div class="row my-3">
+ <div class="col-12">
+ <button type="submit" class="btn btn-md btn-primary float-right m-3">Save</button>
+ </div>
+ </div>
+ </form>
+ </div>
+ <br><br><br><br>
+ <script type="text/javascript">
+ $(function () {
+ $(".inline.{{ form_file.prefix }}").formset({
+ prefix: "{{ form_file.prefix }}", // The form prefix for your django formset
+ addCssClass: "btn btn-md btn-primary bordered inline-form-add", // CSS class applied to the add link
+ deleteCssClass: "hidden", // CSS class applied to the delete link
+ addText: 'Add another attachment', // Text for the add link
+ deleteText: '',
+ formCssClass: 'inline-form' // CSS class applied to each form in a formset
+ })
+ });
+ </script>
+{% endblock %} \ No newline at end of file
diff --git a/workshop_app/templates/workshop_app/workshop_type_details.html b/workshop_app/templates/workshop_app/workshop_type_details.html
index b8d6559..298d976 100644
--- a/workshop_app/templates/workshop_app/workshop_type_details.html
+++ b/workshop_app/templates/workshop_app/workshop_type_details.html
@@ -1,23 +1,40 @@
-
{% extends 'workshop_app/base.html' %}
{% block title %}
- View Workshop details
+ View Workshop details
{% endblock %}
{% block extra %}
- <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> -->
+ <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> -->
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
- <script src="{{URL_ROOT}}/static/workshop_app/js/bootstrap-3.3.7.min.js"></script>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+ <script src="{{ URL_ROOT }}/static/workshop_app/js/bootstrap-3.3.7.min.js"></script>
{% endblock %}
{% block content %}
- <div class="container">
- {{ workshop_type.description | safe }}
- </div>
+ <div class="container">
+ <h2 class="text-center m-3">Workshop Details</h2>
+ <table class="table table-hover">
+ <tr class="d-flex">
+ <th class="col-3">Workshop Name :</th>
+ <td class="col">{{ workshop_type.name }}</td>
+ </tr>
+ <tr class="d-flex">
+ <th class="col-3">Duration :</th>
+ <td class="col">{{ workshop_type.duration }}</td>
+ </tr>
+ <tr class="d-flex">
+ <th class="col-3">Description :</th>
+ <td class="col">{{ workshop_type.description }}</td>
+ </tr>
+ <tr class="d-flex">
+ <th class="col-3">Terms and Conditions :</th>
+ <td class="col">{{ workshop_type.terms_and_conditions }}</td>
+ </tr>
+ </table>
+ </div>
{% endblock %}
diff --git a/workshop_app/templates/workshop_app/workshop_type_list.html b/workshop_app/templates/workshop_app/workshop_type_list.html
index 0531864..a3d9c6e 100644
--- a/workshop_app/templates/workshop_app/workshop_type_list.html
+++ b/workshop_app/templates/workshop_app/workshop_type_list.html
@@ -4,55 +4,16 @@
View List of available Workshops
{% endblock %}
-{% block extra %}
-
- <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> -->
- <style>
- /* The Modal (background) */
- .modal {
- display: none; /* Hidden by default */
- position: fixed; /* Stay in place */
- z-index: 1; /* Sit on top */
- padding-top: 100px; /* Location of the box */
- left: 0;
- top: 0;
- width: 100%; /* Full width */
- height: 100%; /* Full height */
- overflow: auto; /* Enable scroll if needed */
- background-color: rgb(0,0,0); /* Fallback color */
- background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
- }
-
- /* Modal Content */
- .modal-content {
- background-color: #fefefe;
- margin: auto;
- padding: 20px;
- border: 1px solid #888;
- width: 80%;
- }
-
- /* The Close Button */
- .close {
- color: #aaaaaa;
- float: right;
- font-size: 28px;
- font-weight: bold;
- }
- .close:hover,
- .close:focus {
- color: #000;
- text-decoration: none;
- cursor: pointer;
- }
- </style>
-
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
- <script src="{{URL_ROOT}}/static/workshop_app/js/bootstrap-3.3.7.min.js"></script>
- {% endblock %}
-
{% block content %}
-
+ <div class="container">
+ <h2 class="text-center">Workshop Types</h2>
+ <br>
+ {% if request.user.profile.position == 'instructor' %}
+ <a href="{% url 'add_workshop_type' %}">
+ <button class="btn btn-md btn-primary float-right mb-3 mx-4">Add Workshop Type</button>
+ </a>
+ <br>
+ {% endif %}
<div class="container">
<table class="table table-hover">
<thead>
@@ -60,6 +21,7 @@
<th>id</th>
<th>Workshop Name</th>
<th>Workshop Duration</th>
+ <th>Action</th>
</tr>
</thead>
@@ -119,5 +81,5 @@
</nav>
</div>
</div>
-
+</div>
{% endblock %}
diff --git a/workshop_app/urls.py b/workshop_app/urls.py
index eb101c3..f9c7877 100644
--- a/workshop_app/urls.py
+++ b/workshop_app/urls.py
@@ -29,10 +29,12 @@ urlpatterns = [
url(r'^dashboard$', views.workshop_status_instructor, name='workshop_status_instructor'),
url(r'^accept_workshop/(?P<workshop_id>\d+)', views.accept_workshop, name='accept_workshop'),
url(r'^change_workshop_date/(?P<workshop_id>\d+)$', views.change_workshop_date, name='change_workshop_date'),
- url(r'^propose_workshop/$', views.propose_workshop),
- url(r'^workshop_types/$', views.workshop_type_list),
url(r'^workshops/(?P<workshop_id>\d+)$', views.workshop_details, name='workshop_details'),
url(r'^workshop_type_details/(?P<workshop_type_id>\d+)$', views.workshop_type_details, name='workshop_type_details'),
url(r'^workshop_type_tnc/(?P<workshop_type_id>\d+)$', views.workshop_type_tnc, name='workshop_type_tnc'),
- url(r'^view_profile/(?P<workshop_type_id>\d+)$', views.view_comment_profile, name='view_profile'),
+ url(r'^propose_workshop/$', views.propose_workshop, name='propose_workshop'),
+ url(r'^add_workshop_type$', views.add_workshop_type, name='add_workshop_type'),
+ url(r'^delete_attachment_file/(?P<file_id>\d+)$', views.delete_attachment_file, name='delete_attachment_file'),
+ url(r'^workshop_types/$', views.workshop_type_list, name='workshop_type_list'),
+ url(r'^view_profile/(?P<user_id>\d+)$', views.view_comment_profile, name='view_profile'),
]
diff --git a/workshop_app/views.py b/workshop_app/views.py
index eefb94e..3f24a2f 100644
--- a/workshop_app/views.py
+++ b/workshop_app/views.py
@@ -1,4 +1,5 @@
from django.db.models import Q
+from django.forms import inlineformset_factory, model_to_dict
from django.http import JsonResponse, Http404
from django.urls import reverse
@@ -16,12 +17,12 @@ from django.utils import timezone
from .forms import (
UserRegistrationForm, UserLoginForm,
- ProfileForm, WorkshopForm, CommentsForm
+ ProfileForm, WorkshopForm, CommentsForm, WorkshopTypeForm
)
from .models import (
Profile, User,
- Workshop,
- WorkshopType, Comment
+ Workshop, Comment,
+ WorkshopType, AttachmentFile
)
from .send_mails import send_email
@@ -336,13 +337,41 @@ def propose_workshop(request):
)
+@login_required
def workshop_type_details(request, workshop_type_id):
"""Gives the types of workshop details """
user = request.user
if user.is_superuser:
return redirect("/admin")
- workshop_type = WorkshopType.objects.get(id=workshop_type_id)
+ workshop_type = WorkshopType.objects.filter(id=workshop_type_id)
+ if workshop_type.exists():
+ workshop_type = workshop_type.first()
+ else:
+ return redirect(reverse('workshop_type_list'))
+
+ qs = AttachmentFile.objects.filter(workshop_type=workshop_type)
+ AttachmentFileFormSet = inlineformset_factory(WorkshopType, AttachmentFile, fields=['attachments'],
+ can_delete=False, extra=(qs.count() + 1))
+
+ if is_instructor(user):
+ if request.method == 'POST':
+ form = WorkshopTypeForm(request.POST, instance=workshop_type)
+ form_file = AttachmentFileFormSet(request.POST, request.FILES, instance=form.instance)
+ if form.is_valid():
+ form_data = form.save()
+ for file in form_file:
+ if file.is_valid() and file.clean() and file.clean()['attachments']:
+ if file.cleaned_data['id']:
+ file.cleaned_data['id'].delete()
+ file.save()
+ return redirect(reverse('workshop_type_details', args=[form_data.id]))
+ else:
+ form = WorkshopTypeForm(instance=workshop_type)
+ form_file = AttachmentFileFormSet()
+ for subform, data in zip(form_file, qs):
+ subform.initial = model_to_dict(data)
+ return render(request, 'workshop_app/edit_workshop_type.html', {'form': form, 'form_file': form_file})
return render(
request, 'workshop_app/workshop_type_details.html', {'workshop_type': workshop_type}
@@ -350,6 +379,18 @@ def workshop_type_details(request, workshop_type_id):
@login_required
+def delete_attachment_file(request, file_id):
+ if not is_instructor(request.user):
+ return redirect(get_landing_page(request.user))
+ file = AttachmentFile.objects.filter(id=file_id)
+ if file.exists():
+ file = file.first()
+ file.delete()
+ return redirect(reverse('workshop_type_details', args=[file.workshop_type.id]))
+ return redirect(reverse('workshop_type_list'))
+
+
+@login_required
def workshop_type_tnc(request, workshop_type_id):
workshop_type = WorkshopType.objects.filter(id=workshop_type_id)
if workshop_type.exists():
@@ -368,7 +409,6 @@ def workshop_type_list(request):
workshop_types = WorkshopType.objects.all()
paginator = Paginator(workshop_types, 12) # Show upto 12 workshops per page
-
page = request.GET.get('page')
workshop_type = paginator.get_page(page)
@@ -403,6 +443,20 @@ def workshop_details(request, workshop_id):
@login_required
+def add_workshop_type(request):
+ if not is_instructor(request.user):
+ return redirect(get_landing_page(request.user))
+ if request.method == 'POST':
+ form = WorkshopTypeForm(request.POST)
+ if form.is_valid():
+ form_data = form.save()
+ return redirect(reverse('workshop_type_details', args=[form_data.id]))
+ else:
+ form = WorkshopTypeForm
+ return render(request, 'workshop_app/add_workshop_type.html', {'form': form})
+
+
+@login_required
def view_comment_profile(request, user_id):
"""Instructor can view coordinator profile """
user = request.user