summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--statistics_app/templates/statistics_app/team_stats.html124
-rw-r--r--statistics_app/urls.py5
-rw-r--r--statistics_app/views.py26
-rw-r--r--teams/__init__.py0
-rw-r--r--teams/admin.py5
-rw-r--r--teams/apps.py5
-rw-r--r--teams/models.py9
-rw-r--r--teams/tests.py3
-rw-r--r--teams/views.py3
-rw-r--r--workshop_app/templates/workshop_app/my_workshops.html68
-rw-r--r--workshop_app/views.py58
-rw-r--r--workshop_portal/settings.py1
12 files changed, 238 insertions, 69 deletions
diff --git a/statistics_app/templates/statistics_app/team_stats.html b/statistics_app/templates/statistics_app/team_stats.html
new file mode 100644
index 0000000..4e3e870
--- /dev/null
+++ b/statistics_app/templates/statistics_app/team_stats.html
@@ -0,0 +1,124 @@
+{% extends 'workshop_app/base.html' %}
+
+{% block title %}
+ Workshop Statistics
+{% 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://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.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>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
+ <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.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>
+
+ <!-- For Google GeoChart India Map -->
+ <script type='text/javascript' src='https://www.google.com/jsapi'></script>
+
+{% endblock %}
+
+{% block content %}
+
+<div class="container">
+<div class="row">
+ <br>
+ <div class="col-md-12 ">
+ <br>
+ <canvas id="myChartPie" ></canvas>
+ <script>
+ var dynamic_pie_color = [];
+ var data = {{ workshop_data.data}};
+
+ var dynamicColors = function() {
+ var r = Math.floor(Math.random() * 255);
+ var g = Math.floor(Math.random() * 255);
+ var b = Math.floor(Math.random() * 255);
+ return "rgb(" + r + "," + g + "," + b + ")";
+ };
+
+
+ for (var i in data) {
+ dynamic_pie_color.push(dynamicColors());
+ }
+
+ var data = {
+ datasets: [{
+ data: data,
+ label: 'My dataset', // for legend
+ backgroundColor: dynamic_pie_color,
+ }],
+ labels: [{% for label in workshop_data.labels %}"{{ label }}",{% endfor %}]
+ };
+
+ var pieOptions = {
+ events: false,
+ animation: {
+ duration: 500,
+ easing: "easeOutQuart",
+ onComplete: function () {
+ var ctx = this.chart.ctx;
+ ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'bottom';
+
+ this.data.datasets.forEach(function (dataset) {
+
+ for (var i = 0; i < dataset.data.length; i++) {
+ var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
+ total = dataset._meta[Object.keys(dataset._meta)[0]].total,
+ mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
+ start_angle = model.startAngle,
+ end_angle = model.endAngle,
+ mid_angle = start_angle + (end_angle - start_angle)/2;
+
+ var x = mid_radius * Math.cos(mid_angle);
+ var y = mid_radius * Math.sin(mid_angle);
+
+ ctx.fillStyle = '#fff';
+ if (i == 3){ // Darker text color for lighter background
+ ctx.fillStyle = '#444';
+ }
+
+ var val = dataset.data[i];
+ var percent = String(Math.round(val/total*100)) + "%";
+
+ if(val != 0) {
+ ctx.fillText(dataset.data[i], model.x + x, model.y + y);
+ // Display percent in another line, line break doesn't work for fillText
+ ctx.fillText(percent, model.x + x, model.y + y + 15);
+ }
+ }
+ });
+ }
+ }
+ };
+
+ var pieChartCanvas = $("#myChartPie");
+ var pieChart = new Chart(pieChartCanvas, {
+ type: 'pie', // or doughnut
+ data: data,
+ options: pieOptions
+ });
+ </script>
+ <style>
+ #visualization path {
+ stroke-width:1; /* control the countries borders width */
+ stroke:white; /* choose a color for the border */
+ }
+ </style>
+ <div id="visualization" style="width: 400px; height: 300px; display: block; margin: 0 auto;" ></div>
+
+ </div>
+</div>
+</div>
+<br>
+{% endblock %}
diff --git a/statistics_app/urls.py b/statistics_app/urls.py
index 94b358e..9e0dbbf 100644
--- a/statistics_app/urls.py
+++ b/statistics_app/urls.py
@@ -2,12 +2,13 @@
from django.conf.urls import url
from django.contrib import admin
from statistics_app import views
-import django
-
urlpatterns = [
url(r'^statistics/$', views.workshop_stats),
url(r'^statistics/public_stats/$', views.workshop_public_stats),
url(r'^statistics/profile_stats/$', views.profile_stats),
+ url(r'^statistics/v1/team_stats/$', views.team_stats),
+ # url(r'^statistics/v1/filter/$', views.team_stats),
+ url(r'^statistics/v1/all/$', views.all_stats),
]
diff --git a/statistics_app/views.py b/statistics_app/views.py
index 1507196..8c3a6f0 100644
--- a/statistics_app/views.py
+++ b/statistics_app/views.py
@@ -10,6 +10,8 @@ from workshop_app.models import (
BookedWorkshop, ProposeWorkshopDate,
Testimonial
)
+from teams.models import Team
+
from django.template.loader import get_template
from django.template import RequestContext
from datetime import datetime, date
@@ -582,3 +584,27 @@ def profile_stats(request):
else:
logout(request)
return render(request, "workshop_app/logout.html")
+
+@login_required
+def team_stats(request, team_id):
+ user = request.user
+ team = Team.objects.get(team_id)
+ if user not in team.members.all():
+ if user.groups.filter(name='instructor').count() > 0:
+ return redirect('/manage/')
+ return redirect('/book/')
+
+ member_workshop_data = {}
+ for member in team.members.all():
+ workshop_count = ProposeWorkshopDate.objects.filter(proposed_workshop_instructor=member.id).count()
+ if member_workshop_data.get('data'):
+ member_workshop_data['data'].append(workshop_count)
+ else:
+ member_workshop_data['data'] = [workshop_count]
+ if member_workshop_data.get('labels'):
+ member_workshop_data['labels'].append(member.user.username)
+ else:
+ member_workshop_data['labels'] = [member.user.username]
+ return render(request, 'statistics_app/team_stats.html', {'workshop_data': member_workshop_data})
+
+
diff --git a/teams/__init__.py b/teams/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/teams/__init__.py
diff --git a/teams/admin.py b/teams/admin.py
new file mode 100644
index 0000000..1653090
--- /dev/null
+++ b/teams/admin.py
@@ -0,0 +1,5 @@
+from django.contrib import admin
+
+from teams.models import Team
+
+admin.site.register(Team)
diff --git a/teams/apps.py b/teams/apps.py
new file mode 100644
index 0000000..17954d6
--- /dev/null
+++ b/teams/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class TeamsConfig(AppConfig):
+ name = 'teams'
diff --git a/teams/models.py b/teams/models.py
new file mode 100644
index 0000000..c82a92c
--- /dev/null
+++ b/teams/models.py
@@ -0,0 +1,9 @@
+from django.db import models
+from django.contrib.auth.models import User
+
+from workshop_app.models import Profile
+
+class Team(models.Model):
+ members = models.ManyToManyField(Profile)
+ creator = models.OneToOneField(User)
+ created_date = models.DateTimeField(auto_now=True) \ No newline at end of file
diff --git a/teams/tests.py b/teams/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/teams/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/teams/views.py b/teams/views.py
new file mode 100644
index 0000000..91ea44a
--- /dev/null
+++ b/teams/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/workshop_app/templates/workshop_app/my_workshops.html b/workshop_app/templates/workshop_app/my_workshops.html
index 846c11b..ba35757 100644
--- a/workshop_app/templates/workshop_app/my_workshops.html
+++ b/workshop_app/templates/workshop_app/my_workshops.html
@@ -119,12 +119,44 @@
{% block content %}
-{% if workshop_occurences %}
+{% if workshops %}
<h3 align="center" style="color:#2952a2;">The status of your workshops </h3>
<br>
<!-- Pending View -->
<div class="container">
+ {% if request.user.profile.position == 'instructor'%}
+ <h3 align="center" style="color: #04a9cf;"><strong><u>Team Member Requests</u></strong></h3>
+
+ <table class="table">
+ <thead>
+ <tr>
+ <th>Coordinator Name</th>
+ <th>Team Member</th>
+ <th>Workshop Name</th>
+ <th>Workshop Day</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for workshop in team_workshops %}
+ <tr>
+ <td><a href="{{ URL_ROOT }}/view_comment_profile/{{ workshop.requested_workshop_coordinator.profile.user.id }}">
+ {{ workshop.proposed_workshop_coordinator.get_full_name }}</a>
+ </td>
+ <td>
+ {{ workshop.proposed_workshop_instructor.get_full_name }}
+ </td>
+ <td>
+ {{ workshop.proposed_workshop_title }}
+ </td>
+ <td>
+ {{ workshop.proposed_workshop_date | date }}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
{% if request.user.profile.position == 'instructor' %}
<h3 align="center" style="color: #04a9cf;"><strong><u>Requests for Me</u></strong></h3>
{% else %}
@@ -144,7 +176,7 @@
</tr>
</thead>
{% csrf_token %}
- {% for workshop in workshop_occurences %}
+ {% for workshop in workshops %}
<tbody>
<tr>
{% if workshop.status == 'Pending' and workshop.requested_workshop_instructor %}
@@ -186,7 +218,7 @@
</tr>
</thead>
{% csrf_token %}
- {% for workshop in workshop_occurences %}
+ {% for workshop in workshops %}
<tbody>
<tr>
{% if workshop.status == 'ACCEPTED' and workshop.requested_workshop_title %}
@@ -271,7 +303,7 @@
</tr>
</thead>
{% csrf_token %}
- {% for workshop in workshop_occurences %}
+ {% for workshop in workshops %}
<tbody>
<tr>
{% if workshop.status == 'Pending' and workshop.condition_one %}
@@ -314,7 +346,7 @@
</tr>
</thead>
{% csrf_token %}
- {% for workshop in workshop_occurences %}
+ {% for workshop in workshops %}
<tbody>
<tr>
{% if workshop.status == 'DELETED' or workshop.status == 'REJECTED' %}
@@ -335,32 +367,6 @@
</table>
</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 workshop_occurences.has_previous %}
- <a class="page-link" tabindex="-1"
- href="?page={{ workshop_occurences.previous_page_number }}">Previous</a>
- {% endif %}
- </li>
- <li class="page-item">
- <span class="current">
- Page {{ workshop_occurences.number }} of {{ workshop_occurences.paginator.num_pages }}
- </span>
- </li>
- <li class="page-item">
- {% if workshop_occurences.has_next %}
- <a class="page-link" href="?page={{ workshop_occurences.next_page_number }}">Next
- </a>
- {% endif %}
- </li>
- </ul>
- </nav>
- </div>
- </div>
{% else %}
{% if request.user.profile.position == 'instructor' %}
diff --git a/workshop_app/views.py b/workshop_app/views.py
index 961445a..772615b 100644
--- a/workshop_app/views.py
+++ b/workshop_app/views.py
@@ -10,6 +10,7 @@ from .models import (
BookedWorkshop, ProposeWorkshopDate,
Testimonial, ProfileComments
)
+from teams.models import Team
from datetime import datetime, date
from django.contrib.auth import login, logout, authenticate
from django.contrib.auth.decorators import login_required
@@ -658,38 +659,36 @@ def my_workshops(request):
today = datetime.today().date()
workshop_occurence_list = RequestedWorkshop.objects.filter(
requested_workshop_instructor=user.id,
- requested_workshop_date__gt=today,
+ requested_workshop_date__gte=today,
).order_by('-requested_workshop_date')
- for w in workshop_occurence_list:
- workshops.append(w)
proposed_workshop = ProposeWorkshopDate.objects.filter(
proposed_workshop_instructor=user.id,
- proposed_workshop_date__gt=today,
+ proposed_workshop_date__gte=today,
).order_by('-proposed_workshop_date')
- for p in proposed_workshop:
- workshops.append(p)
proposed_workshop_pending = ProposeWorkshopDate.objects.filter(
status='Pending'
).order_by('-proposed_workshop_date')
- for p in proposed_workshop_pending:
- workshops.append(p)
+ workshops = list(workshop_occurence_list) + list(proposed_workshop) + list(proposed_workshop_pending)
+
+ # team_members = list(set(user.profile.team_set.all().values_list('members', flat=True)))
+ teams = Team.objects.filter(members=user.profile)
+ team_workshops = []
+
+ if teams:
+ team_members = Profile.objects.filter(team__in=teams).exclude(id=user.profile.id).distinct()
+ team_member_ids = team_members.values_list('user__id')
+ team_workshops = ProposeWorkshopDate.objects.filter(
+ proposed_workshop_date__gte=today,
+ proposed_workshop_instructor_id__in=team_member_ids,
+ )
+ print(team_workshops)
- #Show upto 12 Workshops per page
- paginator = Paginator(workshops, 12)
- page = request.GET.get('page')
- try:
- workshop_occurences = paginator.page(page)
- except PageNotAnInteger:
- #If page is not an integer, deliver first page.
- workshop_occurences = paginator.page(1)
- except EmptyPage:
- #If page is out of range(e.g 999999), deliver last page.
- workshop_occurences = paginator.page(paginator.num_pages)
return render(request, 'workshop_app/my_workshops.html',
- { "workshop_occurences" :workshop_occurences,
+ { "workshops" :workshops,
+ "team_workshops": team_workshops,
"today": today})
else:
@@ -697,28 +696,15 @@ def my_workshops(request):
workshop_occurence_list = RequestedWorkshop.objects.filter(
requested_workshop_coordinator=user.id
).order_by('-requested_workshop_date')
- for w in workshop_occurence_list:
- workshops.append(w)
proposed_workshop = ProposeWorkshopDate.objects.filter(
proposed_workshop_coordinator=user.id
).order_by('-proposed_workshop_date')
- for p in proposed_workshop:
- workshops.append(p)
- #Show upto 12 Workshops per page
- paginator = Paginator(workshops, 12)
- page = request.GET.get('page')
- try:
- workshop_occurences = paginator.page(page)
- except PageNotAnInteger:
- #If page is not an integer, deliver first page.
- workshop_occurences = paginator.page(1)
- except EmptyPage:
- #If page is out of range(e.g 999999), deliver last page.
- workshop_occurences = paginator.page(paginator.num_pages)
+ workshops = list(workshop_occurence_list) + list(proposed_workshop) + list(proposed_workshop_pending)
+
return render(request, 'workshop_app/my_workshops.html',
- {"workshop_occurences": workshop_occurences})
+ {"workshops": workshops})
else:
return redirect('/login/')
diff --git a/workshop_portal/settings.py b/workshop_portal/settings.py
index e7f9adb..46dc9b7 100644
--- a/workshop_portal/settings.py
+++ b/workshop_portal/settings.py
@@ -48,6 +48,7 @@ INSTALLED_APPS = [
'workshop_app',
'recurrence',
'statistics_app',
+ 'teams',
]
MIDDLEWARE_CLASSES = [