feat: added user messages and backed now uses discussion_enabled flag (#31716)
* refactor: simplified tasks.py for discussions * fix: do not create a topic for the unpublished unit * feat: added user messages and backed now uses discussion_enabled flag * fix: update default for discussion_enabled flag * feat: removed redundant tests and fixes
This commit is contained in:
@@ -50,31 +50,56 @@ def update_discussions_settings_from_course(course_key: CourseKey) -> CourseDisc
|
||||
supports_in_context = discussions_config.supports_in_context_discussions()
|
||||
provider_type = discussions_config.provider_type
|
||||
|
||||
def iter_discussable_units():
|
||||
# Start at 99 so that the initial increment starts it at 100.
|
||||
# This leaves the first 100 slots for the course wide topics, which is only a concern if there are more
|
||||
# than that many.
|
||||
idx = 99
|
||||
for section in course.get_children():
|
||||
if section.location.block_type != "chapter":
|
||||
continue
|
||||
for subsection in section.get_children():
|
||||
if subsection.location.block_type != "sequential":
|
||||
continue
|
||||
for unit in subsection.get_children():
|
||||
if unit.location.block_type != 'vertical':
|
||||
continue
|
||||
# Increment index even for skipped units so that the index is more stable and won't change
|
||||
# if settings change, only if a unit is added or removed.
|
||||
with store.branch_setting(ModuleStoreEnum.Branch.published_only, course_key):
|
||||
course = store.get_course(course_key)
|
||||
enable_in_context = discussions_config.enable_in_context
|
||||
provider_config = discussions_config.plugin_configuration
|
||||
unit_level_visibility = discussions_config.unit_level_visibility
|
||||
enable_graded_units = discussions_config.enable_graded_units
|
||||
|
||||
contexts = []
|
||||
if supports_in_context:
|
||||
sorted_topics = sorted(
|
||||
course.discussion_topics.items(),
|
||||
key=lambda item: item[1].get("sort_key", item[0]),
|
||||
)
|
||||
contexts = []
|
||||
for idx, (topic_name, topic_config) in enumerate(sorted_topics):
|
||||
if topic_config.get('id', None):
|
||||
context = DiscussionTopicContext(
|
||||
title=topic_name,
|
||||
external_id=topic_config.get('id', None),
|
||||
ordering=idx
|
||||
)
|
||||
contexts.append(context)
|
||||
if enable_in_context:
|
||||
contexts.extend(list(get_discussable_units(course, enable_graded_units)))
|
||||
config_data = CourseDiscussionConfigurationData(
|
||||
course_key=course_key,
|
||||
enable_in_context=enable_in_context,
|
||||
enable_graded_units=enable_graded_units,
|
||||
unit_level_visibility=unit_level_visibility,
|
||||
provider_type=provider_type,
|
||||
plugin_configuration=provider_config,
|
||||
contexts=contexts,
|
||||
)
|
||||
return config_data
|
||||
|
||||
|
||||
def get_discussable_units(course, enable_graded_units):
|
||||
"""
|
||||
Get all the units in the course that are discussable.
|
||||
"""
|
||||
idx = 99
|
||||
store = modulestore()
|
||||
for section in get_sections(course):
|
||||
for subsection in get_subsections(section):
|
||||
with store.bulk_operations(course.id, emit_signals=False):
|
||||
for unit in get_units(subsection):
|
||||
idx += 1
|
||||
# If unit-level visibility is enabled and the unit doesn't have discussion enabled, skip it.
|
||||
if unit_level_visibility and not getattr(unit, "discussion_enabled", False):
|
||||
continue
|
||||
# If the unit is in a graded section and graded sections aren't enabled skip it.
|
||||
if subsection.graded and not enable_graded_units:
|
||||
continue
|
||||
# If the unit is an exam, skip it.
|
||||
if subsection.is_practice_exam or subsection.is_proctored_enabled or subsection.is_time_limited:
|
||||
if not is_discussable_unit(unit, store, enable_graded_units, subsection):
|
||||
unit.discussion_enabled = False
|
||||
store.update_item(unit, unit.published_by, emit_signals=False)
|
||||
continue
|
||||
yield DiscussionTopicContext(
|
||||
usage_key=unit.location,
|
||||
@@ -88,39 +113,51 @@ def update_discussions_settings_from_course(course_key: CourseKey) -> CourseDisc
|
||||
},
|
||||
)
|
||||
|
||||
with store.branch_setting(ModuleStoreEnum.Branch.published_only, course_key):
|
||||
course = store.get_course(course_key)
|
||||
enable_in_context = discussions_config.enable_in_context
|
||||
provider_config = discussions_config.plugin_configuration
|
||||
unit_level_visibility = discussions_config.unit_level_visibility
|
||||
enable_graded_units = discussions_config.enable_graded_units
|
||||
contexts = []
|
||||
if supports_in_context:
|
||||
sorted_topics = sorted(
|
||||
course.discussion_topics.items(),
|
||||
key=lambda item: item[1].get("sort_key", item[0]),
|
||||
)
|
||||
contexts = [
|
||||
DiscussionTopicContext(
|
||||
title=topic_name,
|
||||
external_id=topic_config.get('id', None),
|
||||
ordering=idx,
|
||||
)
|
||||
for idx, (topic_name, topic_config) in enumerate(sorted_topics)
|
||||
if topic_config.get('id', None)
|
||||
]
|
||||
if enable_in_context:
|
||||
contexts.extend(list(iter_discussable_units()))
|
||||
config_data = CourseDiscussionConfigurationData(
|
||||
course_key=course_key,
|
||||
enable_in_context=enable_in_context,
|
||||
enable_graded_units=enable_graded_units,
|
||||
unit_level_visibility=unit_level_visibility,
|
||||
provider_type=provider_type,
|
||||
plugin_configuration=provider_config,
|
||||
contexts=contexts,
|
||||
)
|
||||
return config_data
|
||||
|
||||
def get_sections(course):
|
||||
"""
|
||||
Get sections for given course
|
||||
"""
|
||||
for section in course.get_children():
|
||||
if section.location.block_type == "chapter":
|
||||
yield section
|
||||
|
||||
|
||||
def get_subsections(section):
|
||||
"""
|
||||
Get subsections for given section
|
||||
"""
|
||||
for subsection in section.get_children():
|
||||
if subsection.location.block_type == "sequential":
|
||||
yield subsection
|
||||
|
||||
|
||||
def get_units(subsection):
|
||||
"""
|
||||
Get units for given subsection
|
||||
"""
|
||||
for unit in subsection.get_children():
|
||||
if unit.location.block_type == 'vertical':
|
||||
yield unit
|
||||
|
||||
|
||||
def is_discussable_unit(unit, store, enable_graded_units, subsection):
|
||||
"""
|
||||
Check if unit should have discussion's topic
|
||||
"""
|
||||
if not store.has_published_version(unit):
|
||||
return False
|
||||
|
||||
if not getattr(unit, "discussion_enabled", False):
|
||||
return False
|
||||
|
||||
if subsection.graded and not enable_graded_units:
|
||||
return False
|
||||
|
||||
if subsection.is_practice_exam or subsection.is_proctored_enabled or subsection.is_time_limited:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def update_unit_discussion_state_from_discussion_blocks(course_key: CourseKey, user_id: int, force=False) -> None:
|
||||
|
||||
@@ -162,10 +162,10 @@ class UpdateDiscussionsSettingsFromCourseTestCase(ModuleStoreTestCase, Discussio
|
||||
({}, 3, {"Unit", "Discussable Unit"},
|
||||
{"Graded Unit", "Non-Discussable Unit", "Discussable Graded Unit", "Non-Discussable Graded Unit"}),
|
||||
({"enable_in_context": False}, 1, set(), {"Unit", "Graded Unit"}),
|
||||
({"unit_level_visibility": False, "enable_graded_units": False}, 4,
|
||||
{"Unit", "Discussable Unit", "Non-Discussable Unit"},
|
||||
({"unit_level_visibility": False, "enable_graded_units": False}, 3,
|
||||
{"Unit", "Discussable Unit"},
|
||||
{"Graded Unit"}),
|
||||
({"unit_level_visibility": False, "enable_graded_units": True}, 7,
|
||||
({"unit_level_visibility": False, "enable_graded_units": True}, 5,
|
||||
{"Unit", "Graded Unit", "Discussable Graded Unit"}, set()),
|
||||
({"enable_graded_units": True}, 5,
|
||||
{"Discussable Unit", "Discussable Graded Unit", "Graded Unit"},
|
||||
|
||||
Reference in New Issue
Block a user