summaryrefslogtreecommitdiff
path: root/workshop_app
diff options
context:
space:
mode:
authorAkshen2017-09-05 14:05:25 +0530
committerAkshen2017-09-05 14:05:25 +0530
commit47cdf0a98730ba006a24d4d710afdad04c861363 (patch)
treecc56921a1199fd57d4f612e3efa279a07d335405 /workshop_app
parent86e0b947d7d8cf20cd354d6653b1c84c0e6d124f (diff)
downloadworkshop_booking-47cdf0a98730ba006a24d4d710afdad04c861363.tar.gz
workshop_booking-47cdf0a98730ba006a24d4d710afdad04c861363.tar.bz2
workshop_booking-47cdf0a98730ba006a24d4d710afdad04c861363.zip
Updates Workshop Stats
- Updates .gitignore - Updates footer, sets it to fixed position - Adds Workshop Stats - Instructor can Download or View Workshop stats from the givin date range - Instructor can view number of workshops per month in chart - Writes test for Workshop Stats
Diffstat (limited to 'workshop_app')
-rw-r--r--workshop_app/forms.py4
-rw-r--r--workshop_app/reminder_script.py10
-rw-r--r--workshop_app/static/workshop_app/css/sticky-footer.css18
-rw-r--r--workshop_app/templates/workshop_app/base.html2
-rw-r--r--workshop_app/templates/workshop_app/edit_profile.html2
-rw-r--r--workshop_app/templates/workshop_app/manage.html4
-rw-r--r--workshop_app/templates/workshop_app/my_workshops.html14
-rw-r--r--workshop_app/templates/workshop_app/profile_updated.html2
-rw-r--r--workshop_app/templates/workshop_app/propose_workshop.html2
-rw-r--r--workshop_app/templates/workshop_app/scheduled_workshops.html89
-rw-r--r--workshop_app/templates/workshop_app/view_profile.html2
-rw-r--r--workshop_app/templates/workshop_app/view_workshoptype_list.html2
-rw-r--r--workshop_app/templates/workshop_app/workshop_stats.html245
-rw-r--r--workshop_app/tests/test_views.py52
-rw-r--r--workshop_app/urls.py2
-rw-r--r--workshop_app/views.py238
16 files changed, 510 insertions, 178 deletions
diff --git a/workshop_app/forms.py b/workshop_app/forms.py
index cce6dfc..1e9eb05 100644
--- a/workshop_app/forms.py
+++ b/workshop_app/forms.py
@@ -190,7 +190,6 @@ class ProposeWorkshopDateForm(forms.ModelForm):
self.fields['proposed_workshop_title'].label = "Workshop :"
self.fields['proposed_workshop_date'].label = "Workshop Date :"
-
class Meta:
model = ProposeWorkshopDate
exclude = ['status', 'proposed_workshop_instructor',
@@ -198,5 +197,4 @@ class ProposeWorkshopDateForm(forms.ModelForm):
widgets = {
'proposed_workshop_date': forms.DateInput(attrs={
'class':'datepicker'}),
- }
-
+ } \ No newline at end of file
diff --git a/workshop_app/reminder_script.py b/workshop_app/reminder_script.py
index 9b3f059..4c4350c 100644
--- a/workshop_app/reminder_script.py
+++ b/workshop_app/reminder_script.py
@@ -25,16 +25,15 @@ from workshop_portal.settings import (
from workshop_app.models import *
from datetime import datetime, date
-
def send_email():
- tomorrow = date.today() + dt.timedelta(days=2)
+ upcoming = date.today() + dt.timedelta(days=2)
upcoming_requested_workshops = RequestedWorkshop.objects.filter(
- requested_workshop_date=tomorrow,
+ requested_workshop_date=upcoming,
status='ACCEPTED'
)
upcoming_proposed_workshops = ProposeWorkshopDate.objects.filter(
- proposed_workshop_date=tomorrow,
+ proposed_workshop_date=upcoming,
status='ACCEPTED'
)
for w in upcoming_proposed_workshops:
@@ -81,5 +80,4 @@ def send_email():
[w.requested_workshop_instructor.email], fail_silently=False
)
-
-send_email() \ No newline at end of file
+send_email()
diff --git a/workshop_app/static/workshop_app/css/sticky-footer.css b/workshop_app/static/workshop_app/css/sticky-footer.css
index 924258c..7e5ed4c 100644
--- a/workshop_app/static/workshop_app/css/sticky-footer.css
+++ b/workshop_app/static/workshop_app/css/sticky-footer.css
@@ -36,14 +36,16 @@
background-color: #efefef;
}
-/* Footer CSS */
+/**
+ * Footer Styles
+ */
+
.footer {
- position: relative;
- bottom: 0;
- right: 0;
- left: 0;
-}
-.hiddenRow {
- padding: 0 !important;
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background-color: #efefef;
+ text-align: center;
} \ 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 391fa9b..b2a5335 100644
--- a/workshop_app/templates/workshop_app/base.html
+++ b/workshop_app/templates/workshop_app/base.html
@@ -44,10 +44,10 @@
<h1>Base Template Content. Please override me</h1>
{% endblock %}
+</body>
<footer class="footer">
<div class="container">
<p align="center">Developed by FOSSEE group, IIT Bombay</p>
</div>
</footer>
-</body>
</html> \ No newline at end of file
diff --git a/workshop_app/templates/workshop_app/edit_profile.html b/workshop_app/templates/workshop_app/edit_profile.html
index 5e01430..70ad417 100644
--- a/workshop_app/templates/workshop_app/edit_profile.html
+++ b/workshop_app/templates/workshop_app/edit_profile.html
@@ -15,7 +15,7 @@
<li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
<li><a href="{{ URL_ROOT }}/view_workshoptype_list/">Workshop List</a></li>
<li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li>
- <li><a href="{{ URL_ROOT }}/scheduled_workshops/">Scheduled Workshops</a></li>
+ <li><a href="{{ URL_ROOT }}/workshop_stats/">Workshop Stats</a></li>
</ul>
{% else %}
<div class="navbar-header">
diff --git a/workshop_app/templates/workshop_app/manage.html b/workshop_app/templates/workshop_app/manage.html
index 9aac809..97f1604 100644
--- a/workshop_app/templates/workshop_app/manage.html
+++ b/workshop_app/templates/workshop_app/manage.html
@@ -10,7 +10,7 @@
<li ><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
<li ><a href="{{ URL_ROOT }}/view_workshoptype_list/"> Workshop List</a></li>
<li ><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li>
- <li><a href="{{ URL_ROOT }}/scheduled_workshops/">Scheduled Workshops</a></li>
+ <li><a href="{{ URL_ROOT }}/workshop_stats/">Workshop Stats</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li>
@@ -126,4 +126,4 @@
</div>
{% endif %}
-{% endblock %} \ No newline at end of file
+{% endblock %}
diff --git a/workshop_app/templates/workshop_app/my_workshops.html b/workshop_app/templates/workshop_app/my_workshops.html
index c36485e..740e28f 100644
--- a/workshop_app/templates/workshop_app/my_workshops.html
+++ b/workshop_app/templates/workshop_app/my_workshops.html
@@ -49,7 +49,7 @@
<li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
<li><a href="{{ URL_ROOT }}/view_workshoptype_list/">Workshop List</a></li>
<li class="active"><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li>
- <li><a href="{{ URL_ROOT }}/scheduled_workshops/">Scheduled Workshops</a></li>
+ <li><a href="{{ URL_ROOT }}/workshop_stats/">Workshop Stats</a></li>
</ul>
{% else %}
<div class="navbar-header">
@@ -61,7 +61,7 @@
<li><a href="{{ URL_ROOT }}/faq/">FAQ's</a></li>
<li><a href="{{ URL_ROOT }}/benefits/">Benefits</a></li>
<li><a href="{{ URL_ROOT }}/view_workshoptype_details/"> Workshop List</a></li>
- <li><a href="{{ URL_ROOT }}/how_to_participate/">How to Participate</a></li>
+ <li><a href="{{ URL_ROOT }}/how_to_participate/">How to Participate</a></li>
</ul>
{% endif %}
@@ -81,7 +81,7 @@
<!-- Pending View -->
<div class="container">
- <h3 align="center"><strong><u>Pending</u></strong></h3>
+ <h3 align="center"><strong><u>My Requests</u></strong></h3>
<table class="table table-striped">
<thead>
<tr>
@@ -122,7 +122,7 @@
<!-- Accepted View -->
<div class="container">
- <h3 align="center"><strong><u>Accepted</u></strong></h3>
+ <h3 align="center"><strong><u>Workshops Accepted</u></strong></h3>
<table class="table table-striped">
<thead>
<tr>
@@ -171,7 +171,7 @@
<!-- Proposed View -->
<div class="container">
- <h3 align="center"><strong><u>Proposed</u></strong></h3>
+ <h3 align="center"><strong><u>Proposed Workshops</u></strong></h3>
<table class="table table-striped">
<thead>
<tr>
@@ -211,7 +211,7 @@
<!-- Deleted/Rejected View -->
<div class="container">
- <h3 align="center"><strong><u>Deleted/Rejected</u></strong></h3>
+ <h3 align="center"><strong><u>Workshops Deleted/Rejected</u></strong></h3>
<table class="table table-striped">
<thead>
<tr>
@@ -295,4 +295,4 @@
{% endif %}
{% endif %}
-{% endblock %} \ No newline at end of file
+{% endblock %}
diff --git a/workshop_app/templates/workshop_app/profile_updated.html b/workshop_app/templates/workshop_app/profile_updated.html
index e0aa3ad..abeb3de 100644
--- a/workshop_app/templates/workshop_app/profile_updated.html
+++ b/workshop_app/templates/workshop_app/profile_updated.html
@@ -15,7 +15,7 @@
<li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
<li><a href="{{ URL_ROOT }}/view_workshoptype_details/"> Workshop List</a></li>
<li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li>
- <li><a href="{{ URL_ROOT }}/scheduled_workshops/">Scheduled Workshops</a></li>
+ <li><a href="{{ URL_ROOT }}/workshop_stats/">Workshop Stats</a></li>
</ul>
{% else %}
<div class="navbar-header">
diff --git a/workshop_app/templates/workshop_app/propose_workshop.html b/workshop_app/templates/workshop_app/propose_workshop.html
index ce90dc8..95a4008 100644
--- a/workshop_app/templates/workshop_app/propose_workshop.html
+++ b/workshop_app/templates/workshop_app/propose_workshop.html
@@ -22,7 +22,7 @@
changeMonth: true,
changeYear: true,
minDate: dateToday,
- maxDate: upto
+ maxDate: upto,
// You can put more options here.
});
});
diff --git a/workshop_app/templates/workshop_app/scheduled_workshops.html b/workshop_app/templates/workshop_app/scheduled_workshops.html
deleted file mode 100644
index a9aedd6..0000000
--- a/workshop_app/templates/workshop_app/scheduled_workshops.html
+++ /dev/null
@@ -1,89 +0,0 @@
-{% extends 'workshop_app/base.html' %}
-
-{% block header %}
- <nav class="navbar navbar-default navbar-custom">
- <div class="container-fluid">
- <div class="navbar-header">
- <a class="navbar-brand" href="{{ URL_ROOT }}/manage/">Home</a>
- </div>
- <ul class="nav navbar-nav">
- <li ><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
- <li ><a href="{{ URL_ROOT }}/view_workshoptype_list/"> Workshop List</a></li>
- <li ><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li>
- <li><a href="{{ URL_ROOT }}/scheduled_workshops/">Scheduled Workshops</a></li>
- </ul>
- <ul class="nav navbar-nav navbar-right">
- <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li>
- <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li>
- </ul>
- </div>
- </nav>
-{% endblock %}
-
-
-{% block content %}
-
- <div class="container">
- {% if scheduled_workshops %}
- <h3>This Table Shows Scheduled Workshops which were Proposed By Coordinators</h3>
- <br>
- <table class="table table-hover">
- <thead>
- <tr>
- <th>Coordinator Name</th>
- <th>Institute Name</th>
- <th>Instructor Name</th>
- <th>Workshop Name</th>
- <th>Workshop Date</th>
- </tr>
- </thead>
- {% csrf_token %}
- {% for workshop in proposed_workshops %}
- {% if workshop.status == 'ACCEPTED' %}
- <tbody>
- <tr>
- <td>{{ workshop.proposed_workshop_coordinator.get_full_name | capfirst }}</td>
- <td>{{ workshop.proposed_workshop_coordinator.profile.institute | capfirst }}</td>
- <td>{{ workshop.proposed_workshop_instructor.get_full_name }}</td>
- <td>{{ workshop.proposed_workshop_title.workshoptype_name }}</td>
- <td>{{ workshop.proposed_workshop_date | date}}</td>
- </tr>
- </tbody>
- {% endif %}
- {% endfor %}
- </table>
- <h3>This Table Shows Scheduled Workshops based on Instructors Approval </h3>
- <br>
- <table class="table table-hover">
- <thead>
- <tr>
- <th>Coordinator Name</th>
- <th>Institute Name</th>
- <th>Instructor Name</th>
- <th>Workshop Name</th>
- <th>Workshop Date</th>
- </tr>
- </thead>
- {% csrf_token %}
- {% for workshop in requested_workshops %}
- {% if workshop.status == 'ACCEPTED' %}
- <tbody>
- <tr>
- <td>{{ workshop.requested_workshop_coordinator.get_full_name | capfirst }}</td>
- <td>{{ workshop.requested_workshop_coordinator.profile.institute | capfirst }}</td>
- <td>{{ workshop.requested_workshop_instructor.get_full_name }}</td>
- <td>{{ workshop.requested_workshop_title.workshoptype_name }}</td>
- <td>{{ workshop.requested_workshop_date | date}}</td>
- </tr>
- </tbody>
- {% endif %}
- {% endfor %}
- </table>
-
- {% else %}
- <div class="jumbotron">
- <h2>Permission to View Scheduled Workshops is set to False</h2>
- </div>
- {% endif %}
- </div>
-{% endblock %}
diff --git a/workshop_app/templates/workshop_app/view_profile.html b/workshop_app/templates/workshop_app/view_profile.html
index d960f45..91efdf1 100644
--- a/workshop_app/templates/workshop_app/view_profile.html
+++ b/workshop_app/templates/workshop_app/view_profile.html
@@ -15,7 +15,7 @@
<li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
<li><a href="{{ URL_ROOT }}/view_workshoptype_list/">Workshop List</a></li>
<li><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li>
- <li><a href="{{ URL_ROOT }}/scheduled_workshops/">Scheduled Workshops</a></li>
+ <li><a href="{{ URL_ROOT }}/workshop_stats/">Workshop Stats</a></li>
</ul>
{% else %}
<div class="navbar-header">
diff --git a/workshop_app/templates/workshop_app/view_workshoptype_list.html b/workshop_app/templates/workshop_app/view_workshoptype_list.html
index 53d32ce..75cee32 100644
--- a/workshop_app/templates/workshop_app/view_workshoptype_list.html
+++ b/workshop_app/templates/workshop_app/view_workshoptype_list.html
@@ -15,7 +15,7 @@
<ul class="nav navbar-nav">
{% if request.user.profile.position == 'instructor'%}
<li><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
- <li><a href="{{ URL_ROOT }}/scheduled_workshops/">Scheduled Workshops</a></li>
+ <li><a href="{{ URL_ROOT }}/workshop_stats/">Workshop Stats</a></li>
{% else %}
<li><a href="{{ URL_ROOT }}/book/">Book</a></li>
<li><a href="{{ URL_ROOT }}/propose_workshop/">Propose a Workshop</a></li>
diff --git a/workshop_app/templates/workshop_app/workshop_stats.html b/workshop_app/templates/workshop_app/workshop_stats.html
new file mode 100644
index 0000000..464c625
--- /dev/null
+++ b/workshop_app/templates/workshop_app/workshop_stats.html
@@ -0,0 +1,245 @@
+{% extends 'workshop_app/base.html' %}
+
+{% block header %}
+ <nav class="navbar navbar-default navbar-custom">
+ <div class="container-fluid">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="{{ URL_ROOT }}/manage/">Home</a>
+ </div>
+ <ul class="nav navbar-nav">
+ <li ><a href="{{ URL_ROOT }}/create_workshop/">Create Workshop</a></li>
+ <li ><a href="{{ URL_ROOT }}/view_workshoptype_list/"> Workshop List</a></li>
+ <li ><a href="{{ URL_ROOT }}/my_workshops/">My Workshops</a></li>
+ <li class="active"><a href="{{ URL_ROOT }}/workshop_stats/" >Workshop Stats</a></li>
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li><a href="{{ URL_ROOT }}/view_profile/"><span class="glyphicon glyphicon-user"></span> Profile </a></li>
+ <li><a href="{{ URL_ROOT }}/logout/"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li>
+ </ul>
+ </div>
+ </nav>
+{% endblock %}
+
+{% block extra %}
+ <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+ <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+ <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
+
+ <!-- For Charts -->
+
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
+
+<script>
+ var dateToday = new Date();
+ var upto = new Date();
+
+ dateToday.setDate(dateToday.getDate() - 1);
+ upto.setFullYear(dateToday.getFullYear() + 1);
+
+ $( function() {
+ from = $( "#from" )
+ .datepicker({
+ defaultDate: "+1w",
+ changeMonth: true,
+ changeYear: true,
+ showButtonPanel: true,
+ maxDate: dateToday,
+ dateFormat: "yy-mm-dd"
+ })
+ .on( "change", function() {
+ to.datepicker( "option", "minDate", getDate( this ) );
+ }),
+ to = $( "#to" ).datepicker({
+ defaultDate: "+1w",
+ changeMonth: true,
+ changeYear: true,
+ showButtonPanel: true,
+ minDate: dateToday,
+ maxDate: upto,
+ dateFormat: "yy-mm-dd"
+ })
+ .on( "change", function() {
+ from.datepicker( "option", "maxDate", getDate( this ) );
+ });
+
+ function getDate( element ) {
+ var date;
+ try {
+ date = $.datepicker.parseDate( dateFormat, element.value );
+ } catch( error ) {
+ date = null;
+ }
+
+ return date;
+ }
+ } );
+
+ </script>
+
+{% endblock %}
+
+{% block content %}
+
+ <div class="container">
+ {% if show_workshop_stats %}
+ <div align="right">
+ <form method="POST" >
+ {% csrf_token %}
+ <div class="form-group">
+ <label for="from">From</label>
+ <input type="text" id="from" name="from">
+ <label for="to">to</label>
+ <input type="text" id="to" name="to">
+ <button class="btn btn-warning" type="submit" name="Download" value="Download">Download</button>
+ <button class="btn btn-info" type="submit" name="View" value="View">View</button>
+ </div>
+ </form>
+ {% if messages %}
+
+ <ul class="messages">
+ {% for message in messages %}
+ <div class="alert alert-{{ message.tags }}">
+ <li {% if message.tags %} class="{{ message.tags }}"{% endif %}> {{ message }}
+ </li>
+ </div>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </div>
+ <br>
+ <table class="table table-hover">
+ <thead>
+ <tr>
+ <th>Coordinator Name</th>
+ <th>Institute Name</th>
+ <th>Instructor Name</th>
+ <th>Workshop Name</th>
+ <th>Workshop Date</th>
+ <th>Requested/Proposed By</th>
+ </tr>
+ </thead>
+ {% csrf_token %}
+ {% for workshop in upcoming_workshops %}
+ {% if workshop.proposed_workshop_date %}
+ <tbody>
+ <tr>
+ <td>{{ workshop.proposed_workshop_coordinator.get_full_name | capfirst }}</td>
+ <td>{{ workshop.proposed_workshop_coordinator.profile.institute | capfirst }}</td>
+ <td>{{ workshop.proposed_workshop_instructor.get_full_name }}</td>
+ <td>{{ workshop.proposed_workshop_title.workshoptype_name }}</td>
+ <td>{{ workshop.proposed_workshop_date | date}}</td>
+ <td>Coordinator</td>
+ </tr>
+ </tbody>
+ {% else %}
+ <tbody>
+ <tr>
+ <td>{{ workshop.requested_workshop_coordinator.get_full_name | capfirst }}</td>
+ <td>{{ workshop.requested_workshop_coordinator.profile.institute | capfirst }}</td>
+ <td>{{ workshop.requested_workshop_instructor.get_full_name }}</td>
+ <td>{{ workshop.requested_workshop_title.workshoptype_name }}</td>
+ <td>{{ workshop.requested_workshop_date | date}}</td>
+ <td>Instructor</td>
+ </tr>
+ </tbody>
+ {% endif %}
+ {% endfor %}
+ </table>
+
+ <!-- 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 upcoming_workshops.has_previous %}
+ <a class="page-link" tabindex="-1"
+ href="?page={{ upcoming_workshops.previous_page_number }}">Previous</a>
+ {% endif %}
+ </li>
+ <li class="page-item">
+ <span class="current">
+ Page {{ upcoming_workshops.number }} of {{ upcoming_workshops.paginator.num_pages }}
+ </span>
+ </li>
+ <li class="page-item">
+ {% if upcoming_workshops.has_next %}
+ <a class="page-link" href="?page={{ upcoming_workshops.next_page_number }}">Next
+ </a>
+ {% endif %}
+ </li>
+ </ul>
+ </nav>
+ </div>
+ </div>
+ {% else %}
+ <div class="jumbotron">
+ <h2>Permission to View Upcoming Workshops is set to false, please set it to true in settings.py</h2>
+ </div>
+ {% endif %}
+ </div>
+<br>
+ <div class="row">
+ <br>
+ <div class="col-md-12 ">
+ <br>
+ <canvas id="myChart" width="300px" height="40px"></canvas>
+ <script>
+ var ctx = document.getElementById("myChart").getContext('2d');
+ var myChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', ' December'],
+ datasets: [{
+ label: 'Number of workshops per Month for '+ dateToday.getFullYear(),
+ data: {{ workshop_count }},
+ backgroundColor: [
+ 'rgba(255, 99, 132, 0.2)',
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(255, 206, 86, 0.2)',
+ 'rgba(75, 192, 192, 0.2)',
+ 'rgba(153, 102, 255, 0.2)',
+ 'rgba(242, 38, 19, 0.2)',
+ 'rgba(25, 91, 13, 0.2)',
+ 'rgba(54, 12, 235, 0.2)',
+ 'rgba(150, 40, 27, 0.2)',
+ 'rgba(66, 114, 155, 0.2)',
+ 'rgba(219, 10, 91, 0.2)',
+ 'rgba(191, 191, 191, 0.2)'
+ ],
+ borderColor: [
+ 'rgba(255, 99, 132, 1)',
+ 'rgba(54, 162, 235, 1)',
+ 'rgba(255, 206, 86, 1)',
+ 'rgba(75, 192, 192, 1)',
+ 'rgba(153, 102, 255, 1)',
+ 'rgba(242, 38, 19, 1)',
+ 'rgba(25, 91, 13, 1)',
+ 'rgba(54, 12, 235, 1)',
+ 'rgba(150, 40, 27 ,1)',
+ 'rgba(66, 114, 155, 1)',
+ 'rgba(219, 10, 91, 1)',
+ 'rgba(191, 191, 191, 1)'
+ ],
+ borderWidth: 1
+ }]
+ },
+ options: {
+ responsive: true,
+ scales: {
+ yAxes: [{
+ ticks: {
+ beginAtZero:true
+ }
+ }]
+ }
+ }
+ });
+ </script>
+ </div>
+
+ </div>
+<br>
+{% endblock %}
diff --git a/workshop_app/tests/test_views.py b/workshop_app/tests/test_views.py
index 5dbfff5..583efd2 100644
--- a/workshop_app/tests/test_views.py
+++ b/workshop_app/tests/test_views.py
@@ -10,6 +10,7 @@ from django.contrib.auth.models import Group, Permission
from django.contrib.auth import authenticate
from django.core.urlresolvers import reverse
from workshop_app.forms import CreateWorkshop
+from django.conf import settings
class TestProfile(TestCase):
def setUp(self):
@@ -289,3 +290,54 @@ class TestStaticPages(TestCase):
def test_view_workshoptype_details(self):
response = self.client.get('/view_workshoptype_details/')
self.assertEqual(response.status_code, 200)
+
+
+class TestWorkshopStats(TestCase):
+ def setUp(self):
+ '''
+ test user as instructor
+ '''
+ self.superuser = User.objects.create_superuser(
+ username='admin',
+ password='pass@123',
+ email='test.user@gmail.com')
+
+ self.mod_group = Group.objects.create(name='instructor')
+
+ self.user_one = User.objects.create(
+ username='test_user1',
+ email='test.user@gmail.com')
+
+ self.user_one.set_password('pass@123')
+ self.user_one.save()
+
+ self.user_one_profile = Profile.objects.create(
+ user=self.user_one,
+ department='cs',
+ institute='IIT',
+ position='instructor',
+ phone_number='1122993388',
+ is_email_verified=1
+ )
+
+ #Add user_one in instructor group and give required permissions
+ self.mod_group.user_set.add(self.user_one)
+ self.permission = (Permission.objects.all())
+ self.user_one.user_permissions.add(self.permission[44])
+ self.user_one.user_permissions.add(self.permission[43])
+ self.user_one.user_permissions.add(self.permission[42])
+
+ def test_workshop_stats(self):
+ settings.SHOW_WORKSHOP_STATS = True
+ self.client.login(username=self.user_one, password='pass@123')
+ response = self.client.post('/workshop_stats/',
+ {
+ 'from': '2017-01-01',
+ 'to': '2017-12-31',
+ 'Download': 'download'
+ }
+ )
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.get('Content-Disposition'),'attachment;\
+ filename="records_from_2017-01-01_to_2017-12-31.csv"')
+
diff --git a/workshop_app/urls.py b/workshop_app/urls.py
index 6c2a04d..3d3b76a 100644
--- a/workshop_app/urls.py
+++ b/workshop_app/urls.py
@@ -44,7 +44,7 @@ urlpatterns = [
url(r'^view_workshoptype_details/$', views.view_workshoptype_details),
url(r'^create_workshop/$', views.create_workshop),
url(r'^propose_workshop/$', views.propose_workshop),
- url(r'^scheduled_workshops/$', views.scheduled_workshops),
+ url(r'^workshop_stats/$', views.workshop_stats),
url(r'^testimonials/$', views.testimonials),
url(r'^file_view/(?P<workshop_title>[\w|\W]+)$', views.file_view),
url(r'^jsi18n/$', django.views.i18n.javascript_catalog, js_info_dict),
diff --git a/workshop_app/views.py b/workshop_app/views.py
index 3bd6552..8e065f9 100644
--- a/workshop_app/views.py
+++ b/workshop_app/views.py
@@ -1,15 +1,16 @@
from .forms import (
- UserRegistrationForm, UserLoginForm,
- ProfileForm, CreateWorkshop,
- ProposeWorkshopDateForm
- )
+ UserRegistrationForm, UserLoginForm,
+ ProfileForm, CreateWorkshop,
+ ProposeWorkshopDateForm
+ )
from .models import (
- Profile, User,
- has_profile, Workshop,
- WorkshopType, RequestedWorkshop,
- BookedWorkshop, ProposeWorkshopDate,
- Testimonial
- )
+ Profile, User,
+ has_profile, Workshop,
+ WorkshopType, RequestedWorkshop,
+ BookedWorkshop, ProposeWorkshopDate,
+ Testimonial
+ )
+from django.template.loader import get_template
from django.template import RequestContext
from datetime import datetime, date
from django.contrib.auth import login, logout, authenticate
@@ -27,7 +28,10 @@ from textwrap import dedent
from django.conf import settings
from os import listdir, path, sep
from zipfile import ZipFile
+from django.db.models import Count
+from django.contrib import messages
import datetime as dt
+import csv
try:
from StringIO import StringIO as string_io
except ImportError:
@@ -192,13 +196,13 @@ def book(request):
for d in range(len(dates)):
workshop_occurence = [
- dates[d].strftime("%d-%m-%Y"),
- workshops.workshop_instructor,
- workshops.workshop_title,
- workshops.workshop_instructor_id,
- workshops.workshop_title_id,
- workshops.workshop_title.workshoptype_description
- ]
+ dates[d].strftime("%d-%m-%Y"),
+ workshops.workshop_instructor,
+ workshops.workshop_title,
+ workshops.workshop_instructor_id,
+ workshops.workshop_title_id,
+ workshops.workshop_title.workshoptype_description
+ ]
workshop_occurence_list.append(workshop_occurence)
del workshop_occurence
@@ -225,8 +229,8 @@ def book(request):
#Objects of RequestedWorkshop for that particular coordinator
rW_obj = RequestedWorkshop.objects.filter(
- requested_workshop_coordinator=request.user
- )
+ requested_workshop_coordinator=request.user
+ )
for r in rW_obj:
x = r.requested_workshop_date.strftime("%d-%m-%Y")
for a in workshop_occurence_list:
@@ -272,32 +276,32 @@ def book_workshop(request):
queue = RequestedWorkshop.objects.filter(
requested_workshop_instructor=client_data[1],
requested_workshop_date=datetime.strptime(
- client_data[0][2:], "%d-%m-%Y"
- ),
+ client_data[0][2:], "%d-%m-%Y"
+ ),
requested_workshop_title=client_data[-2]
).count() + 1
return HttpResponse(str(queue))
workshops_list = Workshop.objects.filter(
- workshop_instructor=client_data[1],
- workshop_title_id=client_data[2]
- )
+ workshop_instructor=client_data[1],
+ workshop_title_id=client_data[2]
+ )
today = datetime.now() + dt.timedelta(days=3)
upto = datetime.now() + dt.timedelta(weeks=52)
for workshop in workshops_list:
workshop_recurrence_list = workshop.recurrences.between(
- today,
- upto,
- inc=True
- )
+ today,
+ upto,
+ inc=True
+ )
rW_obj = RequestedWorkshop()
if RequestedWorkshop.objects.filter(
requested_workshop_instructor=workshop.workshop_instructor,
requested_workshop_date=datetime.strptime(
- client_data[0][2:], "%d-%m-%Y",
- ),
+ client_data[0][2:], "%d-%m-%Y",
+ ),
requested_workshop_coordinator=request.user,
requested_workshop_title=client_data[-1]
).count() > 0:
@@ -312,8 +316,8 @@ def book_workshop(request):
rW_obj.requested_workshop_instructor = workshop.workshop_instructor
rW_obj.requested_workshop_coordinator = request.user
rW_obj.requested_workshop_date = datetime.strptime(
- workshop_date,"%d-%m-%Y"
- )
+ workshop_date,"%d-%m-%Y"
+ )
rW_obj.requested_workshop_title = workshop.workshop_title
rW_obj.save()
@@ -361,8 +365,8 @@ def manage(request):
try:
#Can Handle Multiple Workshops
workshop_details = Workshop.objects.filter(
- workshop_instructor=user.id
- )
+ workshop_instructor=user.id
+ )
workshop_occurence_list = []
today = datetime.now() + dt.timedelta(days=3)
@@ -866,11 +870,12 @@ def file_view(request, workshop_title):
zipfile_name.seek(0)
response = HttpResponse(content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename={0}.zip'.format(
- filename.workshoptype_name.replace(" ", "_")
- )
+ filename.workshoptype_name.replace(" ", "_")
+ )
response.write(zipfile_name.read())
return response
+
def testimonials(request):
testimonials = Testimonial.objects.all().order_by('-id')
paginator = Paginator(testimonials, 3) #Show upto 12 workshops per page
@@ -884,42 +889,163 @@ def testimonials(request):
except EmptyPage:
#If page is out of range(e.g 999999), deliver last page.
messages = paginator.page(paginator.num_pages)
- return render(request, 'workshop_app/testimonals.html', {"messages":messages})
+ return render(request, 'workshop_app/testimonals.html',
+ {"messages":messages})
+
+
+def check_workshop_type(x):
+ try:
+ y = datetime.strftime(x.proposed_workshop_date, '%d-%m-%Y')
+ except:
+ y = datetime.strftime(x.requested_workshop_date, '%d-%m-%Y')
+ return y
+
@login_required
-def scheduled_workshops(request):
+def workshop_stats(request):
user = request.user
today = datetime.now()
- upto = datetime.now() + dt.timedelta(days=15)
+ upto = today + dt.timedelta(days=15)
+
+ #For Monthly Chart
+ workshop_count = [0] * 12
+ for x in range(12):
+ workshop_count[x-1] +=RequestedWorkshop.objects.filter(
+ requested_workshop_date__year=str(today.year),
+ requested_workshop_date__month=str(x)).count()
+ workshop_count[x-1] +=ProposeWorkshopDate.objects.filter(
+ proposed_workshop_date__year=str(today.year),
+ proposed_workshop_date__month=str(x)).count()
+
+ if request.method == 'POST':
+ try:
+ from_dates = request.POST.get('from')
+ to_dates = request.POST.get('to')
+
+ #Fetches Accepted workshops which were proposed by Coordinators
+ proposed_workshops = ProposeWorkshopDate.objects.filter(
+ proposed_workshop_date__range=(from_dates, to_dates),
+ status='ACCEPTED'
+ )
+
+ # Fetches Accepted workshops which were Accepted by
+ # Instructors based on their Availability
+ requested_workshops = RequestedWorkshop.objects.filter(
+ requested_workshop_date__range=(from_dates, to_dates),
+ status='ACCEPTED'
+ )
+
+ upcoming_workshops = []
+
+ for workshop in proposed_workshops:
+ upcoming_workshops.append(workshop)
+
+ for workshop in requested_workshops:
+ upcoming_workshops.append(workshop)
+
+ upcoming_workshops = sorted(upcoming_workshops,
+ key=lambda x: check_workshop_type(x))
+
+ download = request.POST.get('Download')
+ if download:
+ response = HttpResponse(content_type='text/csv')
+
+ response['Content-Disposition'] = 'attachment;\
+ filename="records_from_{0}_to_{1}.csv"'.format(
+ from_dates,to_dates
+ )
+
+ writer = csv.writer(response)
+ header = [
+ 'coordinator name',
+ 'instructor name',
+ 'workshop',
+ 'date',
+ 'status',
+ 'institute name'
+ ]
+
+ writer.writerow(header)
+
+ for workshop in upcoming_workshops:
+ try:
+ row = [
+ workshop.proposed_workshop_coordinator,
+ workshop.proposed_workshop_instructor,
+ workshop.proposed_workshop_title,
+ workshop.proposed_workshop_date,
+ workshop.status,
+ workshop.proposed_workshop_coordinator.profile.institute
+ ]
+
+ except:
+ row = [
+ workshop.requested_workshop_coordinator,
+ workshop.requested_workshop_instructor,
+ workshop.requested_workshop_title,
+ workshop.requested_workshop_date,
+ workshop.status,
+ workshop.requested_workshop_coordinator.profile.institute
+ ]
+
+ writer.writerow(row)
+ return response
+ else:
+ return render(request, 'workshop_app/workshop_stats.html',
+ {
+ "upcoming_workshops": upcoming_workshops,
+ "show_workshop_stats": settings.SHOW_WORKSHOP_STATS,
+ "workshop_count": workshop_count
+ })
+ except:
+ messages.info(request, 'Please enter Valid Dates')
+
if is_instructor(user) and is_email_checked(user):
try:
#Fetches Accepted workshops which were proposed by Coordinators
proposed_workshops = ProposeWorkshopDate.objects.filter(
proposed_workshop_date__range=(today, upto),
status='ACCEPTED'
- )
- proposed_workshops = (sorted(proposed_workshops,
- key=lambda x: datetime.strftime(
- x.proposed_workshop_date, '%d-%m-%Y'
- )))
- #Fetches Accepted workshops which were Accepted by Instructors based on their Availability
+ )
+
+ #Fetches Accepted workshops which were Accepted by
+ # Instructors based on their Availability
requested_workshops = RequestedWorkshop.objects.filter(
requested_workshop_date__range=(today, upto),
status='ACCEPTED'
)
- requested_workshops = (sorted(requested_workshops,
- key=lambda x: datetime.strftime(
- x.request_workshop_date, '%d-%m-%Y'
- )))
+
+ upcoming_workshops = []
+ for workshop in proposed_workshops:
+ upcoming_workshops.append(workshop)
+
+ for workshop in requested_workshops:
+ upcoming_workshops.append(workshop)
+ upcoming_workshops = sorted(upcoming_workshops,
+ key=lambda x: check_workshop_type(x))
+
except:
- proposed_workshops = None
- requested_workshops = None
- return render(request, 'workshop_app/scheduled_workshops.html',
+ upcoming_workshops = None
+
+ paginator = Paginator(upcoming_workshops, 12)
+
+ page = request.GET.get('page')
+ try:
+ upcoming_workshops = paginator.page(page)
+ except PageNotAnInteger:
+ #If page is not an integer, deliver first page.
+ upcoming_workshops = paginator.page(1)
+ except EmptyPage:
+ #If page is out of range(e.g 999999), deliver last page.
+ upcoming_workshops = paginator.page(paginator.num_pages)
+
+
+ return render(request, 'workshop_app/workshop_stats.html',
{
- "proposed_workshops": proposed_workshops,
- "requested_workshops": requested_workshops,
- "scheduled_workshops": settings.SCHEDULED_WORKSHOPS
+ "upcoming_workshops": upcoming_workshops,
+ "show_workshop_stats": settings.SHOW_WORKSHOP_STATS,
+ "workshop_count": workshop_count
})
else:
- redirect('/book/')
+ redirect('/manage/')