diff options
author | Akshen | 2018-08-03 16:22:10 +0530 |
---|---|---|
committer | GitHub | 2018-08-03 16:22:10 +0530 |
commit | 8c6ecdec16359244ac1fe86388475936adcd7b83 (patch) | |
tree | 2934378ef57fb473168747b49d603b863d426f90 | |
parent | 1376481c54600d9ddc41d89552e83632277e997a (diff) | |
parent | 802ab05a0cd4fbf197b014664d5bb70907862aef (diff) | |
download | workshop_booking-8c6ecdec16359244ac1fe86388475936adcd7b83.tar.gz workshop_booking-8c6ecdec16359244ac1fe86388475936adcd7b83.tar.bz2 workshop_booking-8c6ecdec16359244ac1fe86388475936adcd7b83.zip |
Merge pull request #63 from Akshen/develop
Allow Instructors to Post Comments on Coordinator's Profile
-rw-r--r-- | workshop_app/forms.py | 25 | ||||
-rw-r--r-- | workshop_app/models.py | 21 | ||||
-rw-r--r-- | workshop_app/send_mails.py | 4 | ||||
-rw-r--r-- | workshop_app/templates/workshop_app/base.html | 6 | ||||
-rw-r--r-- | workshop_app/templates/workshop_app/index.html | 11 | ||||
-rw-r--r-- | workshop_app/templates/workshop_app/my_workshops.html | 13 | ||||
-rw-r--r-- | workshop_app/templates/workshop_app/view_comment_profile.html | 110 | ||||
-rw-r--r-- | workshop_app/tests/test_views.py | 12 | ||||
-rw-r--r-- | workshop_app/urls.py | 1 | ||||
-rw-r--r-- | workshop_app/views.py | 51 | ||||
-rw-r--r-- | workshop_portal/settings.py | 2 |
11 files changed, 233 insertions, 23 deletions
diff --git a/workshop_app/forms.py b/workshop_app/forms.py index bbc2811..68ada33 100644 --- a/workshop_app/forms.py +++ b/workshop_app/forms.py @@ -2,7 +2,8 @@ from django import forms from django.utils import timezone from .models import ( Profile, User, Workshop, WorkshopType, - RequestedWorkshop, BookedWorkshop, ProposeWorkshopDate + RequestedWorkshop, BookedWorkshop, ProposeWorkshopDate, + ProfileComments ) from string import punctuation, digits try: @@ -263,3 +264,25 @@ class ProposeWorkshopDateForm(forms.ModelForm): 'proposed_workshop_date': forms.DateInput(attrs={ 'class':'datepicker'}) } + + + +class ProfileCommentsForm(forms.ModelForm): + """ + Instructors will post comments on Coordinators profile + """ + + def __init__(self, *args, **kwargs): + super(ProfileCommentsForm, self).__init__(*args, **kwargs) + self.fields['comment'].label = "" + self.fields['comment'].widget.attrs['rows'] = 5 + self.fields['comment'].widget.attrs['cols'] = 95 + + class Meta: + model = ProfileComments + exclude = ['coordinator_profile', 'instructor_profile', + 'created_date' + ] + widgets = { + 'comments' : forms.CharField(), + }
\ No newline at end of file diff --git a/workshop_app/models.py b/workshop_app/models.py index 1d0852c..3f78e1d 100644 --- a/workshop_app/models.py +++ b/workshop_app/models.py @@ -2,6 +2,7 @@ from django.db import models from django.contrib.auth.models import User from django.core.validators import RegexValidator from recurrence.fields import RecurrenceField +from django.utils import timezone import os position_choices = ( @@ -269,3 +270,23 @@ class Testimonial(models.Model): self.institute, self.department ) + + + +class ProfileComments(models.Model): + """ + Contains comments posted by instructors on coordinator profile + """ + + coordinator_profile = models.ForeignKey(User, + on_delete=models.CASCADE) + comment = models.TextField() + instructor_profile = models.ForeignKey(User, + related_name="%(app_label)s_%(class)s_related") + created_date = models.DateTimeField(default=timezone.now) + + def __str__(self): + return u"{0} | {1}".format( + self.comment, + self.created_date + )
\ No newline at end of file diff --git a/workshop_app/send_mails.py b/workshop_app/send_mails.py index 3826ec8..548834d 100644 --- a/workshop_app/send_mails.py +++ b/workshop_app/send_mails.py @@ -340,8 +340,8 @@ def send_email( request, call_on, elif call_on == 'Proposed Workshop': if user_position == "instructor": message = dedent("""\ - A coordinator has proposed a workshop below are the - details: + A coordinator has proposed a workshop. The details are + given below: Coordinator name: {0} Coordinator email: {1} diff --git a/workshop_app/templates/workshop_app/base.html b/workshop_app/templates/workshop_app/base.html index 1722e59..724ecb2 100644 --- a/workshop_app/templates/workshop_app/base.html +++ b/workshop_app/templates/workshop_app/base.html @@ -9,9 +9,8 @@ </title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> - <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> - <link href="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"> - + <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> + <link href="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"> <link rel="stylesheet" href="{{ URL_ROOT }}/static/workshop_app/css/sticky-footer.css" type="text/css" /> </head> @@ -90,6 +89,7 @@ <h1>Base Template Content. Please override me</h1> {% endblock %} + </body> <footer class="footer"> <div class="container"> diff --git a/workshop_app/templates/workshop_app/index.html b/workshop_app/templates/workshop_app/index.html index ad7bc1a..def5544 100644 --- a/workshop_app/templates/workshop_app/index.html +++ b/workshop_app/templates/workshop_app/index.html @@ -9,7 +9,6 @@ <!-- <script src="{{ URL_ROOT }}/static/workshop_app/css/bootstrap4.min.css"></script> --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> - <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> <!-- Custom CSS --> @@ -21,14 +20,14 @@ <!-- Add icon library --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> - <script type="text/javascript" src="//code.jquery.com/jquery-1.11.0.min.js"></script> - <script type="text/javascript" src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script> +<script type="text/javascript" src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script> - <!-- Custom JS --> - <script src="{{ URL_ROOT }}/static/workshop_app/js/index.js"></script> - <script src="{{ URL_ROOT }}/static/workshop_app/js/slick.js"></script> +<!-- Custom JS --> +<script src="{{ URL_ROOT }}/static/workshop_app/js/index.js"></script> +<script src="{{ URL_ROOT }}/static/workshop_app/js/slick.js"></script> +<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> <title>Welcome</title> diff --git a/workshop_app/templates/workshop_app/my_workshops.html b/workshop_app/templates/workshop_app/my_workshops.html index 1708c95..846c11b 100644 --- a/workshop_app/templates/workshop_app/my_workshops.html +++ b/workshop_app/templates/workshop_app/my_workshops.html @@ -149,7 +149,8 @@ <tr> {% if workshop.status == 'Pending' and workshop.requested_workshop_instructor %} {% if request.user.profile.position == 'instructor' %} - <td>{{ workshop.requested_workshop_coordinator.get_full_name }}</td> + <td><a href="{{ URL_ROOT }}/view_comment_profile/{{ workshop.requested_workshop_coordinator.profile.user.id }}"> + {{ workshop.requested_workshop_coordinator.get_full_name }}</a></td> {% else %} <td>{{ workshop.requested_workshop_instructor.get_full_name }}</td> {% endif %} @@ -190,7 +191,8 @@ <tr> {% if workshop.status == 'ACCEPTED' and workshop.requested_workshop_title %} {% if request.user.profile.position == 'instructor' %} - <td>{{ workshop.requested_workshop_coordinator.get_full_name }}</td> + <td><a href="{{ URL_ROOT }}/view_comment_profile/{{ workshop.requested_workshop_coordinator.profile.user.id }}"> + {{ workshop.requested_workshop_coordinator.get_full_name }}</a></td> <td>{{ workshop.requested_workshop_coordinator.profile.institute }}</td> {% else %} <td>{{ workshop.requested_workshop_instructor.get_full_name }}</td> @@ -214,7 +216,8 @@ {% endif %} {% if workshop.status == 'ACCEPTED' and workshop.condition_one %} {% if request.user.profile.position == 'instructor' %} - <td>{{ workshop.proposed_workshop_coordinator.get_full_name }}</td> + <td><a href="{{ URL_ROOT }}/view_comment_profile/{{ workshop.proposed_workshop_coordinator.profile.user.id }}"> + {{ workshop.proposed_workshop_coordinator.get_full_name }}</a></td> <td>{{ workshop.proposed_workshop_coordinator.profile.institute }}</td> {% else %} <td>{{ workshop.proposed_workshop_instructor.get_full_name }}</td> @@ -273,7 +276,9 @@ <tr> {% if workshop.status == 'Pending' and workshop.condition_one %} {% if request.user.profile.position == 'instructor' %} - <td>{{ workshop.proposed_workshop_coordinator.get_full_name }}</td> + + <td><a href="{{ URL_ROOT }}/view_comment_profile/{{ workshop.proposed_workshop_coordinator.profile.user.id }}"> + {{ workshop.proposed_workshop_coordinator.get_full_name }}</a></td> <td>{{ workshop.proposed_workshop_coordinator.profile.institute }}</td> {% endif %} <td>{{ workshop.proposed_workshop_title }}</td> diff --git a/workshop_app/templates/workshop_app/view_comment_profile.html b/workshop_app/templates/workshop_app/view_comment_profile.html new file mode 100644 index 0000000..b420694 --- /dev/null +++ b/workshop_app/templates/workshop_app/view_comment_profile.html @@ -0,0 +1,110 @@ +{% extends 'workshop_app/base.html' %} + +{% block title %} + Coordinator Profile +{% endblock %} + + + {% block extra %} + <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 %} + +{% csrf_token %} +{% block content %} + + <div class="container" style="overflow-y: scroll;"> + <table class="table table-bordered"> + <tr> + <th><label for="id_first_name"><h5>First name:</h5></label></th> + <th><label for="id_first_name"><h5>{{ coordinator_profile.user.first_name }}</h5></label></th> + </tr> + <tr> + <th><label for="id_last_name"><h5>Last name:</h5></label></th> + <th><label for="id_last_name"><h5>{{ coordinator_profile.user.last_name }}</h5></label></th> + </tr> + <tr> + <th><label for="id_email"><h5>Email:</h5></label></th> + <th><label for="id_email"><h5>{{ coordinator_profile.user.email }}</h5></label></th> + </tr> + <tr> + <th><label for="id_institute"><h5>Institute:</h5></label></th> + <th><label for="id_institute"><h5>{{ coordinator_profile.user.profile.institute }}</h5></label></th> + </tr> + <tr> + <th><label for="id_phone_number"><h5>Phone Number:</h5></label></th> + <th><label for="id_phone_number"><h5>{{ coordinator_profile.user.profile.phone_number }}</h5></label></th> + </tr> + <tr> + <th><label for="id_department"><h5>Department:</h5></label></th> + <th><label for="id_department"><h5>{{ coordinator_profile.user.profile.department }}</h5></label></th> + </tr> + <tr> + <th><label for="id_location"><h5>Location:</h5></label></th> + <th><label for="id_location"><h5>{{ coordinator_profile.user.profile.location }}</h5></label></th> + </tr> + <tr> + <th><label for="id_position"><h5>Position:</h5></label></th> + <th><label for="id_position"><h5>{{ user.profile.position }}</h5></label></th> + </tr> + </table> + + <br> + <h1 style="color:#2c5aa0">Comments</h1> + <div> + <form method="POST"> + <br> + {% csrf_token %} + {{ comment_form.as_p }} + <button type="submit" class="btn btn-default">Post</button> + </form> + + </div> + <hr style="background-color: #fff; + border-top: 5px double #8c8b8b;"> + <table> + {% for comment in comments %} + <tbody> + <tr> + <td> + <h5>{{ comment.instructor_profile.profile.user.get_full_name }} | {{ comment.created_date | date }}</h5> + <h6 style="background-color: #ecf0f1; padding:10px;">{{ comment.comment }}</h6> + <hr style="border-top: 0.5px solid #8c8b8b;"> + </td> + </tr> + </tbody> + {% endfor %} + </table> + +<br><br> + </div> + + <!-- Page Navigation --> + <div class="container"> + <div class="Page-Nav" align="center"> + <nav aria-label="Page navigation"> + <ul class="pagination pagination-sm"> + <li class="page-item"> + {% if comments.has_previous %} + <a class="page-link" tabindex="-1" + href="?page={{ comments.previous_page_number }}">Previous</a> + {% endif %} + </li> + <li class="page-item"> + <span class="current"> + Page {{ comments.number }} of {{ comments.paginator.num_pages }} + </span> + </li> + <li class="page-item"> + {% if comments.has_next %} + <a class="page-link" href="?page={{ comments.next_page_number }}">Next + </a> + {% endif %} + </li> + </ul> + </nav> + </div> + <br> + </div> + +{% endblock %} diff --git a/workshop_app/tests/test_views.py b/workshop_app/tests/test_views.py index efe8c38..1a0d276 100644 --- a/workshop_app/tests/test_views.py +++ b/workshop_app/tests/test_views.py @@ -1,8 +1,8 @@ from workshop_app.views import view_profile, user_login, edit_profile from django.test import TestCase from workshop_app.models import Profile, User, Workshop, WorkshopType,\ - RequestedWorkshop, BookedWorkshop, ProposeWorkshopDate,\ - has_profile + RequestedWorkshop, BookedWorkshop, ProposeWorkshopDate,\ + has_profile from datetime import datetime from json import dumps from django.test import Client @@ -279,8 +279,8 @@ class TestWorkshopDashboard(TestCase): workshop_title=self.workshoptype, recurrences='RRULE:FREQ=WEEKLY;UNTIL=20170624T183000Z;BYDAY=WE;' ) - - + + class TestStaticPages(TestCase): def test_register(self): @@ -299,6 +299,10 @@ class TestStaticPages(TestCase): response = self.client.get('/view_workshoptype_list/') self.assertEqual(response.status_code, 200) + def test_view_self_workshop(self): + response = self.client.get('/self_workshop/') + self.assertEqual(response.status_code, 200) + class TestWorkshopStats(TestCase): def setUp(self): diff --git a/workshop_app/urls.py b/workshop_app/urls.py index 6f428b3..154915d 100644 --- a/workshop_app/urls.py +++ b/workshop_app/urls.py @@ -44,5 +44,6 @@ urlpatterns = [ url(r'^workshop_stats/$', views.workshop_stats), url(r'^jsi18n/$', django.views.i18n.javascript_catalog, js_info_dict), url(r'^self_workshop', views.self_workshop), + url(r'^view_comment_profile/([1-9][0-9]*)$', views.view_comment_profile), ] diff --git a/workshop_app/views.py b/workshop_app/views.py index 699c4d9..76edc95 100644 --- a/workshop_app/views.py +++ b/workshop_app/views.py @@ -1,14 +1,14 @@ from .forms import ( UserRegistrationForm, UserLoginForm, ProfileForm, CreateWorkshop, - ProposeWorkshopDateForm + ProposeWorkshopDateForm, ProfileCommentsForm ) from .models import ( Profile, User, has_profile, Workshop, WorkshopType, RequestedWorkshop, BookedWorkshop, ProposeWorkshopDate, - Testimonial + Testimonial, ProfileComments ) from datetime import datetime, date from django.contrib.auth import login, logout, authenticate @@ -1180,3 +1180,50 @@ def workshop_stats(request): def self_workshop(request): return render(request, "workshop_app/self_workshop.html") + + + +@login_required +def view_comment_profile(request, user_id): + '''instructor can view/post comments on coordinator profile ''' + user = request.user + if is_instructor(user) and is_email_checked(user): + comment_form = ProfileCommentsForm() + coordinator_profile = Profile.objects.get(user_id=user_id) + try: + comments = ProfileComments.objects.filter(coordinator_profile_id=user_id).order_by('-created_date') + except: + comments = None + if request.method == 'POST': + comment_formpost = ProfileCommentsForm(request.POST) + if comment_formpost.is_valid(): + form_data = comment_formpost.save(commit=False) + form_data.coordinator_profile_id = user_id + form_data.instructor_profile_id = user.id + form_data.save() + + return render(request, "workshop_app/view_comment_profile.html", + {"coordinator_profile": coordinator_profile, + "comments": comments, + "comment_form": comment_form + }) + else: + if comments is not None: + #Show upto 12 Workshops per page + paginator = Paginator(comments, 12) + page = request.GET.get('page') + try: + comments = paginator.page(page) + except PageNotAnInteger: + #If page is not an integer, deliver first page. + comments = paginator.page(1) + except EmptyPage: + #If page is out of range(e.g 999999), deliver last page. + comments = paginator.page(paginator.num_pages) + + return render(request, "workshop_app/view_comment_profile.html", + {"coordinator_profile": coordinator_profile, + "comments": comments, + "comment_form": comment_form}) + return redirect('/book/') + diff --git a/workshop_portal/settings.py b/workshop_portal/settings.py index cf3db96..179d354 100644 --- a/workshop_portal/settings.py +++ b/workshop_portal/settings.py @@ -164,4 +164,4 @@ SHOW_WORKSHOP_STATS = False LOGIN_REDIRECT_URL = '/profile' SESSION_EXPIRE_AT_BROWSER_CLOSE = True SESSION_SAVE_EVERY_REQUEST = True -SESSION_COOKIE_AGE = 360 +SESSION_COOKIE_AGE = 3600 |