Adds in radio button patch request and text for page
EDUCATOR-229
This commit is contained in:
@@ -63,25 +63,10 @@ class CourseCohortSettingsFactory(DjangoModelFactory):
|
||||
always_cohort_inline_discussions = False
|
||||
|
||||
|
||||
def topic_name_to_id(course, name):
|
||||
"""
|
||||
Given a discussion topic name, return an id for that name (includes
|
||||
course and url_name).
|
||||
"""
|
||||
return "{course}_{run}_{name}".format(
|
||||
course=course.location.course,
|
||||
run=course.url_name,
|
||||
name=name
|
||||
)
|
||||
|
||||
|
||||
def config_course_cohorts_legacy(
|
||||
course,
|
||||
discussions,
|
||||
cohorted,
|
||||
cohorted_discussions=None,
|
||||
auto_cohort_groups=None,
|
||||
always_cohort_inline_discussions=None
|
||||
auto_cohort_groups=None
|
||||
):
|
||||
"""
|
||||
Given a course with no discussion set up, add the discussions and set
|
||||
@@ -93,39 +78,19 @@ def config_course_cohorts_legacy(
|
||||
|
||||
Arguments:
|
||||
course: CourseDescriptor
|
||||
discussions: list of topic names strings. Picks ids and sort_keys
|
||||
automatically.
|
||||
cohorted: bool.
|
||||
cohorted_discussions: optional list of topic names. If specified,
|
||||
converts them to use the same ids as topic names.
|
||||
auto_cohort_groups: optional list of strings
|
||||
(names of groups to put students into).
|
||||
|
||||
Returns:
|
||||
Nothing -- modifies course in place.
|
||||
"""
|
||||
def to_id(name):
|
||||
"""
|
||||
Helper method to convert a discussion topic name to a database identifier
|
||||
"""
|
||||
return topic_name_to_id(course, name)
|
||||
|
||||
topics = dict((name, {"sort_key": "A",
|
||||
"id": to_id(name)})
|
||||
for name in discussions)
|
||||
|
||||
course.discussion_topics = topics
|
||||
course.discussion_topics = {}
|
||||
|
||||
config = {"cohorted": cohorted}
|
||||
if cohorted_discussions is not None:
|
||||
config["cohorted_discussions"] = [to_id(name)
|
||||
for name in cohorted_discussions]
|
||||
if auto_cohort_groups is not None:
|
||||
config["auto_cohort_groups"] = auto_cohort_groups
|
||||
|
||||
if always_cohort_inline_discussions is not None:
|
||||
config["always_cohort_inline_discussions"] = always_cohort_inline_discussions
|
||||
|
||||
course.cohort_config = config
|
||||
|
||||
try:
|
||||
@@ -135,53 +100,11 @@ def config_course_cohorts_legacy(
|
||||
pass
|
||||
|
||||
|
||||
# pylint: disable=dangerous-default-value
|
||||
def config_course_discussions(
|
||||
course,
|
||||
discussion_topics={},
|
||||
divided_discussions=[],
|
||||
always_divide_inline_discussions=False
|
||||
):
|
||||
"""
|
||||
Set discussions and configure divided discussions for a course.
|
||||
|
||||
Arguments:
|
||||
course: CourseDescriptor
|
||||
discussion_topics (Dict): Discussion topic names. Picks ids and
|
||||
sort_keys automatically.
|
||||
divided_discussions: Discussion topics to divide. Converts the
|
||||
list to use the same ids as discussion topic names.
|
||||
always_divide_inline_discussions (bool): Whether inline discussions
|
||||
should be divided by default.
|
||||
|
||||
Returns:
|
||||
Nothing -- modifies course in place.
|
||||
"""
|
||||
|
||||
def to_id(name):
|
||||
"""Convert name to id."""
|
||||
return topic_name_to_id(course, name)
|
||||
|
||||
set_course_discussion_settings(
|
||||
course.id,
|
||||
divided_discussions=[to_id(name) for name in divided_discussions],
|
||||
always_divide_inline_discussions=always_divide_inline_discussions,
|
||||
division_scheme=CourseDiscussionSettings.COHORT,
|
||||
)
|
||||
|
||||
course.discussion_topics = dict((name, {"sort_key": "A", "id": to_id(name)})
|
||||
for name in discussion_topics)
|
||||
try:
|
||||
# Not implemented for XMLModulestore, which is used by test_cohorts.
|
||||
modulestore().update_item(course, ModuleStoreEnum.UserID.test)
|
||||
except NotImplementedError:
|
||||
pass
|
||||
|
||||
|
||||
# pylint: disable=dangerous-default-value
|
||||
def config_course_cohorts(
|
||||
course,
|
||||
is_cohorted,
|
||||
discussion_division_scheme=CourseDiscussionSettings.COHORT,
|
||||
auto_cohorts=[],
|
||||
manual_cohorts=[],
|
||||
):
|
||||
@@ -191,6 +114,8 @@ def config_course_cohorts(
|
||||
Arguments:
|
||||
course: CourseDescriptor
|
||||
is_cohorted (bool): Is the course cohorted?
|
||||
discussion_division_scheme (String): the division scheme for discussions. Default is
|
||||
CourseDiscussionSettings.COHORT.
|
||||
auto_cohorts (list): Names of auto cohorts to create.
|
||||
manual_cohorts (list): Names of manual cohorts to create.
|
||||
|
||||
@@ -201,7 +126,7 @@ def config_course_cohorts(
|
||||
set_course_cohorted(course.id, is_cohorted)
|
||||
set_course_discussion_settings(
|
||||
course.id,
|
||||
division_scheme=CourseDiscussionSettings.COHORT,
|
||||
division_scheme=discussion_division_scheme,
|
||||
)
|
||||
|
||||
for cohort_name in auto_cohorts:
|
||||
|
||||
@@ -350,7 +350,6 @@ class TestCohorts(ModuleStoreTestCase):
|
||||
# This will have no effect on lms side as we are already done with migrations
|
||||
config_course_cohorts_legacy(
|
||||
course,
|
||||
discussions=[],
|
||||
cohorted=True,
|
||||
auto_cohort_groups=["OtherGroup"]
|
||||
)
|
||||
@@ -393,7 +392,6 @@ class TestCohorts(ModuleStoreTestCase):
|
||||
# This will have no effect on lms side as we are already done with migrations
|
||||
config_course_cohorts_legacy(
|
||||
course,
|
||||
discussions=[],
|
||||
cohorted=True,
|
||||
auto_cohort_groups=["AutoGroup"]
|
||||
)
|
||||
|
||||
@@ -6,36 +6,34 @@ Tests for course group views
|
||||
import json
|
||||
|
||||
from collections import namedtuple
|
||||
from datetime import datetime
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.http import Http404
|
||||
from django.test.client import RequestFactory
|
||||
|
||||
from django_comment_common.models import CourseDiscussionSettings
|
||||
from django_comment_common.utils import get_course_discussion_settings
|
||||
from student.models import CourseEnrollment
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from xmodule.modulestore.tests.factories import ItemFactory
|
||||
from lms.djangoapps.django_comment_client.constants import TYPE_ENTRY, TYPE_SUBCATEGORY
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
|
||||
|
||||
from ..models import CourseUserGroup, CourseCohort
|
||||
from ..views import (
|
||||
course_cohort_settings_handler, course_discussions_settings_handler,
|
||||
course_cohort_settings_handler,
|
||||
cohort_handler, users_in_cohort,
|
||||
add_users_to_cohort, remove_user_from_cohort,
|
||||
link_cohort_to_partition_group, discussion_topics
|
||||
link_cohort_to_partition_group,
|
||||
)
|
||||
from ..cohorts import (
|
||||
get_cohort, get_cohort_by_name, get_cohort_by_id,
|
||||
DEFAULT_COHORT_NAME, get_group_info_for_cohort
|
||||
)
|
||||
from .helpers import (
|
||||
config_course_cohorts, config_course_discussions, config_course_cohorts_legacy, CohortFactory, CourseCohortFactory, topic_name_to_id
|
||||
config_course_cohorts, config_course_cohorts_legacy, CohortFactory, CourseCohortFactory
|
||||
)
|
||||
|
||||
|
||||
@@ -101,40 +99,6 @@ class CohortViewsTestCase(ModuleStoreTestCase):
|
||||
view_args.insert(0, request)
|
||||
self.assertRaises(Http404, view, *view_args)
|
||||
|
||||
def create_divided_discussions(self):
|
||||
"""
|
||||
Set up a divided discussion in the system, complete with all the fixings
|
||||
"""
|
||||
divided_inline_discussions = ['Topic A']
|
||||
divided_course_wide_discussions = ["Topic B"]
|
||||
divided_discussions = divided_inline_discussions + divided_course_wide_discussions
|
||||
|
||||
# inline discussion
|
||||
ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category="discussion",
|
||||
discussion_id=topic_name_to_id(self.course, "Topic A"),
|
||||
discussion_category="Chapter",
|
||||
discussion_target="Discussion",
|
||||
start=datetime.now()
|
||||
)
|
||||
# course-wide discussion
|
||||
discussion_topics = {
|
||||
"Topic B": {"id": "Topic B"},
|
||||
}
|
||||
|
||||
config_course_cohorts(
|
||||
self.course,
|
||||
is_cohorted=True,
|
||||
)
|
||||
|
||||
config_course_discussions(
|
||||
self.course,
|
||||
discussion_topics=discussion_topics,
|
||||
divided_discussions=divided_discussions
|
||||
)
|
||||
return divided_inline_discussions, divided_course_wide_discussions
|
||||
|
||||
def get_handler(self, course, cohort=None, expected_response_code=200, handler=cohort_handler):
|
||||
"""
|
||||
Call a GET on `handler` for a given `course` and return its response as a dict.
|
||||
@@ -183,129 +147,6 @@ class CohortViewsTestCase(ModuleStoreTestCase):
|
||||
return json.loads(response.content)
|
||||
|
||||
|
||||
@attr(shard=2)
|
||||
class CourseDiscussionsHandlerTestCase(CohortViewsTestCase):
|
||||
"""
|
||||
Tests the course_discussion_settings_handler
|
||||
"""
|
||||
def get_expected_response(self):
|
||||
"""
|
||||
Returns the static response dict.
|
||||
"""
|
||||
return {
|
||||
u'always_divide_inline_discussions': False,
|
||||
u'divided_inline_discussions': [],
|
||||
u'divided_course_wide_discussions': [],
|
||||
u'id': 1
|
||||
}
|
||||
|
||||
def test_non_staff(self):
|
||||
"""
|
||||
Verify that we cannot access course_discussions_settings_handler if we're a non-staff user.
|
||||
"""
|
||||
self._verify_non_staff_cannot_access(course_discussions_settings_handler, "GET", [unicode(self.course.id)])
|
||||
self._verify_non_staff_cannot_access(course_discussions_settings_handler, "PATCH", [unicode(self.course.id)])
|
||||
|
||||
def test_update_always_divide_inline_discussion_settings(self):
|
||||
"""
|
||||
Verify that course_discussions_settings_handler is working for always_divide_inline_discussions via HTTP PATCH.
|
||||
"""
|
||||
config_course_cohorts(self.course, is_cohorted=True)
|
||||
|
||||
response = self.get_handler(self.course, handler=course_discussions_settings_handler)
|
||||
|
||||
expected_response = self.get_expected_response()
|
||||
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
expected_response['always_divide_inline_discussions'] = True
|
||||
response = self.patch_handler(self.course, data=expected_response, handler=course_discussions_settings_handler)
|
||||
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
def test_update_course_wide_discussion_settings(self):
|
||||
"""
|
||||
Verify that course_discussions_settings_handler is working for divided_course_wide_discussions via HTTP PATCH.
|
||||
"""
|
||||
# course-wide discussion
|
||||
discussion_topics = {
|
||||
"Topic B": {"id": "Topic B"},
|
||||
}
|
||||
|
||||
config_course_cohorts(self.course, is_cohorted=True)
|
||||
config_course_discussions(self.course, discussion_topics=discussion_topics)
|
||||
|
||||
response = self.get_handler(self.course, handler=course_discussions_settings_handler)
|
||||
|
||||
expected_response = self.get_expected_response()
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
expected_response['divided_course_wide_discussions'] = [topic_name_to_id(self.course, "Topic B")]
|
||||
response = self.patch_handler(self.course, data=expected_response, handler=course_discussions_settings_handler)
|
||||
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
def test_update_inline_discussion_settings(self):
|
||||
"""
|
||||
Verify that course_discussions_settings_handler is working for divided_inline_discussions via HTTP PATCH.
|
||||
"""
|
||||
config_course_cohorts(self.course, is_cohorted=True)
|
||||
|
||||
response = self.get_handler(self.course, handler=course_discussions_settings_handler)
|
||||
|
||||
expected_response = self.get_expected_response()
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
now = datetime.now()
|
||||
# inline discussion
|
||||
ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
category="discussion",
|
||||
discussion_id="Topic_A",
|
||||
discussion_category="Chapter",
|
||||
discussion_target="Discussion",
|
||||
start=now
|
||||
)
|
||||
|
||||
expected_response['divided_inline_discussions'] = ["Topic_A"]
|
||||
response = self.patch_handler(self.course, data=expected_response, handler=course_discussions_settings_handler)
|
||||
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
def test_get_settings(self):
|
||||
"""
|
||||
Verify that course_discussions_settings_handler is working for HTTP GET.
|
||||
"""
|
||||
divided_inline_discussions, divided_course_wide_discussions = self.create_divided_discussions()
|
||||
|
||||
response = self.get_handler(self.course, handler=course_discussions_settings_handler)
|
||||
expected_response = self.get_expected_response()
|
||||
|
||||
expected_response['divided_inline_discussions'] = [topic_name_to_id(self.course, name)
|
||||
for name in divided_inline_discussions]
|
||||
expected_response['divided_course_wide_discussions'] = [topic_name_to_id(self.course, name)
|
||||
for name in divided_course_wide_discussions]
|
||||
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
def test_update_settings_with_invalid_field_data_type(self):
|
||||
"""
|
||||
Verify that course_discussions_settings_handler return HTTP 400 if field data type is incorrect.
|
||||
"""
|
||||
config_course_cohorts(self.course, is_cohorted=True)
|
||||
|
||||
response = self.patch_handler(
|
||||
self.course,
|
||||
data={'always_divide_inline_discussions': ''},
|
||||
expected_response_code=400,
|
||||
handler=course_discussions_settings_handler
|
||||
)
|
||||
self.assertEqual(
|
||||
"Incorrect field type for `{}`. Type must be `{}`".format('always_divide_inline_discussions', bool.__name__),
|
||||
response.get("error")
|
||||
)
|
||||
|
||||
|
||||
@attr(shard=2)
|
||||
class CourseCohortSettingsHandlerTestCase(CohortViewsTestCase):
|
||||
"""
|
||||
@@ -345,6 +186,30 @@ class CourseCohortSettingsHandlerTestCase(CohortViewsTestCase):
|
||||
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
def test_enabling_cohorts_does_not_change_division_scheme(self):
|
||||
"""
|
||||
Verify that enabling cohorts on a course does not automatically set the discussion division_scheme
|
||||
to cohort.
|
||||
"""
|
||||
config_course_cohorts(self.course, is_cohorted=False, discussion_division_scheme=CourseDiscussionSettings.NONE)
|
||||
|
||||
response = self.get_handler(self.course, handler=course_cohort_settings_handler)
|
||||
|
||||
expected_response = self.get_expected_response()
|
||||
expected_response['is_cohorted'] = False
|
||||
self.assertEqual(response, expected_response)
|
||||
self.assertEqual(
|
||||
CourseDiscussionSettings.NONE, get_course_discussion_settings(self.course.id).division_scheme
|
||||
)
|
||||
|
||||
expected_response['is_cohorted'] = True
|
||||
response = self.patch_handler(self.course, data=expected_response, handler=course_cohort_settings_handler)
|
||||
|
||||
self.assertEqual(response, expected_response)
|
||||
self.assertEqual(
|
||||
CourseDiscussionSettings.NONE, get_course_discussion_settings(self.course.id).division_scheme
|
||||
)
|
||||
|
||||
def test_update_settings_with_missing_field(self):
|
||||
"""
|
||||
Verify that course_cohort_settings_handler return HTTP 400 if required data field is missing from post data.
|
||||
@@ -492,7 +357,7 @@ class CohortHandlerTestCase(CohortViewsTestCase):
|
||||
|
||||
# set auto_cohort_groups
|
||||
# these cohort config will have not effect on lms side as we are already done with migrations
|
||||
config_course_cohorts_legacy(self.course, [], cohorted=True, auto_cohort_groups=["AutoGroup"])
|
||||
config_course_cohorts_legacy(self.course, cohorted=True, auto_cohort_groups=["AutoGroup"])
|
||||
|
||||
# We should expect the DoesNotExist exception because above cohort config have
|
||||
# no effect on lms side so as a result there will be no AutoGroup cohort present
|
||||
@@ -1270,60 +1135,3 @@ class RemoveUserFromCohortTestCase(CohortViewsTestCase):
|
||||
cohort = CohortFactory(course_id=self.course.id, users=[user])
|
||||
response_dict = self.request_remove_user_from_cohort(user.username, cohort)
|
||||
self.verify_removed_user_from_cohort(user.username, response_dict, cohort)
|
||||
|
||||
|
||||
@attr(shard=2)
|
||||
@skip_unless_lms
|
||||
class CourseDividedDiscussionTopicsTestCase(CohortViewsTestCase):
|
||||
"""
|
||||
Tests the `divide_discussion_topics` view.
|
||||
"""
|
||||
|
||||
def test_non_staff(self):
|
||||
"""
|
||||
Verify that we cannot access divide_discussion_topics if we're a non-staff user.
|
||||
"""
|
||||
self._verify_non_staff_cannot_access(discussion_topics, "GET", [unicode(self.course.id)])
|
||||
|
||||
def test_get_discussion_topics(self):
|
||||
"""
|
||||
Verify that divide_discussion_topics is working for HTTP GET.
|
||||
"""
|
||||
# create inline & course-wide discussion to verify the different map.
|
||||
self.create_divided_discussions()
|
||||
|
||||
response = self.get_handler(self.course, handler=discussion_topics)
|
||||
start_date = response['inline_discussions']['subcategories']['Chapter']['start_date']
|
||||
expected_response = {
|
||||
"course_wide_discussions": {
|
||||
'children': [['Topic B', TYPE_ENTRY]],
|
||||
'entries': {
|
||||
'Topic B': {
|
||||
'sort_key': 'A',
|
||||
'is_divided': True,
|
||||
'id': topic_name_to_id(self.course, "Topic B"),
|
||||
'start_date': response['course_wide_discussions']['entries']['Topic B']['start_date']
|
||||
}
|
||||
}
|
||||
},
|
||||
"inline_discussions": {
|
||||
'subcategories': {
|
||||
'Chapter': {
|
||||
'subcategories': {},
|
||||
'children': [['Discussion', TYPE_ENTRY]],
|
||||
'entries': {
|
||||
'Discussion': {
|
||||
'sort_key': None,
|
||||
'is_divided': True,
|
||||
'id': topic_name_to_id(self.course, "Topic A"),
|
||||
'start_date': start_date
|
||||
}
|
||||
},
|
||||
'sort_key': 'Chapter',
|
||||
'start_date': start_date
|
||||
}
|
||||
},
|
||||
'children': [['Chapter', TYPE_SUBCATEGORY]]
|
||||
}
|
||||
}
|
||||
self.assertEqual(response, expected_response)
|
||||
|
||||
@@ -15,11 +15,7 @@ from django.http import Http404, HttpResponseBadRequest
|
||||
from django.utils.translation import ugettext
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.decorators.http import require_http_methods, require_POST
|
||||
from django_comment_common.models import CourseDiscussionSettings
|
||||
from django_comment_common.utils import get_course_discussion_settings, set_course_discussion_settings
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from lms.djangoapps.django_comment_client.constants import TYPE_ENTRY
|
||||
from lms.djangoapps.django_comment_client.utils import get_discussion_categories_ids, get_discussion_category_map
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from util.json_request import JsonResponse, expect_json
|
||||
@@ -74,22 +70,6 @@ def _get_course_cohort_settings_representation(cohort_id, is_cohorted):
|
||||
}
|
||||
|
||||
|
||||
def _get_course_discussion_settings_representation(course, course_discussion_settings):
|
||||
"""
|
||||
Returns a JSON representation of a course discussion settings.
|
||||
"""
|
||||
divided_course_wide_discussions, divided_inline_discussions = get_divided_discussions(
|
||||
course, course_discussion_settings
|
||||
)
|
||||
|
||||
return {
|
||||
'id': course_discussion_settings.id,
|
||||
'divided_inline_discussions': divided_inline_discussions,
|
||||
'divided_course_wide_discussions': divided_course_wide_discussions,
|
||||
'always_divide_inline_discussions': course_discussion_settings.always_divide_inline_discussions,
|
||||
}
|
||||
|
||||
|
||||
def _get_cohort_representation(cohort, course):
|
||||
"""
|
||||
Returns a JSON representation of a cohort.
|
||||
@@ -107,80 +87,6 @@ def _get_cohort_representation(cohort, course):
|
||||
}
|
||||
|
||||
|
||||
def get_divided_discussions(course, discussion_settings):
|
||||
"""
|
||||
Returns the course-wide and inline divided discussion ids separately.
|
||||
"""
|
||||
divided_course_wide_discussions = []
|
||||
divided_inline_discussions = []
|
||||
|
||||
course_wide_discussions = [topic['id'] for __, topic in course.discussion_topics.items()]
|
||||
all_discussions = get_discussion_categories_ids(course, None, include_all=True)
|
||||
|
||||
for divided_discussion_id in discussion_settings.divided_discussions:
|
||||
if divided_discussion_id in course_wide_discussions:
|
||||
divided_course_wide_discussions.append(divided_discussion_id)
|
||||
elif divided_discussion_id in all_discussions:
|
||||
divided_inline_discussions.append(divided_discussion_id)
|
||||
|
||||
return divided_course_wide_discussions, divided_inline_discussions
|
||||
|
||||
|
||||
@require_http_methods(("GET", "PATCH"))
|
||||
@ensure_csrf_cookie
|
||||
@expect_json
|
||||
@login_required
|
||||
def course_discussions_settings_handler(request, course_key_string):
|
||||
"""
|
||||
The restful handler for divided discussion setting requests. Requires JSON.
|
||||
This will raise 404 if user is not staff.
|
||||
GET
|
||||
Returns the JSON representation of divided discussion settings for the course.
|
||||
PATCH
|
||||
Updates the divided discussion settings for the course. Returns the JSON representation of updated settings.
|
||||
"""
|
||||
course_key = CourseKey.from_string(course_key_string)
|
||||
course = get_course_with_access(request.user, 'staff', course_key)
|
||||
discussion_settings = get_course_discussion_settings(course_key)
|
||||
|
||||
if request.method == 'PATCH':
|
||||
divided_course_wide_discussions, divided_inline_discussions = get_divided_discussions(
|
||||
course, discussion_settings
|
||||
)
|
||||
|
||||
settings_to_change = {}
|
||||
|
||||
if 'divided_course_wide_discussions' in request.json or 'divided_inline_discussions' in request.json:
|
||||
divided_course_wide_discussions = request.json.get(
|
||||
'divided_course_wide_discussions', divided_course_wide_discussions
|
||||
)
|
||||
divided_inline_discussions = request.json.get(
|
||||
'divided_inline_discussions', divided_inline_discussions
|
||||
)
|
||||
settings_to_change['divided_discussions'] = divided_course_wide_discussions + divided_inline_discussions
|
||||
|
||||
if 'always_divide_inline_discussions' in request.json:
|
||||
settings_to_change['always_divide_inline_discussions'] = request.json.get(
|
||||
'always_divide_inline_discussions'
|
||||
)
|
||||
|
||||
if not settings_to_change:
|
||||
return JsonResponse({"error": unicode("Bad Request")}, 400)
|
||||
|
||||
try:
|
||||
if settings_to_change:
|
||||
discussion_settings = set_course_discussion_settings(course_key, **settings_to_change)
|
||||
|
||||
except ValueError as err:
|
||||
# Note: error message not translated because it is not exposed to the user (UI prevents this state).
|
||||
return JsonResponse({"error": unicode(err)}, 400)
|
||||
|
||||
return JsonResponse(_get_course_discussion_settings_representation(
|
||||
course,
|
||||
discussion_settings
|
||||
))
|
||||
|
||||
|
||||
@require_http_methods(("GET", "PATCH"))
|
||||
@ensure_csrf_cookie
|
||||
@expect_json
|
||||
@@ -196,7 +102,7 @@ def course_cohort_settings_handler(request, course_key_string):
|
||||
"""
|
||||
course_key = CourseKey.from_string(course_key_string)
|
||||
# Although this course data is not used this method will return 404 is user is not staff
|
||||
course = get_course_with_access(request.user, 'staff', course_key)
|
||||
get_course_with_access(request.user, 'staff', course_key)
|
||||
|
||||
if request.method == 'PATCH':
|
||||
if 'is_cohorted' not in request.json:
|
||||
@@ -205,9 +111,6 @@ def course_cohort_settings_handler(request, course_key_string):
|
||||
is_cohorted = request.json.get('is_cohorted')
|
||||
try:
|
||||
cohorts.set_course_cohorted(course_key, is_cohorted)
|
||||
scheme = CourseDiscussionSettings.COHORT if is_cohorted else CourseDiscussionSettings.NONE
|
||||
scheme_settings = {'division_scheme': scheme}
|
||||
set_course_discussion_settings(course_key, **scheme_settings)
|
||||
except ValueError as err:
|
||||
# Note: error message not translated because it is not exposed to the user (UI prevents this state).
|
||||
return JsonResponse({"error": unicode(err)}, 400)
|
||||
@@ -464,81 +367,3 @@ def debug_cohort_mgmt(request, course_key_string):
|
||||
kwargs={'course_key': course_key.to_deprecated_string()}
|
||||
)}
|
||||
return render_to_response('/course_groups/debug.html', context)
|
||||
|
||||
|
||||
@expect_json
|
||||
@login_required
|
||||
def discussion_topics(request, course_key_string):
|
||||
"""
|
||||
The handler for divided discussion categories requests.
|
||||
This will raise 404 if user is not staff.
|
||||
|
||||
Returns the JSON representation of discussion topics w.r.t categories for the course.
|
||||
|
||||
Example:
|
||||
>>> example = {
|
||||
>>> "course_wide_discussions": {
|
||||
>>> "entries": {
|
||||
>>> "General": {
|
||||
>>> "sort_key": "General",
|
||||
>>> "is_divided": True,
|
||||
>>> "id": "i4x-edx-eiorguegnru-course-foobarbaz"
|
||||
>>> }
|
||||
>>> }
|
||||
>>> "children": ["General", "entry"]
|
||||
>>> },
|
||||
>>> "inline_discussions" : {
|
||||
>>> "subcategories": {
|
||||
>>> "Getting Started": {
|
||||
>>> "subcategories": {},
|
||||
>>> "children": [
|
||||
>>> ["Working with Videos", "entry"],
|
||||
>>> ["Videos on edX", "entry"]
|
||||
>>> ],
|
||||
>>> "entries": {
|
||||
>>> "Working with Videos": {
|
||||
>>> "sort_key": None,
|
||||
>>> "is_divided": False,
|
||||
>>> "id": "d9f970a42067413cbb633f81cfb12604"
|
||||
>>> },
|
||||
>>> "Videos on edX": {
|
||||
>>> "sort_key": None,
|
||||
>>> "is_divided": False,
|
||||
>>> "id": "98d8feb5971041a085512ae22b398613"
|
||||
>>> }
|
||||
>>> }
|
||||
>>> },
|
||||
>>> "children": ["Getting Started", "subcategory"]
|
||||
>>> },
|
||||
>>> }
|
||||
>>> }
|
||||
"""
|
||||
course_key = CourseKey.from_string(course_key_string)
|
||||
course = get_course_with_access(request.user, 'staff', course_key)
|
||||
|
||||
discussion_topics = {}
|
||||
discussion_category_map = get_discussion_category_map(
|
||||
course, request.user, divided_only_if_explicit=True, exclude_unstarted=False
|
||||
)
|
||||
|
||||
# We extract the data for the course wide discussions from the category map.
|
||||
course_wide_entries = discussion_category_map.pop('entries')
|
||||
|
||||
course_wide_children = []
|
||||
inline_children = []
|
||||
|
||||
for name, c_type in discussion_category_map['children']:
|
||||
if name in course_wide_entries and c_type == TYPE_ENTRY:
|
||||
course_wide_children.append([name, c_type])
|
||||
else:
|
||||
inline_children.append([name, c_type])
|
||||
|
||||
discussion_topics['course_wide_discussions'] = {
|
||||
'entries': course_wide_entries,
|
||||
'children': course_wide_children
|
||||
}
|
||||
|
||||
discussion_category_map['children'] = inline_children
|
||||
discussion_topics['inline_discussions'] = discussion_category_map
|
||||
|
||||
return JsonResponse(discussion_topics)
|
||||
|
||||
Reference in New Issue
Block a user