Commit 47aacc70 by Brian Talbot

Merge branch 'master' into feature/btalbot/studio-alerts

parents bc0b1b09 999ed17e
......@@ -21,18 +21,26 @@ class Command(BaseCommand):
'''Delete a MongoDB backed course'''
def handle(self, *args, **options):
if len(args) != 1:
raise CommandError("delete_course requires one argument: <location>")
if len(args) != 1 and len(args) != 2:
raise CommandError("delete_course requires one or more arguments: <location> |commit|")
loc_str = args[0]
commit = False
if len(args) == 2:
commit = args[1] == 'commit'
if commit:
print 'Actually going to delete the course from DB....'
ms = modulestore('direct')
cs = contentstore()
if query_yes_no("Deleting course {0}. Confirm?".format(loc_str), default="no"):
if query_yes_no("Are you sure. This action cannot be undone!", default="no"):
loc = CourseDescriptor.id_to_location(loc_str)
if delete_course(ms, cs, loc) == True:
if delete_course(ms, cs, loc, commit) == True:
print 'removing User permissions from course....'
# in the django layer, we need to remove all the user permissions groups associated with this course
_delete_course_group(loc)
if commit:
_delete_course_group(loc)
......@@ -171,7 +171,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012')
delete_course(ms, cs, location)
delete_course(ms, cs, location, commit=True)
items = ms.get_items(Location(['i4x', 'edX', 'full', 'vertical', None]))
self.assertEqual(len(items), 0)
......@@ -465,7 +465,9 @@ class ContentStoreTest(ModuleStoreTestCase):
# check for grace period definition which should be defined at the course level
self.assertIn('graceperiod', new_module.metadata)
self.assertEqual(course.metadata['graceperiod'], new_module.metadata['graceperiod'])
self.assertEqual(parent.metadata['graceperiod'], new_module.metadata['graceperiod'])
self.assertEqual(course.metadata['xqa_key'], new_module.metadata['xqa_key'])
#
# now let's define an override at the leaf node level
......
......@@ -80,10 +80,15 @@ def get_lms_link_for_item(location, preview=False, course_id=None):
course_id = get_course_id(location)
if settings.LMS_BASE is not None:
lms_link = "//{preview}{lms_base}/courses/{course_id}/jump_to/{location}".format(
preview='preview.' if preview else '',
lms_base=settings.LMS_BASE,
course_id= course_id,
if preview:
lms_base = settings.MITX_FEATURES.get('PREVIEW_LMS_BASE',
'preview.' + settings.LMS_BASE)
else:
lms_base = settings.LMS_BASE
lms_link = "//{lms_base}/courses/{course_id}/jump_to/{location}".format(
lms_base=lms_base,
course_id=course_id,
location=Location(location)
)
else:
......
......@@ -320,8 +320,11 @@ def edit_unit(request, location):
break
index = index + 1
preview_lms_link = '//{preview}{lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}'.format(
preview='preview.',
preview_lms_base = settings.MITX_FEATURES.get('PREVIEW_LMS_BASE',
'preview.' + settings.LMS_BASE)
preview_lms_link = '//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}'.format(
preview_lms_base=preview_lms_base,
lms_base=settings.LMS_BASE,
org=course.location.org,
course=course.location.course,
......
......@@ -172,6 +172,9 @@ LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identi
USE_I18N = True
USE_L10N = True
# Tracking
TRACK_MAX_EVENT = 10000
# Messages
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
......@@ -275,6 +278,10 @@ INSTALLED_APPS = (
'auth',
'student', # misleading name due to sharing with lms
'course_groups', # not used in cms (yet), but tests run
# tracking
'track',
# For asset pipelining
'pipeline',
'staticfiles',
......
......@@ -97,7 +97,7 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({
}
var newVal = new Date(date.getTime() + time * 1000);
if (!cacheModel.has(fieldName) || cacheModel.get(fieldName).getTime() !== newVal.getTime()) {
cacheModel.save(fieldName, newVal, { error: CMS.ServerError});
cacheModel.save(fieldName, newVal);
}
}
};
......
......@@ -90,8 +90,7 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({
setGracePeriod : function(event) {
event.data.clearValidationErrors();
var newVal = event.data.model.dateToGracePeriod($(event.currentTarget).timepicker('getTime'));
if (event.data.model.get('grace_period') != newVal) event.data.model.save('grace_period', newVal,
{ error : CMS.ServerError});
if (event.data.model.get('grace_period') != newVal) event.data.model.save('grace_period', newVal);
},
updateModel : function(event) {
if (!this.selectorToField[event.currentTarget.id]) return;
......@@ -227,8 +226,7 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({
object[cutoff['designation']] = cutoff['cutoff'] / 100.0;
return object;
},
{}),
{ error : CMS.ServerError});
{}));
},
addNewGrade: function(e) {
......
<form class="choicegroup capa_inputtype" id="inputtype_${id}">
<div class="indicator_container">
% if status == 'unsubmitted':
<span class="unanswered" style="display:inline-block;" id="status_${id}"></span>
% elif status == 'correct':
<span class="correct" id="status_${id}"></span>
% elif status == 'incorrect':
<span class="incorrect" id="status_${id}"></span>
% elif status == 'incomplete':
<span class="incorrect" id="status_${id}"></span>
% endif
</div>
<fieldset>
% for choice_id, choice_description in choices:
<label for="input_${id}_${choice_id}"> <input type="${input_type}" name="input_${id}${name_array_suffix}" id="input_${id}_${choice_id}" value="${choice_id}"
<label for="input_${id}_${choice_id}">
% if choice_id in value:
<span class="indicator_container">
% if status == 'unsubmitted':
<span class="unanswered" style="display:inline-block;" id="status_${id}"></span>
% elif status == 'correct':
<span class="correct" id="status_${id}"></span>
% elif status == 'incorrect':
<span class="incorrect" id="status_${id}"></span>
% elif status == 'incomplete':
<span class="incorrect" id="status_${id}"></span>
% endif
</span>
% else:
<span class="indicator_container">&#160;</span>
% endif
<input type="${input_type}" name="input_${id}${name_array_suffix}" id="input_${id}_${choice_id}" value="${choice_id}"
% if choice_id in value:
checked="true"
% endif
/> ${choice_description} </label>
/>
${choice_description}
</label>
% endfor
<span id="answer_${id}"></span>
</fieldset>
......
......@@ -227,7 +227,7 @@ section.problem {
background: url('../images/correct-icon.png') center center no-repeat;
height: 20px;
position: relative;
top: 6px;
top: 3px;
width: 25px;
}
......@@ -237,7 +237,7 @@ section.problem {
height: 20px;
width: 20px;
position: relative;
top: 6px;
top: 3px;
}
}
......
......@@ -92,7 +92,7 @@ def clone_course(modulestore, contentstore, source_location, dest_location, dele
return True
def delete_course(modulestore, contentstore, source_location):
def delete_course(modulestore, contentstore, source_location, commit = False):
# first check to see if the modulestore is Mongo backed
if not isinstance(modulestore, MongoModuleStore):
raise Exception("Expected a MongoModuleStore in the runtime. Aborting....")
......@@ -107,7 +107,8 @@ def delete_course(modulestore, contentstore, source_location):
thumb_loc = Location(thumb["_id"])
id = StaticContent.get_id_from_location(thumb_loc)
print "Deleting {0}...".format(id)
contentstore.delete(id)
if commit:
contentstore.delete(id)
# then delete all of the assets
assets = contentstore.get_all_content_for_course(source_location)
......@@ -115,7 +116,8 @@ def delete_course(modulestore, contentstore, source_location):
asset_loc = Location(asset["_id"])
id = StaticContent.get_id_from_location(asset_loc)
print "Deleting {0}...".format(id)
contentstore.delete(id)
if commit:
contentstore.delete(id)
# then delete all course modules
modules = modulestore.get_items([source_location.tag, source_location.org, source_location.course, None, None, None])
......@@ -123,10 +125,12 @@ def delete_course(modulestore, contentstore, source_location):
for module in modules:
if module.category != 'course': # save deleting the course module for last
print "Deleting {0}...".format(module.location)
modulestore.delete_item(module.location)
if commit:
modulestore.delete_item(module.location)
# finally delete the top-level course module itself
print "Deleting {0}...".format(source_location)
modulestore.delete_item(source_location)
if commit:
modulestore.delete_item(source_location)
return True
......@@ -79,7 +79,7 @@ if Backbone?
#determined in the coffeescript based on whether or not there's a
#group id
if response.is_cohorted
if response.is_cohorted and response.is_moderator
source = "script#_inline_discussion_cohorted"
else
source = "script#_inline_discussion"
......
......@@ -96,24 +96,25 @@ def create_thread(request, course_id, commentable_id):
#kevinchugh because the new requirement is that all groups will be determined
#by the group id in the request this all goes away
#not anymore, only for admins
# Cohort the thread if the commentable is cohorted.
#if is_commentable_cohorted(course_id, commentable_id):
# user_group_id = get_cohort_id(user, course_id)
if is_commentable_cohorted(course_id, commentable_id):
user_group_id = get_cohort_id(user, course_id)
# TODO (vshnayder): once we have more than just cohorts, we'll want to
# change this to a single get_group_for_user_and_commentable function
# that can do different things depending on the commentable_id
# if cached_has_permission(request.user, "see_all_cohorts", course_id):
if cached_has_permission(request.user, "see_all_cohorts", course_id):
# admins can optionally choose what group to post as
# group_id = post.get('group_id', user_group_id)
# else:
group_id = post.get('group_id', user_group_id)
else:
# regular users always post with their own id.
# group_id = user_group_id
group_id = post.get('group_id')
group_id = user_group_id
if group_id:
thread.update_attributes(group_id=group_id)
log.debug("Saving thread %r", thread.attributes)
thread.save()
if post.get('auto_subscribe', 'false').lower() == 'true':
......
......@@ -133,32 +133,23 @@ def inline_discussion(request, course_id, discussion_id):
#if the commentable is cohorted, otherwise everything is not cohorted
#and no one has the option of choosing a cohort
is_cohorted = is_course_cohorted(course_id) and is_commentable_cohorted(course_id, discussion_id)
is_moderator = cached_has_permission(request.user, "see_all_cohorts", course_id)
cohorts_list = list()
if is_cohorted:
cohorts_list.append({'name':'All Groups','id':None})
#if you're a mod, send all cohorts and let you pick
if cached_has_permission(request.user, "see_all_cohorts", course_id):
if is_moderator:
cohorts = get_course_cohorts(course_id)
for c in cohorts:
cohorts_list.append({'name':c.name, 'id':c.id})
else:
#otherwise, just make a dictionary of two
user_cohort = get_cohort(cc_user, course_id)
if user_cohort:
user_cohort_name = user_cohort.name
user_cohort_id = user_cohort.id
else:
user_cohort_name = user_cohort_id = None
if user_cohort:
cohorts_list.append({'name':user_cohort_name, 'id':user_cohort_id})
else:
cohorts_list = None
#students don't get to choose
cohorts_list = None
return utils.JsonResponse({
'discussion_data': map(utils.safe_content, threads),
......@@ -170,6 +161,7 @@ def inline_discussion(request, course_id, discussion_id):
'allow_anonymous_to_peers': allow_anonymous_to_peers,
'allow_anonymous': allow_anonymous,
'cohorts': cohorts_list,
'is_moderator': is_moderator,
'is_cohorted': is_cohorted
})
......
......@@ -46,21 +46,18 @@
%elif course.metadata.get("allow_anonymous_to_peers", False):
<input type="checkbox" name="anonymous_to_peers" class="discussion-anonymous-to-peers" id="new-post-anonymous-to-peers"><label for="new-post-anonymous-to-peers">post anonymously to classmates</label>
%endif
%if is_course_cohorted:
%if is_course_cohorted and is_moderator:
<div class="form-group-label choose-cohort">
Make visible to:
<select class="group-filter-select new-post-group" name = "group_id">
<option value="">All Groups</option>
%if is_moderator:
%for c in cohorts:
<option value="${c.id}">${c.name}</option>
%endfor
%else:
%if user_cohort:
<option value="${user_cohort}">My Cohort</option>
%for c in cohorts:
<option value="${c.id}"
%if user_cohort and str(user_cohort) == str(c.id):
selected
%endif
%endif
>${c.name}</option>
%endfor
</select>
</div>
%endif
......
......@@ -415,7 +415,10 @@ end
namespace :cms do
desc "Delete existing MongoDB based course"
task :delete_course do
if ENV['LOC']
if ENV['LOC'] and ENV['COMMIT']
sh(django_admin(:cms, :dev, :delete_course, ENV['LOC'], ENV['COMMIT']))
elsif ENV['LOC']
sh(django_admin(:cms, :dev, :delete_course, ENV['LOC']))
else
raise "You must pass in a LOC parameter"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment