Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: test pr master #616

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3c1b81c
fix: timeout error for legacy page (#33965)
KristinAoki Dec 21, 2023
3f65347
fix: correct EXAMS_DATE_MICROFRONTEND_URL devstack setting
MichaelRoytman Dec 22, 2023
13cee3e
chore(i18n): update translations
Dec 24, 2023
6780345
chore: geoip2: update maxmind geolite country database
Dec 27, 2023
dd4a97d
feat: added thread_flagged and comment_flagged signals in legacy disc…
muhammadadeeltajamul Dec 29, 2023
30c029f
feat: added comment_endorsed, thread_followed and thread_unfollowed s…
muhammadadeeltajamul Dec 29, 2023
8a9e19a
temp: add temporary logs for course wide notifications
Dec 28, 2023
c2383fa
feat: Show notification types with respect to user form roles (#33927)
AhtishamShahid Jan 2, 2024
4ead1d0
feat: Upgrade Python dependency edx-enterprise
MueezKhan246 Jan 2, 2024
02574af
fix: Update the date to the max year possible in a test. (#33994)
dianakhuang Jan 2, 2024
145609c
chore(i18n): update translations
Jan 2, 2024
0b8ba84
Merge branch 'master' into MueezKhan246/upgrade-edx-enterprise-c2383fa
MueezKhan246 Jan 2, 2024
5e7a91f
Merge pull request #33989 from openedx/MueezKhan246/upgrade-edx-enter…
MueezKhan246 Jan 2, 2024
ec86398
fix: respect ENABLE_NEW_STRUCTURE_DISCUSSIONS flag in course import (…
asadali145 Jan 3, 2024
a471e59
feat: progress logging when doing a reindex
ashultz0 Jan 3, 2024
5001918
Merge pull request #33999 from openedx/ashultz0/chatty-reindex-cmd
ashultz0 Jan 3, 2024
49537d5
docs: add diagrams for course cert awarding and revocation
justinhynes Jan 3, 2024
13ff28e
chore: geoip2: update maxmind geolite country database
Jan 3, 2024
986737a
fix: Incorrect ORA assignment link in Dates tab (#33984)
arslanashraf7 Jan 4, 2024
099fe14
feat: Upgrade Python dependency edx-enterprise
hamzawaleed01 Jan 4, 2024
7d8401c
Merge pull request #33972 from openedx/MichaelRoytman/devstack-exams-…
MichaelRoytman Jan 4, 2024
12c8418
Merge branch 'master' of github.com:openedx/edx-platform into hamzawa…
hamzawaleed01 Jan 4, 2024
96b360a
Merge pull request #34009 from openedx/hamzawaleed01/upgrade-edx-ente…
hamzawaleed01 Jan 4, 2024
b811b29
chore: bump ORA to 6.0.22 (#34010)
nsprenkle Jan 4, 2024
2209549
Merge pull request #34000 from openedx/jhynes/APER-2551
justinhynes Jan 5, 2024
9cd1d7c
feat: create DRF endpoint to get course index context (#33943)
navinkarkera Jan 8, 2024
9979ea2
fix: prevent transcript feedback widget from appearing when there is no
Guilleves Jan 8, 2024
2dee428
Merge pull request #34014 from openedx/hot-fix-hide-feedback-widget-w…
Guilleves Jan 8, 2024
3c9ac69
chore: update openedx-learning version to 0.4.1 (#34015)
rpenido Jan 8, 2024
83d104f
chore(i18n): update translations
Jan 8, 2024
efaef45
fix: protect video transcript handler from scraper (#34017)
connorhaugh Jan 8, 2024
5e66fe9
feat: sample commit
kaustavb12 Jan 9, 2024
d53bbca
test: test
kaustavb12 May 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -7,6 +7,7 @@
pre-requirements pull pull_translations push_translations requirements shell swagger \
technical-docs test-requirements ubuntu-requirements upgrade-package upgrade


# Careful with mktemp syntax: it has to work on Mac and Ubuntu, which have differences.
PRIVATE_FILES := $(shell mktemp -u /tmp/private_files.XXXXXX)

Expand Down
1 change: 1 addition & 0 deletions README.rst
Expand Up @@ -25,6 +25,7 @@ platform. Functionally, the edx-platform repository provides two services:
* CMS (Content Management Service), which powers Open edX Studio, the platform's learning content authoring environment; and
* LMS (Learning Management Service), which delivers learning content.


Documentation
*************

Expand Down
Expand Up @@ -3,6 +3,7 @@

import logging
from textwrap import dedent
from time import time

from django.core.management import BaseCommand, CommandError
from elasticsearch import exceptions
Expand All @@ -24,7 +25,7 @@ class Command(BaseCommand):
Examples:

./manage.py reindex_course <course_id_1> <course_id_2> ... - reindexes courses with provided keys
./manage.py reindex_course --all - reindexes all available courses
./manage.py reindex_course --all --warning - reindexes all available courses with quieter logging
./manage.py reindex_course --setup - reindexes all courses for devstack setup
"""
help = dedent(__doc__)
Expand All @@ -40,6 +41,10 @@ def add_arguments(self, parser):
parser.add_argument('--setup',
action='store_true',
help='Reindex all courses on developers stack setup')
parser.add_argument('--warning',
action='store_true',
help='Reduce logging to a WARNING level of output for progress tracking'
)

def _parse_course_key(self, raw_value):
""" Parses course key from string """
Expand All @@ -61,13 +66,18 @@ def handle(self, *args, **options):
course_ids = options['course_ids']
all_option = options['all']
setup_option = options['setup']
readable_option = options['warning']
index_all_courses_option = all_option or setup_option

if (not len(course_ids) and not index_all_courses_option) or (len(course_ids) and index_all_courses_option): # lint-amnesty, pylint: disable=len-as-condition
raise CommandError("reindex_course requires one or more <course_id>s OR the --all or --setup flags.")

store = modulestore()

if readable_option:
logging.disable(level=logging.INFO)
logging.warning('Reducing logging to WARNING level for easier progress tracking')

if index_all_courses_option:
index_names = (CoursewareSearchIndexer.INDEX_NAME, CourseAboutSearchIndexer.INDEX_NAME)
if setup_option:
Expand Down Expand Up @@ -98,8 +108,18 @@ def handle(self, *args, **options):
# in case course keys are provided as arguments
course_keys = list(map(self._parse_course_key, course_ids))

total = len(course_keys)
logging.warning(f'Reindexing {total} courses')
reindexed = 0
start = time()

for course_key in course_keys:
try:
CoursewareSearchIndexer.do_course_reindex(store, course_key)
reindexed += 1
if reindexed % 10 == 0 or reindexed == total:
now = time()
t = now - start
logging.warning(f'{reindexed}/{total} reindexed in {t:.1f} seconds')
except Exception as exc: # lint-amnesty, pylint: disable=broad-except
logging.exception('Error indexing course %s due to the error: %s', course_key, exc)
20 changes: 20 additions & 0 deletions cms/djangoapps/contentstore/rest_api/serializers/common.py
Expand Up @@ -50,3 +50,23 @@ def to_internal_value(self, data):
)

return ret


class ProctoringErrorModelSerializer(serializers.Serializer):
"""
Serializer for proctoring error model item.
"""
deprecated = serializers.BooleanField()
display_name = serializers.CharField()
help = serializers.CharField()
hide_on_enabled_publisher = serializers.BooleanField()
value = serializers.CharField()


class ProctoringErrorListSerializer(serializers.Serializer):
"""
Serializer for proctoring error list.
"""
key = serializers.CharField()
message = serializers.CharField()
model = ProctoringErrorModelSerializer()
Expand Up @@ -4,6 +4,7 @@
from .course_details import CourseDetailsSerializer
from .course_rerun import CourseRerunSerializer
from .course_team import CourseTeamSerializer
from .course_index import CourseIndexSerializer
from .grading import CourseGradingModelSerializer, CourseGradingSerializer
from .home import CourseHomeSerializer, CourseTabSerializer, LibraryTabSerializer
from .proctoring import (
Expand Down
@@ -0,0 +1,31 @@
"""
API Serializers for course index
"""

from rest_framework import serializers

from cms.djangoapps.contentstore.rest_api.serializers.common import ProctoringErrorListSerializer


class InitialIndexStateSerializer(serializers.Serializer):
"""Serializer for initial course index state"""
expanded_locators = serializers.ListSerializer(child=serializers.CharField())
locator_to_show = serializers.CharField()


class CourseIndexSerializer(serializers.Serializer):
"""Serializer for course index"""
course_release_date = serializers.CharField()
course_structure = serializers.DictField()
deprecated_blocks_info = serializers.DictField()
discussions_incontext_feedback_url = serializers.CharField()
discussions_incontext_learnmore_url = serializers.CharField()
initial_state = InitialIndexStateSerializer()
initial_user_clipboard = serializers.DictField()
language_code = serializers.CharField()
lms_link = serializers.CharField()
mfe_proctored_exam_settings_url = serializers.CharField()
notification_dismiss_url = serializers.CharField()
proctoring_errors = ProctoringErrorListSerializer(many=True)
reindex_link = serializers.CharField()
rerun_notification_id = serializers.IntegerField()
Expand Up @@ -4,6 +4,7 @@

from rest_framework import serializers

from cms.djangoapps.contentstore.rest_api.serializers.common import ProctoringErrorListSerializer
from xmodule.course_block import get_available_providers


Expand Down Expand Up @@ -31,26 +32,6 @@ class ProctoredExamConfigurationSerializer(serializers.Serializer):
course_start_date = serializers.DateTimeField()


class ProctoringErrorModelSerializer(serializers.Serializer):
"""
Serializer for proctoring error model item.
"""
deprecated = serializers.BooleanField()
display_name = serializers.CharField()
help = serializers.CharField()
hide_on_enabled_publisher = serializers.BooleanField()
value = serializers.CharField()


class ProctoringErrorListSerializer(serializers.Serializer):
"""
Serializer for proctoring error list.
"""
key = serializers.CharField()
message = serializers.CharField()
model = ProctoringErrorModelSerializer()


class ProctoringErrorsSerializer(serializers.Serializer):
"""
Serializer for proctoring errors with url to proctored exam settings.
Expand Down
4 changes: 0 additions & 4 deletions cms/djangoapps/contentstore/rest_api/v1/serializers/videos.py
Expand Up @@ -56,9 +56,6 @@ class VideoModelSerializer(serializers.Serializer):
transcripts = serializers.ListField(
child=serializers.CharField()
)
usage_locations = serializers.ListField(
child=serializers.DictField()
)


class VideoActiveTranscriptPreferencesSerializer(serializers.Serializer):
Expand Down Expand Up @@ -99,7 +96,6 @@ class CourseVideosSerializer(serializers.Serializer):
child=serializers.CharField()
)
)
# transcript_available_languages = serializers.BooleanField(required=False, allow_null=True)
video_transcript_settings = VideoTranscriptSettingsSerializer()
pagination_context = serializers.DictField(
child=serializers.CharField(),
Expand Down
6 changes: 6 additions & 0 deletions cms/djangoapps/contentstore/rest_api/v1/urls.py
Expand Up @@ -7,6 +7,7 @@
from .views import (
CourseDetailsView,
CourseTeamView,
CourseIndexView,
CourseGradingView,
CourseRerunView,
CourseSettingsView,
Expand Down Expand Up @@ -69,6 +70,11 @@
CourseSettingsView.as_view(),
name="course_settings"
),
re_path(
fr'^course_index/{COURSE_ID_PATTERN}$',
CourseIndexView.as_view(),
name="course_index"
),
re_path(
fr'^course_details/{COURSE_ID_PATTERN}$',
CourseDetailsView.as_view(),
Expand Down
1 change: 1 addition & 0 deletions cms/djangoapps/contentstore/rest_api/v1/views/__init__.py
Expand Up @@ -2,6 +2,7 @@
Views for v1 contentstore API.
"""
from .course_details import CourseDetailsView
from .course_index import CourseIndexView
from .course_team import CourseTeamView
from .course_rerun import CourseRerunView
from .grading import CourseGradingView
Expand Down
98 changes: 98 additions & 0 deletions cms/djangoapps/contentstore/rest_api/v1/views/course_index.py
@@ -0,0 +1,98 @@
"""API Views for course index"""

import edx_api_doc_tools as apidocs
from django.conf import settings
from opaque_keys.edx.keys import CourseKey
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

from cms.djangoapps.contentstore.rest_api.v1.serializers import CourseIndexSerializer
from cms.djangoapps.contentstore.utils import get_course_index_context
from common.djangoapps.student.auth import has_studio_read_access
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, verify_course_exists, view_auth_classes


@view_auth_classes(is_authenticated=True)
class CourseIndexView(DeveloperErrorViewMixin, APIView):
"""View for Course Index"""

@apidocs.schema(
parameters=[
apidocs.string_parameter("course_id", apidocs.ParameterLocation.PATH, description="Course ID"),
apidocs.string_parameter(
"show",
apidocs.ParameterLocation.QUERY,
description="Query param to set initial state which fully expanded to see the item",
)],
responses={
200: CourseIndexSerializer,
401: "The requester is not authenticated.",
403: "The requester cannot access the specified course.",
404: "The requested course does not exist.",
},
)
@verify_course_exists()
def get(self, request: Request, course_id: str):
"""
Get an object containing course index for outline.

**Example Request**

GET /api/contentstore/v1/course_index/{course_id}?show=block-v1:edx+101+y+type@course+block@course

**Response Values**

If the request is successful, an HTTP 200 "OK" response is returned.

The HTTP 200 response contains a single dict that contains keys that
are the course's outline.

**Example Response**

```json
{
"course_release_date": "Set Date",
"course_structure": {},
"deprecated_blocks_info": {
"deprecated_enabled_block_types": [],
"blocks": [],
"advance_settings_url": "/settings/advanced/course-v1:edx+101+y76"
},
"discussions_incontext_feedback_url": "",
"discussions_incontext_learnmore_url": "",
"initial_state": {
"expanded_locators": [
"block-v1:edx+101+y76+type@chapter+block@03de0adc9d1c4cc097062d80eb04abf6",
"block-v1:edx+101+y76+type@sequential+block@8a85e287e30a47e98d8c1f37f74a6a9d"
],
"locator_to_show": "block-v1:edx+101+y76+type@chapter+block@03de0adc9d1c4cc097062d80eb04abf6"
},
"initial_user_clipboard": {
"content": null,
"source_usage_key": "",
"source_context_title": "",
"source_edit_url": ""
},
"language_code": "en",
"lms_link": "//localhost:18000/courses/course-v1:edx+101+y76/jump_to/block-v1:edx+101+y76",
"mfe_proctored_exam_settings_url": "",
"notification_dismiss_url": "/course_notifications/course-v1:edx+101+y76/2",
"proctoring_errors": [],
"reindex_link": "/course/course-v1:edx+101+y76/search_reindex",
"rerun_notification_id": 2
}
```
"""

course_key = CourseKey.from_string(course_id)
if not has_studio_read_access(request.user, course_key):
self.permission_denied(request)
course_index_context = get_course_index_context(request, course_key)
course_index_context.update({
"discussions_incontext_learnmore_url": settings.DISCUSSIONS_INCONTEXT_LEARNMORE_URL,
"discussions_incontext_feedback_url": settings.DISCUSSIONS_INCONTEXT_FEEDBACK_URL,
})

serializer = CourseIndexSerializer(course_index_context)
return Response(serializer.data)