Add initial set of views for managing cohorts
- lets user see and add cohorts - needs styling - needs to allow them to actually manage membership!
This commit is contained in:
committed by
Victor Shnayder
parent
ac8c59126d
commit
bab3b0c39e
@@ -1,6 +1,10 @@
|
||||
import logging
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class CourseUserGroup(models.Model):
|
||||
"""
|
||||
This model represents groups of users in a course. Groups may have different types,
|
||||
@@ -27,7 +31,6 @@ class CourseUserGroup(models.Model):
|
||||
GROUP_TYPE_CHOICES = ((COHORT, 'Cohort'),)
|
||||
group_type = models.CharField(max_length=20, choices=GROUP_TYPE_CHOICES)
|
||||
|
||||
|
||||
def get_cohort(user, course_id):
|
||||
"""
|
||||
Given a django User and a course_id, return the user's cohort. In classes with
|
||||
@@ -65,3 +68,49 @@ def get_course_cohorts(course_id):
|
||||
"""
|
||||
return list(CourseUserGroup.objects.filter(course_id=course_id,
|
||||
group_type=CourseUserGroup.COHORT))
|
||||
|
||||
### Helpers for cohor management views
|
||||
|
||||
def get_cohort_by_name(course_id, name):
|
||||
"""
|
||||
Return the CourseUserGroup object for the given cohort. Raises DoesNotExist
|
||||
it isn't present.
|
||||
"""
|
||||
return CourseUserGroup.objects.get(course_id=course_id,
|
||||
group_type=CourseUserGroup.COHORT,
|
||||
name=name)
|
||||
|
||||
def add_cohort(course_id, name):
|
||||
"""
|
||||
Add a cohort to a course. Raises ValueError if a cohort of the same name already
|
||||
exists.
|
||||
"""
|
||||
log.debug("Adding cohort %s to %s", name, course_id)
|
||||
if CourseUserGroup.objects.filter(course_id=course_id,
|
||||
group_type=CourseUserGroup.COHORT,
|
||||
name=name).exists():
|
||||
raise ValueError("Can't create two cohorts with the same name")
|
||||
|
||||
return CourseUserGroup.objects.create(course_id=course_id,
|
||||
group_type=CourseUserGroup.COHORT,
|
||||
name=name)
|
||||
|
||||
def get_course_cohort_names(course_id):
|
||||
"""
|
||||
Return a list of the cohort names in a course.
|
||||
"""
|
||||
return [c.name for c in get_course_cohorts(course_id)]
|
||||
|
||||
|
||||
def delete_empty_cohort(course_id, name):
|
||||
"""
|
||||
Remove an empty cohort. Raise ValueError if cohort is not empty.
|
||||
"""
|
||||
cohort = get_cohort_by_name(course_id, name)
|
||||
if cohort.users.exists():
|
||||
raise ValueError(
|
||||
"Can't delete non-empty cohort {0} in course {1}".format(
|
||||
name, course_id))
|
||||
|
||||
cohort.delete()
|
||||
|
||||
|
||||
108
common/djangoapps/course_groups/views.py
Normal file
108
common/djangoapps/course_groups/views.py
Normal file
@@ -0,0 +1,108 @@
|
||||
import json
|
||||
from django_future.csrf import ensure_csrf_cookie
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.context_processors import csrf
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, HttpResponseForbidden, Http404
|
||||
from django.shortcuts import redirect
|
||||
import logging
|
||||
|
||||
from courseware.courses import get_course_with_access
|
||||
from mitxmako.shortcuts import render_to_response, render_to_string
|
||||
from .models import CourseUserGroup
|
||||
from . import models
|
||||
|
||||
import track.views
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def JsonHttpReponse(data):
|
||||
"""
|
||||
Return an HttpResponse with the data json-serialized and the right content type
|
||||
header. Named to look like a class.
|
||||
"""
|
||||
return HttpResponse(json.dumps(data), content_type="application/json")
|
||||
|
||||
@ensure_csrf_cookie
|
||||
def list_cohorts(request, course_id):
|
||||
"""
|
||||
Return json dump of dict:
|
||||
|
||||
{'success': True,
|
||||
'cohorts': [{'name': name, 'id': id}, ...]}
|
||||
"""
|
||||
get_course_with_access(request.user, course_id, 'staff')
|
||||
|
||||
cohorts = [{'name': c.name, 'id': c.id}
|
||||
for c in models.get_course_cohorts(course_id)]
|
||||
|
||||
return JsonHttpReponse({'success': True,
|
||||
'cohorts': cohorts})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
def add_cohort(request, course_id):
|
||||
"""
|
||||
Return json of dict:
|
||||
{'success': True,
|
||||
'cohort': {'id': id,
|
||||
'name': name}}
|
||||
|
||||
or
|
||||
|
||||
{'success': False,
|
||||
'msg': error_msg} if there's an error
|
||||
"""
|
||||
get_course_with_access(request.user, course_id, 'staff')
|
||||
|
||||
|
||||
if request.method != "POST":
|
||||
raise Http404("Must POST to add cohorts")
|
||||
|
||||
name = request.POST.get("name")
|
||||
if not name:
|
||||
return JsonHttpReponse({'success': False,
|
||||
'msg': "No name specified"})
|
||||
|
||||
try:
|
||||
cohort = models.add_cohort(course_id, name)
|
||||
except ValueError as err:
|
||||
return JsonHttpReponse({'success': False,
|
||||
'msg': str(err)})
|
||||
|
||||
return JsonHttpReponse({'success': 'True',
|
||||
'cohort': {
|
||||
'id': cohort.id,
|
||||
'name': cohort.name
|
||||
}})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
def users_in_cohort(request, course_id, cohort_id):
|
||||
"""
|
||||
"""
|
||||
get_course_with_access(request.user, course_id, 'staff')
|
||||
|
||||
return JsonHttpReponse({'error': 'Not implemented'})
|
||||
|
||||
|
||||
@ensure_csrf_cookie
|
||||
def add_users_to_cohort(request, course_id):
|
||||
"""
|
||||
"""
|
||||
get_course_with_access(request.user, course_id, 'staff')
|
||||
|
||||
return JsonHttpReponse({'error': 'Not implemented'})
|
||||
|
||||
|
||||
def debug_cohort_mgmt(request, course_id):
|
||||
"""
|
||||
Debugging view for dev.
|
||||
"""
|
||||
# add staff check to make sure it's safe if it's accidentally deployed.
|
||||
get_course_with_access(request.user, course_id, 'staff')
|
||||
|
||||
context = {'cohorts_ajax_url': reverse('cohorts',
|
||||
kwargs={'course_id': course_id})}
|
||||
return render_to_response('/course_groups/debug.html', context)
|
||||
118
common/static/js/course_groups/cohorts.js
Normal file
118
common/static/js/course_groups/cohorts.js
Normal file
@@ -0,0 +1,118 @@
|
||||
// structure stolen from http://briancray.com/posts/javascript-module-pattern
|
||||
|
||||
var CohortManager = (function ($) {
|
||||
// private variables and functions
|
||||
|
||||
// using jQuery
|
||||
function getCookie(name) {
|
||||
var cookieValue = null;
|
||||
if (document.cookie && document.cookie != '') {
|
||||
var cookies = document.cookie.split(';');
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var cookie = $.trim(cookies[i]);
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
var csrftoken = getCookie('csrftoken');
|
||||
|
||||
function csrfSafeMethod(method) {
|
||||
// these HTTP methods do not require CSRF protection
|
||||
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
|
||||
}
|
||||
$.ajaxSetup({
|
||||
crossDomain: false, // obviates need for sameOrigin test
|
||||
beforeSend: function(xhr, settings) {
|
||||
if (!csrfSafeMethod(settings.type)) {
|
||||
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// constructor
|
||||
var module = function () {
|
||||
var url = $(".cohort_manager").data('ajax_url');
|
||||
var self = this;
|
||||
var error_list = $(".cohort_errors");
|
||||
var cohort_list = $(".cohort_list");
|
||||
var cohorts_display = $(".cohorts_display");
|
||||
var show_cohorts_button = $(".cohort_controls .show_cohorts");
|
||||
var add_cohort_input = $("#cohort-name");
|
||||
var add_cohort_button = $(".add_cohort");
|
||||
|
||||
function show_cohort(item) {
|
||||
// item is a li that has a data-href link to the cohort base url
|
||||
var el = $(this);
|
||||
alert("would show you data about " + el.text() + " from " + el.data('href'));
|
||||
}
|
||||
|
||||
function add_to_cohorts_list(item) {
|
||||
var li = $('<li><a></a></li>');
|
||||
$("a", li).text(item.name)
|
||||
.data('href', url + '/' + item.id)
|
||||
.addClass('link')
|
||||
.click(show_cohort);
|
||||
cohort_list.append(li);
|
||||
};
|
||||
|
||||
function log_error(msg) {
|
||||
error_list.empty();
|
||||
error_list.append($("<li />").text(msg).addClass("error"));
|
||||
};
|
||||
|
||||
function load_cohorts(response) {
|
||||
cohort_list.empty();
|
||||
if (response && response.success) {
|
||||
response.cohorts.forEach(add_to_cohorts_list);
|
||||
} else {
|
||||
log_error(response.msg || "There was an error loading cohorts");
|
||||
}
|
||||
cohorts_display.show();
|
||||
};
|
||||
|
||||
function added_cohort(response) {
|
||||
if (response && response.success) {
|
||||
add_to_cohorts_list(response.cohort);
|
||||
} else {
|
||||
log_error(response.msg || "There was an error adding a cohort");
|
||||
}
|
||||
}
|
||||
|
||||
show_cohorts_button.click(function() {
|
||||
$.ajax(url).done(load_cohorts);
|
||||
});
|
||||
|
||||
add_cohort_input.change(function() {
|
||||
if (!$(this).val()) {
|
||||
add_cohort_button.removeClass('button').addClass('button-disabled');
|
||||
} else {
|
||||
add_cohort_button.removeClass('button-disabled').addClass('button');
|
||||
}
|
||||
});
|
||||
|
||||
add_cohort_button.click(function() {
|
||||
var add_url = url + '/add';
|
||||
data = {'name': add_cohort_input.val()}
|
||||
$.post(add_url, data).done(added_cohort);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// prototype
|
||||
module.prototype = {
|
||||
constructor: module,
|
||||
};
|
||||
|
||||
// return module
|
||||
return module;
|
||||
})(jQuery);
|
||||
|
||||
$(window).load(function () {
|
||||
var my_module = new CohortManager();
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user