Skip to content

Commit

Permalink
Merge branch 'master' into generate_bulk_certificate_exceptions-to-drf
Browse files Browse the repository at this point in the history
  • Loading branch information
awais786 authored Oct 5, 2024
2 parents 5bd2065 + c34ccff commit 9e312c8
Show file tree
Hide file tree
Showing 57 changed files with 797 additions and 465 deletions.
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2
build:
os: "ubuntu-22.04"
tools:
python: "3.8"
python: "3.12"

sphinx:
configuration: docs/conf.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ class CourseSettingsSerializer(serializers.Serializer):
show_min_grade_warning = serializers.BooleanField()
sidebar_html_enabled = serializers.BooleanField()
upgrade_deadline = serializers.DateTimeField(allow_null=True)
use_v2_cert_display_settings = serializers.BooleanField()
2 changes: 0 additions & 2 deletions cms/djangoapps/contentstore/rest_api/v1/views/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ def get(self, request: Request, course_id: str):
"show_min_grade_warning": false,
"sidebar_html_enabled": true,
"upgrade_deadline": null,
"use_v2_cert_display_settings": false
}
```
"""
Expand All @@ -112,7 +111,6 @@ def get(self, request: Request, course_id: str):
'course_display_name_with_default': course_block.display_name_with_default,
'platform_name': settings.PLATFORM_NAME,
'licensing_enabled': settings.FEATURES.get("LICENSING", False),
'use_v2_cert_display_settings': settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS", False),
})

serializer = CourseSettingsSerializer(settings_context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def test_course_settings_response(self):
"show_min_grade_warning": False,
"upgrade_deadline": None,
"licensing_enabled": False,
"use_v2_cert_display_settings": False,
}

self.assertEqual(response.status_code, status.HTTP_200_OK)
Expand Down
53 changes: 46 additions & 7 deletions cms/djangoapps/contentstore/views/tests/test_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -3674,14 +3674,15 @@ def test_special_exam_xblock_info(
@patch_does_backend_support_onboarding
@patch_get_exam_by_content_id_success
@ddt.data(
("lti_external", False),
("other_proctoring_backend", True),
("lti_external", False, None),
("other_proctoring_backend", True, "test_url"),
)
@ddt.unpack
def test_support_onboarding_is_correct_depending_on_lti_external(
def test_proctoring_values_correct_depending_on_lti_external(
self,
external_id,
expected_value,
expected_supports_onboarding_value,
expected_proctoring_link,
mock_get_exam_by_content_id,
mock_does_backend_support_onboarding,
_mock_get_exam_configuration_dashboard_url,
Expand All @@ -3691,8 +3692,9 @@ def test_support_onboarding_is_correct_depending_on_lti_external(
category="sequential",
display_name="Test Lesson 1",
user_id=self.user.id,
is_proctored_enabled=False,
is_time_limited=False,
is_proctored_enabled=True,
is_time_limited=True,
default_time_limit_minutes=100,
is_onboarding_exam=False,
)

Expand All @@ -3709,7 +3711,8 @@ def test_support_onboarding_is_correct_depending_on_lti_external(
include_children_predicate=ALWAYS,
course=self.course,
)
assert xblock_info["supports_onboarding"] is expected_value
assert xblock_info["supports_onboarding"] is expected_supports_onboarding_value
assert xblock_info["proctoring_exam_configuration_link"] == expected_proctoring_link

@patch_get_exam_configuration_dashboard_url
@patch_does_backend_support_onboarding
Expand Down Expand Up @@ -3773,6 +3776,42 @@ def test_xblock_was_never_proctortrack_proctored_exam(
assert xblock_info["was_exam_ever_linked_with_external"] is False
assert mock_get_exam_by_content_id.call_count == 1

@patch_get_exam_configuration_dashboard_url
@patch_does_backend_support_onboarding
@patch_get_exam_by_content_id_success
def test_special_exam_xblock_info_get_dashboard_error(
self,
mock_get_exam_by_content_id,
_mock_does_backend_support_onboarding,
mock_get_exam_configuration_dashboard_url,
):
sequential = BlockFactory.create(
parent_location=self.chapter.location,
category="sequential",
display_name="Test Lesson 1",
user_id=self.user.id,
is_proctored_enabled=True,
is_time_limited=True,
default_time_limit_minutes=100,
is_onboarding_exam=False,
)
sequential = modulestore().get_item(sequential.location)
mock_get_exam_configuration_dashboard_url.side_effect = Exception("proctoring error")
xblock_info = create_xblock_info(
sequential,
include_child_info=True,
include_children_predicate=ALWAYS,
)

# no errors should be raised and proctoring_exam_configuration_link is None
assert xblock_info["is_proctored_exam"] is True
assert xblock_info["was_exam_ever_linked_with_external"] is True
assert xblock_info["is_time_limited"] is True
assert xblock_info["default_time_limit_minutes"] == 100
assert xblock_info["proctoring_exam_configuration_link"] is None
assert xblock_info["supports_onboarding"] is True
assert xblock_info["is_onboarding_exam"] is False


class TestLibraryXBlockInfo(ModuleStoreTestCase):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1159,12 +1159,19 @@ def create_xblock_info( # lint-amnesty, pylint: disable=too-many-statements
supports_onboarding = False

proctoring_exam_configuration_link = None
if xblock.is_proctored_exam:
proctoring_exam_configuration_link = (
get_exam_configuration_dashboard_url(
course.id, xblock_info["id"]

# only call get_exam_configuration_dashboard_url if not using an LTI proctoring provider
if xblock.is_proctored_exam and (course.proctoring_provider != 'lti_external'):
try:
proctoring_exam_configuration_link = (
get_exam_configuration_dashboard_url(
course.id, xblock_info["id"]
)
)
except Exception as e: # pylint: disable=broad-except
log.error(
f"Error while getting proctoring exam configuration link: {e}"
)
)

if course.proctoring_provider == "proctortrack":
show_review_rules = SHOW_REVIEW_RULES_FLAG.is_enabled(
Expand Down
11 changes: 0 additions & 11 deletions cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,17 +468,6 @@
# .. toggle_tickets: https://github.com/openedx/edx-platform/pull/26106
'ENABLE_HELP_LINK': True,

# .. toggle_name: FEATURES['ENABLE_V2_CERT_DISPLAY_SETTINGS']
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: Whether to use the reimagined certificates_display_behavior and certificate_available_date
# .. settings. Will eventually become the default.
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2021-07-26
# .. toggle_target_removal_date: 2021-10-01
# .. toggle_tickets: 'https://openedx.atlassian.net/browse/MICROBA-1405'
'ENABLE_V2_CERT_DISPLAY_SETTINGS': False,

# .. toggle_name: FEATURES['ENABLE_INTEGRITY_SIGNATURE']
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
Expand Down
68 changes: 27 additions & 41 deletions cms/templates/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
${show_min_grade_warning | n, dump_js_escaped_json},
${can_show_certificate_available_date_field(context_course) | n, dump_js_escaped_json},
"${upgrade_deadline | n, js_escaped_string}",
${settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS") | n, dump_js_escaped_json}
);
});
</%block>
Expand Down Expand Up @@ -251,58 +250,45 @@ <h2 class="title-2">${_('Course Schedule')}</h2>
</li>
</ol>

<%
use_v2_cert_display_settings = settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS", False)
%>
% if can_show_certificate_available_date_field(context_course):
<ol class="list-input">
<li class="field-group field-group-certificate-available" id="certificate-available">
<div class="field date" id="field-certificates-display-behavior">
<label for="certificates-display-behavior">${_("Certificates Display Behavior")}</label>
% if use_v2_cert_display_settings:
<select id="certificates-display-behavior">
<option value="early_no_info">${_("Immediately upon passing")}</option>
<option value="end">${_("End date of course")}</option>
<option value="end_with_date">${_("A date after the course end date")}</option>
</select>
% else:
<input id="certificates-display-behavior" type="text">
% endif
<select id="certificates-display-behavior">
<option value="early_no_info">${_("Immediately upon passing")}</option>
<option value="end">${_("End date of course")}</option>
<option value="end_with_date">${_("A date after the course end date")}</option>
</select>
<span class="tip tip-stacked">${_("Certificates are awarded at the end of a course run")}</span>

% if use_v2_cert_display_settings:
<!-- Collapsible -->
<div class="collapsible">
<div id="certificate-display-behavior-collapsible-trigger" class="collapsible-trigger" role="button" tabindex="0" aria-expanded="false">
<span>
<span class="icon icon-inline fa fa-info-circle" aria-hidden="true"></span>
${_("Read more about this setting")}
</span>
<!-- Collapsible -->
<div class="collapsible">
<div id="certificate-display-behavior-collapsible-trigger" class="collapsible-trigger" role="button" tabindex="0" aria-expanded="false">
<span>
<span class="icon icon-inline fa fa-info-circle" aria-hidden="true"></span>
${_("Read more about this setting")}
</span>
</div>
<div id="certificate-display-behavior-collapsible-content" class="collapsible-content collapsed">
<p>${_("In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design)")}</p>
<div>
<div class="collapsible-description-heading">${_("Immediately upon passing")}</div>
<div class="collapsible-description-description">${_("Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.")}</div>
</div>
<div id="certificate-display-behavior-collapsible-content" class="collapsible-content collapsed">
<p>${_("In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design)")}</p>
<div>
<div class="collapsible-description-heading">${_("Immediately upon passing")}</div>
<div class="collapsible-description-description">${_("Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("On course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate once the end date of the course has elapsed.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("A date after the course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate after the date that you set has elapsed.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("On course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate once the end date of the course has elapsed.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("A date after the course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate after the date that you set has elapsed.")}</div>
</div>
</div>
% endif
</div>
</div>

% if use_v2_cert_display_settings:
<div class="field date hidden" id="field-certificate-available-date" >
% else:
<div class="field date" id="field-certificate-available-date" >
% endif
<div class="field date hidden" id="field-certificate-available-date" >
<label for="certificate-available-date">${_("Certificates Available Date")}</label>
<input type="text" class="certificate-available-date date start datepicker" id="certificate-available-date" placeholder="MM/DD/YYYY" autocomplete="off" />
<span class="icon icon-inline fa fa-calendar-check-o datepicker-icon" aria-hidden="true"></span>
Expand Down
21 changes: 7 additions & 14 deletions common/djangoapps/student/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,21 +646,14 @@ def _is_certificate_earned_but_not_available(course_overview, status):
(bool): True if the user earned the certificate but it's hidden due to display behavior, else False
"""
if settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS"):
return (
not certificates_viewable_for_course(course_overview)
and CertificateStatuses.is_passing_status(status)
and course_overview.certificates_display_behavior in (
CertificatesDisplayBehaviors.END_WITH_DATE,
CertificatesDisplayBehaviors.END
)
)
else:
return (
not certificates_viewable_for_course(course_overview) and
CertificateStatuses.is_passing_status(status) and
course_overview.certificate_available_date
return (
not certificates_viewable_for_course(course_overview)
and CertificateStatuses.is_passing_status(status)
and course_overview.certificates_display_behavior in (
CertificatesDisplayBehaviors.END_WITH_DATE,
CertificatesDisplayBehaviors.END
)
)


def process_survey_link(survey_link, user):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ def test_verification_signal(self):
"""
Verification signal is sent upon approval.
"""
with mock.patch('openedx_events.learning.signals.IDV_ATTEMPT_APPROVED.send_event') as mock_signal:
with mock.patch('openedx.core.djangoapps.signals.signals.LEARNER_SSO_VERIFIED.send_robust') as mock_signal:
# Begin the pipeline.
pipeline.set_id_verification_status(
auth_entry=pipeline.AUTH_ENTRY_LOGIN,
Expand Down
Binary file modified common/static/data/geoip/GeoLite2-Country.mmdb
Binary file not shown.
9 changes: 4 additions & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@
except git.InvalidGitRepositoryError:
edx_platform_version = "master"

featuretoggles_source_path = edxplatform_source_path
featuretoggles_source_path = str(edxplatform_source_path)
featuretoggles_repo_url = edxplatform_repo_url
featuretoggles_repo_version = edx_platform_version

settings_source_path = edxplatform_source_path
settings_source_path = str(edxplatform_source_path)
settings_repo_url = edxplatform_repo_url
settings_repo_version = edx_platform_version

Expand All @@ -108,7 +108,7 @@
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'en'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand Down Expand Up @@ -170,7 +170,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# html_static_path = ['_static']

# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
Expand Down Expand Up @@ -274,7 +274,6 @@

# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'https://docs.python.org/2.7': None,
'django': ('https://docs.djangoproject.com/en/1.11/', 'https://docs.djangoproject.com/en/1.11/_objects/'),
}

Expand Down
14 changes: 14 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ locations.
how-tos/index
references/index
concepts/index
hooks/index
extensions/tinymce_plugins

.. grid:: 1 2 2 2
:gutter: 3
Expand Down Expand Up @@ -74,6 +76,18 @@ locations.
:outline:
:expand:

.. grid-item-card:: Hooks and Extensions
:class-card: sd-shadow-md sd-p-2
:class-footer: sd-border-0

* :doc:`hooks/index`
* :doc:`extensions/tinymce_plugins`
+++
.. button-ref:: hooks/index
:color: primary
:outline:
:expand:


Change History
**************
Expand Down
1 change: 1 addition & 0 deletions lms/djangoapps/bulk_email/message_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ class BulkEmail(BaseMessageType):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.options['from_address'] = kwargs['context']['from_address']
self.options['transactional'] = True
Loading

0 comments on commit 9e312c8

Please sign in to comment.