Skip to content

Commit

Permalink
Merge branch 'master' into kireiev/AXM-549/feat/upstream_PR_active_in…
Browse files Browse the repository at this point in the history
…active_courses_API
  • Loading branch information
KyryloKireiev authored Oct 30, 2024
2 parents bc71be4 + 10a876f commit 4015aab
Show file tree
Hide file tree
Showing 59 changed files with 1,217 additions and 975 deletions.
2 changes: 2 additions & 0 deletions catalog-info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ metadata:
- url: "https://docs.openedx.org"
title: "Documentation"
icon: "Web"
annotations:
openedx.org/release: "master"
spec:
owner: group:wg-maintenance-edx-platform
type: 'service'
Expand Down
15 changes: 15 additions & 0 deletions cms/djangoapps/contentstore/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,3 +974,18 @@ def test_if_content_is_plain_text(self):
assert Notification.objects.all().count() == 1
notification = Notification.objects.first()
assert notification.content == "<p><strong>content Sub content heading</strong></p>"

def test_if_html_unescapes(self):
"""
Tests if html unescapes when creating content of course update notification
"""
user = UserFactory()
CourseEnrollment.enroll(user=user, course_key=self.course.id)
assert Notification.objects.all().count() == 0
content = "<p>&lt;p&gt; &amp;nbsp;&lt;/p&gt;<br />"\
"&lt;p&gt;abcd&lt;/p&gt;<br />"\
"&lt;p&gt;&amp;nbsp;&lt;/p&gt;<br /></p>"
send_course_update_notification(self.course.id, content, self.user)
assert Notification.objects.all().count() == 1
notification = Notification.objects.first()
assert notification.content == "<p><strong>abcd</strong></p>"
2 changes: 2 additions & 0 deletions cms/djangoapps/contentstore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from __future__ import annotations
import configparser
import html
import logging
import re
from collections import defaultdict
Expand Down Expand Up @@ -2258,6 +2259,7 @@ def clean_html_body(html_body):
"""
Get html body, remove tags and limit to 500 characters
"""
html_body = html.unescape(html_body).strip()
html_body = BeautifulSoup(Truncator(html_body).chars(500, html=True), 'html.parser')
text_content = html_body.get_text(separator=" ").strip()
text_content = text_content.replace('\n', '').replace('\r', '')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ def setUp(self):
self.store = modulestore()

self.library = library_api.create_library(
library_type=library_api.COMPLEX,
org=Organization.objects.create(name="Test Org", short_name="CL-TEST"),
slug="lib",
title="Library",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ def _create_block(request):
"locator": str(created_xblock.location),
"courseKey": str(created_xblock.location.course_key),
"static_file_notices": asdict(notices),
"upstreamRef": str(created_xblock.upstream),
})

category = request.json["category"]
Expand Down
4 changes: 1 addition & 3 deletions cms/static/js/factories/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ define([
], function($, CourseDetailsModel, MainView) {
'use strict';

return function(detailsUrl, showMinGradeWarning, showCertificateAvailableDate, upgradeDeadline, useV2CertDisplaySettings) {
return function(detailsUrl, showMinGradeWarning, showCertificateAvailableDate, upgradeDeadline) {
var model;
// highlighting labels when fields are focused in
$('form :input')
Expand All @@ -23,7 +23,6 @@ define([
model = new CourseDetailsModel();
model.urlRoot = detailsUrl;
model.showCertificateAvailableDate = showCertificateAvailableDate;
model.useV2CertDisplaySettings = useV2CertDisplaySettings;
model.set('upgrade_deadline', upgradeDeadline);
model.fetch({
// eslint-disable-next-line no-shadow
Expand All @@ -33,7 +32,6 @@ define([
model: model,
showMinGradeWarning: showMinGradeWarning
});
editor.useV2CertDisplaySettings = useV2CertDisplaySettings;
editor.render();
},
reset: true,
Expand Down
54 changes: 26 additions & 28 deletions cms/static/js/models/settings/course_details.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,35 +84,33 @@ function(Backbone, _, gettext, ValidationHelpers, DateUtils, StringUtils) {
);
}

if (this.useV2CertDisplaySettings) {
if (
newattrs.certificates_display_behavior
&& !(Object.values(CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS).includes(newattrs.certificates_display_behavior))
) {
errors.certificates_display_behavior = StringUtils.interpolate(
gettext(
'The certificate display behavior must be one of: {behavior_options}'
),
{
behavior_options: Object.values(CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS).join(', ')
}
);
}
if (
newattrs.certificates_display_behavior
&& !(Object.values(CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS).includes(newattrs.certificates_display_behavior))
) {
errors.certificates_display_behavior = StringUtils.interpolate(
gettext(
'The certificate display behavior must be one of: {behavior_options}'
),
{
behavior_options: Object.values(CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS).join(', ')
}
);
}

// Throw error if there's a value for certificate_available_date
if (
(newattrs.certificate_available_date && newattrs.certificates_display_behavior != CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE)
|| (!newattrs.certificate_available_date && newattrs.certificates_display_behavior == CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE)
) {
errors.certificates_display_behavior = StringUtils.interpolate(
gettext(
'The certificates display behavior must be {valid_option} if certificate available date is set.'
),
{
valid_option: CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE
}
);
}
// Throw error if there's a value for certificate_available_date
if (
(newattrs.certificate_available_date && newattrs.certificates_display_behavior != CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE)
|| (!newattrs.certificate_available_date && newattrs.certificates_display_behavior == CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE)
) {
errors.certificates_display_behavior = StringUtils.interpolate(
gettext(
'The certificates display behavior must be {valid_option} if certificate available date is set.'
),
{
valid_option: CERTIFICATES_DISPLAY_BEHAVIOR_OPTIONS.END_WITH_DATE
}
);
}

if (newattrs.intro_video && newattrs.intro_video !== this.get('intro_video')) {
Expand Down
3 changes: 0 additions & 3 deletions cms/static/js/views/settings/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,6 @@ function(ValidatingView, CodeMirror, _, $, ui, DateUtils, FileUploadModel,
Hides and clears the certificate available date field if a display behavior that doesn't use it is
chosen. Because we are clearing it, toggling back to "end_with_date" will require re-entering the date
*/
if (!this.useV2CertDisplaySettings) {
return;
}
// eslint-disable-next-line prefer-const
let showDatepicker = this.model.get('certificates_display_behavior') == 'end_with_date';
// eslint-disable-next-line prefer-const
Expand Down
2 changes: 0 additions & 2 deletions common/djangoapps/util/tests/test_db.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Tests for util.db module."""

from io import StringIO
import unittest

import ddt
from django.core.management import call_command
Expand Down Expand Up @@ -121,7 +120,6 @@ class MigrationTests(TestCase):
Tests for migrations.
"""

@unittest.skip('Skipping temporarily to drop column in table')
@override_settings(MIGRATION_MODULES={})
def test_migrations_are_in_sync(self):
"""
Expand Down
75 changes: 64 additions & 11 deletions docs/docs_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import all the Studio code.
"""


from textwrap import dedent
import os

from openedx.core.lib.derived import derive_settings
Expand All @@ -27,18 +27,71 @@
FEATURES[key] = True

# Settings that will fail if we enable them, and we don't need them for docs anyway.
FEATURES['RUN_AS_ANALYTICS_SERVER_ENABLED'] = False
FEATURES['ENABLE_SOFTWARE_SECURE_FAKE'] = False
FEATURES['ENABLE_MKTG_SITE'] = False
FEATURES["RUN_AS_ANALYTICS_SERVER_ENABLED"] = False
FEATURES["ENABLE_SOFTWARE_SECURE_FAKE"] = False
FEATURES["ENABLE_MKTG_SITE"] = False

INSTALLED_APPS.extend(
[
"cms.djangoapps.contentstore.apps.ContentstoreConfig",
"cms.djangoapps.course_creators",
"cms.djangoapps.xblock_config.apps.XBlockConfig",
"lms.djangoapps.lti_provider",
]
)

# Swagger generation details
openapi_security_info_basic = (
"Obtain with a `POST` request to `/user/v1/account/login_session/`. "
"If needed, copy the cookies from the response to your new call."
)
openapi_security_info_jwt = dedent(
"""
Obtain by making a `POST` request to `/oauth2/v1/access_token`.
You will need to be logged in and have a client ID and secret already created.
INSTALLED_APPS.extend([
'cms.djangoapps.contentstore.apps.ContentstoreConfig',
'cms.djangoapps.course_creators',
'cms.djangoapps.xblock_config.apps.XBlockConfig',
'lms.djangoapps.lti_provider',
])
Your request should have the headers
```
'Content-Type': 'application/x-www-form-urlencoded'
```
Your request should have the data payload
```
'grant_type': 'client_credentials'
'client_id': [your client ID]
'client_secret': [your client secret]
'token_type': 'jwt'
```
Your JWT will be returned in the response as `access_token`. Prefix with `JWT ` in your header.
"""
)
openapi_security_info_csrf = (
"Obtain by making a `GET` request to `/csrf/api/v1/token`. The token will be in the response cookie `csrftoken`."
)
SWAGGER_SETTINGS["SECURITY_DEFINITIONS"] = {
"Basic": {
"type": "basic",
"description": openapi_security_info_basic,
},
"jwt": {
"type": "apiKey",
"name": "Authorization",
"in": "header",
"description": openapi_security_info_jwt,
},
"csrf": {
"type": "apiKey",
"name": "X-CSRFToken",
"in": "header",
"description": openapi_security_info_csrf,
},
}


COMMON_TEST_DATA_ROOT = ''
COMMON_TEST_DATA_ROOT = ""

derive_settings(__name__)
Loading

0 comments on commit 4015aab

Please sign in to comment.