From 358aa7754b7161ec7a43ed7067356289e8b1891d Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Wed, 13 May 2015 18:34:47 -0400 Subject: [PATCH] Add "Teams Configuration" advanced setting --- .../models/settings/course_metadata.py | 4 ++ cms/envs/bok_choy.py | 3 + cms/envs/common.py | 5 +- cms/envs/test.py | 4 ++ common/lib/xmodule/xmodule/course_module.py | 34 +++++++++ .../xmodule/tests/test_course_module.py | 71 +++++++++++++++++++ .../pages/studio/settings_advanced.py | 1 + lms/envs/bok_choy.py | 3 + lms/envs/common.py | 3 + lms/envs/test.py | 3 + 10 files changed, 130 insertions(+), 1 deletion(-) diff --git a/cms/djangoapps/models/settings/course_metadata.py b/cms/djangoapps/models/settings/course_metadata.py index fadc3d5a87..2f22ba400f 100644 --- a/cms/djangoapps/models/settings/course_metadata.py +++ b/cms/djangoapps/models/settings/course_metadata.py @@ -74,6 +74,10 @@ class CourseMetadata(object): not settings.FEATURES.get("DASHBOARD_SHARE_SETTINGS").get("CUSTOM_COURSE_URLS")): filtered_list.append('social_sharing_url') + # Do not show teams configuration if feature is disabled. + if not settings.FEATURES.get('ENABLE_TEAMS'): + filtered_list.append('teams_configuration') + return filtered_list @classmethod diff --git a/cms/envs/bok_choy.py b/cms/envs/bok_choy.py index a49d673fb7..a01b334dbb 100644 --- a/cms/envs/bok_choy.py +++ b/cms/envs/bok_choy.py @@ -68,6 +68,9 @@ FEATURES['ENABLE_PREREQUISITE_COURSES'] = True # Enable student notes FEATURES['ENABLE_EDXNOTES'] = True +# Enable teams feature +FEATURES['ENABLE_TEAMS'] = True + ########################### Entrance Exams ################################# FEATURES['ENTRANCE_EXAMS'] = True diff --git a/cms/envs/common.py b/cms/envs/common.py index ddf9fe9801..df800bea00 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -155,7 +155,10 @@ FEATURES = { 'DASHBOARD_SHARE_SETTINGS': { # Note: Ensure 'CUSTOM_COURSE_URLS' has a matching value in lms/envs/common.py 'CUSTOM_COURSE_URLS': False - } + }, + + # Teams feature + 'ENABLE_TEAMS': False, } ENABLE_JASMINE = False diff --git a/cms/envs/test.py b/cms/envs/test.py index 63da126ae4..b637368c9f 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -271,5 +271,9 @@ FEATURES['ENABLE_COURSEWARE_INDEX'] = True FEATURES['ENABLE_LIBRARY_INDEX'] = True SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine" + +# teams feature +FEATURES['ENABLE_TEAMS'] = True + # Dummy secret key for dev/test SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 7fa3b50780..7ed4abe4d1 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -846,6 +846,15 @@ class CourseFields(object): scope=Scope.settings, ) + teams_configuration = Dict( + display_name=_("Teams Configuration"), + help=_( + "Enter configuration for the teams feature. Expects two entries: max_team_size and topics, where " + "topics is a list of topics." + ), + scope=Scope.settings + ) + class CourseModule(CourseFields, SequenceModule): # pylint: disable=abstract-method """ @@ -1408,3 +1417,28 @@ class CourseDescriptor(CourseFields, SequenceDescriptor): return "course_{}".format( b32encode(unicode(self.location.course_key)).replace('=', padding_char) ) + + @property + def teams_enabled(self): + """ + Returns whether or not teams has been enabled for this course. + + Currently, teams are considered enabled when at least one topic has been configured for the course. + """ + if self.teams_configuration: + return len(self.teams_configuration.get('topics', [])) > 0 + return False + + @property + def teams_max_size(self): + """ + Returns the max size for teams if teams has been configured, else None. + """ + return self.teams_configuration.get('max_team_size', None) + + @property + def teams_topics(self): + """ + Returns the topics that have been configured for teams for this course, else None. + """ + return self.teams_configuration.get('topics', None) diff --git a/common/lib/xmodule/xmodule/tests/test_course_module.py b/common/lib/xmodule/xmodule/tests/test_course_module.py index addf8bebb0..e3a1b36faa 100644 --- a/common/lib/xmodule/xmodule/tests/test_course_module.py +++ b/common/lib/xmodule/xmodule/tests/test_course_module.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta from fs.memoryfs import MemoryFS from mock import Mock, patch +import itertools from xblock.runtime import KvsFieldData, DictKeyValueStore @@ -277,3 +278,73 @@ class DiscussionTopicsTestCase(unittest.TestCase): def test_default_discussion_topics(self): d = get_dummy_course('2012-12-02T12:00') self.assertEqual({'General': {'id': 'i4x-test_org-test_course-course-test'}}, d.discussion_topics) + + +class TeamsConfigurationTestCase(unittest.TestCase): + """ + Tests for the configuration of teams and the helper methods for accessing them. + """ + + def setUp(self): + super(TeamsConfigurationTestCase, self).setUp() + self.course = get_dummy_course('2012-12-02T12:00') + self.course.teams_configuration = dict() + self.count = itertools.count() + + def add_team_configuration(self, max_team_size=3, topics=None): + """ Add a team configuration to the course. """ + teams_configuration = {} + teams_configuration["topics"] = [] if topics is None else topics + if max_team_size is not None: + teams_configuration["max_team_size"] = max_team_size + self.course.teams_configuration = teams_configuration + + def make_topic(self): + """ Make a sample topic dictionary. """ + next_num = self.count.next() + topic_id = "topic_id_{}".format(next_num) + display_name = "Display Name {}".format(next_num) + description = "Description {}".format(next_num) + return {"display_name": display_name, "description": description, "id": topic_id} + + def test_teams_enabled_new_course(self): + # Make sure we can detect when no teams exist. + self.assertFalse(self.course.teams_enabled) + + # add topics + self.add_team_configuration(max_team_size=4, topics=[self.make_topic()]) + self.assertTrue(self.course.teams_enabled) + + # remove them again + self.add_team_configuration(max_team_size=4, topics=[]) + self.assertFalse(self.course.teams_enabled) + + def test_teams_enabled_max_size_only(self): + self.add_team_configuration(max_team_size=4) + self.assertFalse(self.course.teams_enabled) + + def test_teams_enabled_no_max_size(self): + self.add_team_configuration(max_team_size=None, topics=[self.make_topic()]) + self.assertTrue(self.course.teams_enabled) + + def test_teams_max_size_no_teams_configuration(self): + self.assertIsNone(self.course.teams_max_size) + + def test_teams_max_size_with_teams_configured(self): + size = 4 + self.add_team_configuration(max_team_size=size, topics=[self.make_topic(), self.make_topic()]) + self.assertTrue(self.course.teams_enabled) + self.assertEqual(size, self.course.teams_max_size) + + def test_teams_topics_no_teams(self): + self.assertIsNone(self.course.teams_topics) + + def test_teams_topics_no_topics(self): + self.add_team_configuration(max_team_size=4) + self.assertEqual(self.course.teams_topics, []) + + def test_teams_topics_with_topics(self): + topics = [self.make_topic(), self.make_topic()] + self.add_team_configuration(max_team_size=4, topics=topics) + self.assertTrue(self.course.teams_enabled) + self.assertEqual(self.course.teams_topics, topics) diff --git a/common/test/acceptance/pages/studio/settings_advanced.py b/common/test/acceptance/pages/studio/settings_advanced.py index c30780b26b..34fdd9da38 100644 --- a/common/test/acceptance/pages/studio/settings_advanced.py +++ b/common/test/acceptance/pages/studio/settings_advanced.py @@ -198,4 +198,5 @@ class AdvancedSettingsPage(CoursePage): 'text_customization', 'annotation_storage_url', 'social_sharing_url', + 'teams_configuration', ] diff --git a/lms/envs/bok_choy.py b/lms/envs/bok_choy.py index e7efd6ca73..98e230f7fa 100644 --- a/lms/envs/bok_choy.py +++ b/lms/envs/bok_choy.py @@ -96,6 +96,9 @@ FEATURES['ENABLE_PREREQUISITE_COURSES'] = True # Enable student notes FEATURES['ENABLE_EDXNOTES'] = True +# Enable teams feature +FEATURES['ENABLE_TEAMS'] = True + # Unfortunately, we need to use debug mode to serve staticfiles DEBUG = True diff --git a/lms/envs/common.py b/lms/envs/common.py index c9559c3c85..c00c94fdf6 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -386,6 +386,9 @@ FEATURES = { # Software secure fake page feature flag 'ENABLE_SOFTWARE_SECURE_FAKE': False, + + # Teams feature + 'ENABLE_TEAMS': False, } # Ignore static asset files on import which match this pattern diff --git a/lms/envs/test.py b/lms/envs/test.py index 0d3c092d89..323fa9bfe8 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -449,6 +449,9 @@ MONGODB_LOG = { # Enable EdxNotes for tests. FEATURES['ENABLE_EDXNOTES'] = True +# Enable teams feature for tests. +FEATURES['ENABLE_TEAMS'] = True + # Add milestones to Installed apps for testing INSTALLED_APPS += ('milestones', )