From abfac4912a8fb9df5c4154033477fd3a7f61eb87 Mon Sep 17 00:00:00 2001 From: Ahtisham Shahid Date: Mon, 19 Dec 2022 16:29:12 +0500 Subject: [PATCH] feat: added archived topics in v3 api (#31443) * feat: added archived topis in v3 api * fix: resolved issue with failed test * fix: updated functions docs * feat: added test for util function --- .../discussion/rest_api/tests/test_utils.py | 23 +++++++ lms/djangoapps/discussion/rest_api/utils.py | 61 +++++++++++++++++-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/lms/djangoapps/discussion/rest_api/tests/test_utils.py b/lms/djangoapps/discussion/rest_api/tests/test_utils.py index 8f4b940f9e..d56385352b 100644 --- a/lms/djangoapps/discussion/rest_api/tests/test_utils.py +++ b/lms/djangoapps/discussion/rest_api/tests/test_utils.py @@ -17,6 +17,7 @@ from lms.djangoapps.discussion.rest_api.utils import ( get_course_ta_users_list, get_course_staff_users_list, get_moderator_users_list, + get_archived_topics ) @@ -71,3 +72,25 @@ class DiscussionAPIUtilsTestCase(ModuleStoreTestCase): def test_course_ta_users_list(self): ta_user_list = get_course_ta_users_list(self.course.id) assert len(ta_user_list) == 2 + + def test_get_archived_topics(self): + # Define some example inputs + filtered_topic_ids = ['t1', 't2', 't3', 't4'] + topics = [ + {'id': 't1', 'usage_key': 'u1', 'title': 'Topic 1'}, + {'id': 't2', 'usage_key': None, 'title': 'Topic 2'}, + {'id': 't3', 'usage_key': 'u3', 'title': 'Topic 3'}, + {'id': 't4', 'usage_key': 'u4', 'title': 'Topic 4'}, + {'id': 't5', 'usage_key': None, 'title': 'Topic 5'}, + ] + expected_output = [ + {'id': 't1', 'usage_key': 'u1', 'title': 'Topic 1'}, + {'id': 't3', 'usage_key': 'u3', 'title': 'Topic 3'}, + {'id': 't4', 'usage_key': 'u4', 'title': 'Topic 4'}, + ] + + # Call the function with the example inputs + output = get_archived_topics(filtered_topic_ids, topics) + + # Assert that the output matches the expected output + assert output == expected_output diff --git a/lms/djangoapps/discussion/rest_api/utils.py b/lms/djangoapps/discussion/rest_api/utils.py index a0d2e35943..9ea0691228 100644 --- a/lms/djangoapps/discussion/rest_api/utils.py +++ b/lms/djangoapps/discussion/rest_api/utils.py @@ -1,6 +1,7 @@ """ Utils for discussion API. """ +from typing import List, Dict from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.core.paginator import Paginator @@ -92,7 +93,7 @@ def get_usernames_for_course(course_id, page_number, page_size): matched_users_count (int): count of matched users in course matched_users_pages (int): pages of matched users in course """ - matched_users_in_course = User.objects.filter(courseenrollment__course_id=course_id,)\ + matched_users_in_course = User.objects.filter(courseenrollment__course_id=course_id, ) \ .order_by(Length('username').asc()).values_list('username', flat=True) if not matched_users_in_course: return '', 0, 0 @@ -240,15 +241,67 @@ def create_topics_v3_structure(blocks, topics): value['courseware'] = True courseware_topics.append(value) value['children'] = create_discussion_children_from_ids( - value['children'], + value.get('children', []), blocks, topics, ) subsections = value.get('children') for subsection in subsections: subsection['children'] = create_discussion_children_from_ids( - subsection['children'], + subsection.get('children', []), blocks, topics, ) - return non_courseware_topics + courseware_topics + + structured_topics = non_courseware_topics + courseware_topics + topic_ids = get_topic_ids_from_topics(topics) + + # Remove all topic ids that are contained in the structured topics + for chapter in structured_topics: + for sequential in chapter.get('children', []): + for item in sequential['children']: + topic_ids.remove(item['id']) + + archived_topics = { + 'id': "archived", + 'children': get_archived_topics(topic_ids, topics) + } + if archived_topics['children']: + structured_topics.append(archived_topics) + + return structured_topics + + +def get_topic_ids_from_topics(topics: List[Dict[str, str]]) -> List[str]: + """ + This function takes a list of topics and returns a list of the topic ids. + + Args: + - topics (List[Dict[str, str]]): A list of topic dictionaries. Each dictionary should have an 'id' field. + + Returns: + - A list of topic ids, extracted from the input list of topics. + """ + return [topic['id'] for topic in topics] + + +def get_archived_topics(filtered_topic_ids: List[str], topics: List[Dict[str, str]]) -> List[Dict[str, str]]: + """ + This function takes a list of topic ids and a list of topics, and returns the list of archived topics. + + A topic is considered archived if it has a non-null `usage_key` field. + + Args: + - filtered_topic_ids (List[str]): A list of topic ids to filter on. + - topics (List[Dict[str, str]]): A list of topic dictionaries. + - Each dictionary should have a 'id' and a 'usage_key' field. + + Returns: + - A list of archived topic dictionaries, with the same format as the input topics. + """ + archived_topics = [] + for topic_id in filtered_topic_ids: + for topic in topics: + if topic['id'] == topic_id and topic['usage_key'] is not None: + archived_topics.append(topic) + return archived_topics