Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
d4cc7b8f
Commit
d4cc7b8f
authored
Jul 06, 2016
by
cahrens
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support level support for Studio xblock creation.
TNL-4670
parent
71bebec5
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
577 additions
and
215 deletions
+577
-215
cms/djangoapps/contentstore/tests/test_contentstore.py
+0
-1
cms/djangoapps/contentstore/tests/test_course_settings.py
+10
-0
cms/djangoapps/contentstore/views/component.py
+135
-18
cms/djangoapps/contentstore/views/tests/test_item.py
+126
-29
cms/djangoapps/models/settings/course_metadata.py
+7
-0
cms/envs/aws.py
+0
-3
cms/envs/common.py
+0
-13
cms/static/js/models/component_template.js
+3
-1
cms/static/js/spec/models/component_template_spec.js
+2
-1
cms/static/js/spec/views/pages/container_spec.js
+141
-6
cms/static/js/spec_helpers/edit_helpers.js
+9
-5
cms/static/js/views/components/add_xblock_menu.js
+14
-3
cms/static/sass/_build-v1.scss
+1
-1
cms/static/sass/elements/_modules.scss
+36
-2
cms/static/sass/partials/_variables.scss
+10
-6
cms/templates/js/add-xblock-component-menu-problem.underscore
+15
-11
cms/templates/js/add-xblock-component-menu.underscore
+9
-6
cms/templates/js/add-xblock-component-support-legend.underscore
+22
-0
cms/templates/js/add-xblock-component-support-level.underscore
+10
-0
common/djangoapps/xblock_django/api.py
+8
-11
common/djangoapps/xblock_django/models.py
+2
-19
common/djangoapps/xblock_django/tests/test_api.py
+7
-16
common/djangoapps/xblock_django/tests/test_models.py
+0
-58
common/lib/xmodule/xmodule/course_module.py
+10
-1
lms/envs/common.py
+0
-4
No files found.
cms/djangoapps/contentstore/tests/test_contentstore.py
View file @
d4cc7b8f
...
@@ -691,7 +691,6 @@ class MiscCourseTests(ContentStoreTestCase):
...
@@ -691,7 +691,6 @@ class MiscCourseTests(ContentStoreTestCase):
# Test that malicious code does not appear in html
# Test that malicious code does not appear in html
self
.
assertNotIn
(
malicious_code
,
resp
.
content
)
self
.
assertNotIn
(
malicious_code
,
resp
.
content
)
@patch
(
'django.conf.settings.DEPRECATED_ADVANCED_COMPONENT_TYPES'
,
[])
def
test_advanced_components_in_edit_unit
(
self
):
def
test_advanced_components_in_edit_unit
(
self
):
# This could be made better, but for now let's just assert that we see the advanced modules mentioned in the page
# This could be made better, but for now let's just assert that we see the advanced modules mentioned in the page
# response HTML
# response HTML
...
...
cms/djangoapps/contentstore/tests/test_course_settings.py
View file @
d4cc7b8f
...
@@ -21,6 +21,7 @@ from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
...
@@ -21,6 +21,7 @@ from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
from
openedx.core.djangoapps.models.course_details
import
CourseDetails
from
openedx.core.djangoapps.models.course_details
import
CourseDetails
from
student.roles
import
CourseInstructorRole
,
CourseStaffRole
from
student.roles
import
CourseInstructorRole
,
CourseStaffRole
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
xblock_django.models
import
XBlockStudioConfigurationFlag
from
xmodule.fields
import
Date
from
xmodule.fields
import
Date
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
...
@@ -784,6 +785,15 @@ class CourseMetadataEditingTest(CourseTestCase):
...
@@ -784,6 +785,15 @@ class CourseMetadataEditingTest(CourseTestCase):
)
)
self
.
assertNotIn
(
'edxnotes'
,
test_model
)
self
.
assertNotIn
(
'edxnotes'
,
test_model
)
def
test_allow_unsupported_xblocks
(
self
):
"""
allow_unsupported_xblocks is only shown in Advanced Settings if
XBlockStudioConfigurationFlag is enabled.
"""
self
.
assertNotIn
(
'allow_unsupported_xblocks'
,
CourseMetadata
.
fetch
(
self
.
fullcourse
))
XBlockStudioConfigurationFlag
(
enabled
=
True
)
.
save
()
self
.
assertIn
(
'allow_unsupported_xblocks'
,
CourseMetadata
.
fetch
(
self
.
fullcourse
))
def
test_validate_from_json_correct_inputs
(
self
):
def
test_validate_from_json_correct_inputs
(
self
):
is_valid
,
errors
,
test_model
=
CourseMetadata
.
validate_and_update_from_json
(
is_valid
,
errors
,
test_model
=
CourseMetadata
.
validate_and_update_from_json
(
self
.
course
,
self
.
course
,
...
...
cms/djangoapps/contentstore/views/component.py
View file @
d4cc7b8f
...
@@ -27,7 +27,10 @@ from opaque_keys.edx.keys import UsageKey
...
@@ -27,7 +27,10 @@ from opaque_keys.edx.keys import UsageKey
from
student.auth
import
has_course_author_access
from
student.auth
import
has_course_author_access
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
xblock_django.models
import
XBlockDisableConfig
from
xblock_django.api
import
disabled_xblocks
,
authorable_xblocks
from
xblock_django.models
import
XBlockStudioConfigurationFlag
__all__
=
[
__all__
=
[
'container_handler'
,
'container_handler'
,
...
@@ -47,17 +50,41 @@ CONTAINER_TEMPLATES = [
...
@@ -47,17 +50,41 @@ CONTAINER_TEMPLATES = [
"basic-modal"
,
"modal-button"
,
"edit-xblock-modal"
,
"basic-modal"
,
"modal-button"
,
"edit-xblock-modal"
,
"editor-mode-button"
,
"upload-dialog"
,
"editor-mode-button"
,
"upload-dialog"
,
"add-xblock-component"
,
"add-xblock-component-button"
,
"add-xblock-component-menu"
,
"add-xblock-component"
,
"add-xblock-component-button"
,
"add-xblock-component-menu"
,
"add-xblock-component-menu-problem"
,
"xblock-string-field-editor"
,
"publish-xblock"
,
"publish-history"
,
"add-xblock-component-support-legend"
,
"add-xblock-component-support-level"
,
"add-xblock-component-menu-problem"
,
"xblock-string-field-editor"
,
"publish-xblock"
,
"publish-history"
,
"unit-outline"
,
"container-message"
,
"license-selector"
,
"unit-outline"
,
"container-message"
,
"license-selector"
,
]
]
def
_advanced_component_types
():
def
_advanced_component_types
(
show_unsupported
):
"""
"""
Return advanced component types which can be created.
Return advanced component types which can be created.
Args:
show_unsupported: if True, unsupported XBlocks may be included in the return value
Returns:
A dict of authorable XBlock types and their support levels (see XBlockStudioConfiguration). For example:
{
"done": "us", # unsupported
"discussion: "fs" # fully supported
}
Note that the support level will be "True" for all XBlocks if XBlockStudioConfigurationFlag
is not enabled.
"""
"""
disabled_create_block_types
=
XBlockDisableConfig
.
disabled_create_block_types
()
enabled_block_types
=
_filter_disabled_blocks
(
ADVANCED_COMPONENT_TYPES
)
return
[
c_type
for
c_type
in
ADVANCED_COMPONENT_TYPES
if
c_type
not
in
disabled_create_block_types
]
if
XBlockStudioConfigurationFlag
.
is_enabled
():
authorable_blocks
=
authorable_xblocks
(
allow_unsupported
=
show_unsupported
)
filtered_blocks
=
{}
for
block
in
authorable_blocks
:
if
block
.
name
in
enabled_block_types
:
filtered_blocks
[
block
.
name
]
=
block
.
support_level
return
filtered_blocks
else
:
all_blocks
=
{}
for
block_name
in
enabled_block_types
:
all_blocks
[
block_name
]
=
True
return
all_blocks
def
_load_mixed_class
(
category
):
def
_load_mixed_class
(
category
):
...
@@ -152,13 +179,14 @@ def get_component_templates(courselike, library=False):
...
@@ -152,13 +179,14 @@ def get_component_templates(courselike, library=False):
"""
"""
Returns the applicable component templates that can be used by the specified course or library.
Returns the applicable component templates that can be used by the specified course or library.
"""
"""
def
create_template_dict
(
name
,
cat
,
boilerplate_name
=
None
,
tab
=
"common"
,
hinted
=
False
):
def
create_template_dict
(
name
,
cat
egory
,
support_level
,
boilerplate_name
=
None
,
tab
=
"common"
,
hinted
=
False
):
"""
"""
Creates a component template dict.
Creates a component template dict.
Parameters
Parameters
display_name: the user-visible name of the component
display_name: the user-visible name of the component
category: the type of component (problem, html, etc.)
category: the type of component (problem, html, etc.)
support_level: the support level of this component
boilerplate_name: name of boilerplate for filling in default values. May be None.
boilerplate_name: name of boilerplate for filling in default values. May be None.
hinted: True if hinted problem else False
hinted: True if hinted problem else False
tab: common(default)/advanced, which tab it goes in
tab: common(default)/advanced, which tab it goes in
...
@@ -166,10 +194,50 @@ def get_component_templates(courselike, library=False):
...
@@ -166,10 +194,50 @@ def get_component_templates(courselike, library=False):
"""
"""
return
{
return
{
"display_name"
:
name
,
"display_name"
:
name
,
"category"
:
cat
,
"category"
:
cat
egory
,
"boilerplate_name"
:
boilerplate_name
,
"boilerplate_name"
:
boilerplate_name
,
"hinted"
:
hinted
,
"hinted"
:
hinted
,
"tab"
:
tab
"tab"
:
tab
,
"support_level"
:
support_level
}
def
component_support_level
(
editable_types
,
name
,
template
=
None
):
"""
Returns the support level for the given xblock name/template combination.
Args:
editable_types: a QuerySet of xblocks with their support levels
name: the name of the xblock
template: optional template for the xblock
Returns:
If XBlockStudioConfigurationFlag is enabled, returns the support level
(see XBlockStudioConfiguration) or False if this xblock name/template combination
has no Studio support at all. If XBlockStudioConfigurationFlag is disabled,
simply returns True.
"""
# If the Studio support feature is disabled, return True for all.
if
not
XBlockStudioConfigurationFlag
.
is_enabled
():
return
True
if
template
is
None
:
template
=
""
extension_index
=
template
.
rfind
(
".yaml"
)
if
extension_index
>=
0
:
template
=
template
[
0
:
extension_index
]
for
block
in
editable_types
:
if
block
.
name
==
name
and
block
.
template
==
template
:
return
block
.
support_level
return
False
def
create_support_legend_dict
():
"""
Returns a dict of settings information for the display of the support level legend.
"""
return
{
"show_legend"
:
XBlockStudioConfigurationFlag
.
is_enabled
(),
"allow_unsupported_xblocks"
:
allow_unsupported
,
"documentation_label"
:
_
(
"{platform_name} Support Levels:"
)
.
format
(
platform_name
=
settings
.
PLATFORM_NAME
)
}
}
component_display_names
=
{
component_display_names
=
{
...
@@ -189,14 +257,25 @@ def get_component_templates(courselike, library=False):
...
@@ -189,14 +257,25 @@ def get_component_templates(courselike, library=False):
if
library
:
if
library
:
component_types
=
[
component
for
component
in
component_types
if
component
!=
'discussion'
]
component_types
=
[
component
for
component
in
component_types
if
component
!=
'discussion'
]
component_types
=
_filter_disabled_blocks
(
component_types
)
# Content Libraries currently don't allow opting in to unsupported xblocks/problem types.
allow_unsupported
=
getattr
(
courselike
,
"allow_unsupported_xblocks"
,
False
)
for
category
in
component_types
:
for
category
in
component_types
:
authorable_variations
=
authorable_xblocks
(
allow_unsupported
=
allow_unsupported
,
name
=
category
)
support_level_without_template
=
component_support_level
(
authorable_variations
,
category
)
templates_for_category
=
[]
templates_for_category
=
[]
component_class
=
_load_mixed_class
(
category
)
component_class
=
_load_mixed_class
(
category
)
if
support_level_without_template
:
# add the default template with localized display name
# add the default template with localized display name
# TODO: Once mixins are defined per-application, rather than per-runtime,
# TODO: Once mixins are defined per-application, rather than per-runtime,
# this should use a cms mixed-in class. (cpennington)
# this should use a cms mixed-in class. (cpennington)
display_name
=
xblock_type_display_name
(
category
,
_
(
'Blank'
))
# this is the Blank Advanced problem
display_name
=
xblock_type_display_name
(
category
,
_
(
'Blank'
))
# this is the Blank Advanced problem
templates_for_category
.
append
(
create_template_dict
(
display_name
,
category
,
None
,
'advanced'
))
templates_for_category
.
append
(
create_template_dict
(
display_name
,
category
,
support_level_without_template
,
None
,
'advanced'
)
)
categories
.
add
(
category
)
categories
.
add
(
category
)
# add boilerplates
# add boilerplates
...
@@ -204,6 +283,11 @@ def get_component_templates(courselike, library=False):
...
@@ -204,6 +283,11 @@ def get_component_templates(courselike, library=False):
for
template
in
component_class
.
templates
():
for
template
in
component_class
.
templates
():
filter_templates
=
getattr
(
component_class
,
'filter_templates'
,
None
)
filter_templates
=
getattr
(
component_class
,
'filter_templates'
,
None
)
if
not
filter_templates
or
filter_templates
(
template
,
courselike
):
if
not
filter_templates
or
filter_templates
(
template
,
courselike
):
template_id
=
template
.
get
(
'template_id'
)
support_level_with_template
=
component_support_level
(
authorable_variations
,
category
,
template_id
)
if
support_level_with_template
:
# Tab can be 'common' 'advanced'
# Tab can be 'common' 'advanced'
# Default setting is common/advanced depending on the presence of markdown
# Default setting is common/advanced depending on the presence of markdown
tab
=
'common'
tab
=
'common'
...
@@ -215,31 +299,50 @@ def get_component_templates(courselike, library=False):
...
@@ -215,31 +299,50 @@ def get_component_templates(courselike, library=False):
create_template_dict
(
create_template_dict
(
_
(
template
[
'metadata'
]
.
get
(
'display_name'
)),
# pylint: disable=translation-of-non-string
_
(
template
[
'metadata'
]
.
get
(
'display_name'
)),
# pylint: disable=translation-of-non-string
category
,
category
,
template
.
get
(
'template_id'
),
support_level_with_template
,
template_id
,
tab
,
tab
,
hinted
,
hinted
,
)
)
)
)
# Add any advanced problem types
# Add any advanced problem types
. Note that these are different xblocks being stored as Advanced Problems.
if
category
==
'problem'
:
if
category
==
'problem'
:
for
advanced_problem_type
in
ADVANCED_PROBLEM_TYPES
:
disabled_block_names
=
[
block
.
name
for
block
in
disabled_xblocks
()]
advanced_problem_types
=
[
advanced_problem_type
for
advanced_problem_type
in
ADVANCED_PROBLEM_TYPES
if
advanced_problem_type
[
'component'
]
not
in
disabled_block_names
]
for
advanced_problem_type
in
advanced_problem_types
:
component
=
advanced_problem_type
[
'component'
]
component
=
advanced_problem_type
[
'component'
]
boilerplate_name
=
advanced_problem_type
[
'boilerplate_name'
]
boilerplate_name
=
advanced_problem_type
[
'boilerplate_name'
]
authorable_advanced_component_variations
=
authorable_xblocks
(
allow_unsupported
=
allow_unsupported
,
name
=
component
)
advanced_component_support_level
=
component_support_level
(
authorable_advanced_component_variations
,
component
,
boilerplate_name
)
if
advanced_component_support_level
:
try
:
try
:
component_display_name
=
xblock_type_display_name
(
component
)
component_display_name
=
xblock_type_display_name
(
component
)
except
PluginMissingError
:
except
PluginMissingError
:
log
.
warning
(
'Unable to load xblock type
%
s to read display_name'
,
component
,
exc_info
=
True
)
log
.
warning
(
'Unable to load xblock type
%
s to read display_name'
,
component
,
exc_info
=
True
)
else
:
else
:
templates_for_category
.
append
(
templates_for_category
.
append
(
create_template_dict
(
component_display_name
,
component
,
boilerplate_name
,
'advanced'
)
create_template_dict
(
component_display_name
,
component
,
advanced_component_support_level
,
boilerplate_name
,
'advanced'
)
)
)
categories
.
add
(
component
)
categories
.
add
(
component
)
component_templates
.
append
({
component_templates
.
append
({
"type"
:
category
,
"type"
:
category
,
"templates"
:
templates_for_category
,
"templates"
:
templates_for_category
,
"display_name"
:
component_display_names
[
category
]
"display_name"
:
component_display_names
[
category
],
"support_legend"
:
create_support_legend_dict
()
})
})
# Libraries do not support advanced components at this time.
# Libraries do not support advanced components at this time.
...
@@ -251,19 +354,25 @@ def get_component_templates(courselike, library=False):
...
@@ -251,19 +354,25 @@ def get_component_templates(courselike, library=False):
# are the names of the modules in ADVANCED_COMPONENT_TYPES that should be
# are the names of the modules in ADVANCED_COMPONENT_TYPES that should be
# enabled for the course.
# enabled for the course.
course_advanced_keys
=
courselike
.
advanced_modules
course_advanced_keys
=
courselike
.
advanced_modules
advanced_component_templates
=
{
"type"
:
"advanced"
,
"templates"
:
[],
"display_name"
:
_
(
"Advanced"
)}
advanced_component_templates
=
{
advanced_component_types
=
_advanced_component_types
()
"type"
:
"advanced"
,
"templates"
:
[],
"display_name"
:
_
(
"Advanced"
),
"support_legend"
:
create_support_legend_dict
()
}
advanced_component_types
=
_advanced_component_types
(
allow_unsupported
)
# Set component types according to course policy file
# Set component types according to course policy file
if
isinstance
(
course_advanced_keys
,
list
):
if
isinstance
(
course_advanced_keys
,
list
):
for
category
in
course_advanced_keys
:
for
category
in
course_advanced_keys
:
if
category
in
advanced_component_types
and
category
not
in
categories
:
if
category
in
advanced_component_types
.
keys
()
and
category
not
in
categories
:
# boilerplates not supported for advanced components
# boilerplates not supported for advanced components
try
:
try
:
component_display_name
=
xblock_type_display_name
(
category
,
default_display_name
=
category
)
component_display_name
=
xblock_type_display_name
(
category
,
default_display_name
=
category
)
advanced_component_templates
[
'templates'
]
.
append
(
advanced_component_templates
[
'templates'
]
.
append
(
create_template_dict
(
create_template_dict
(
component_display_name
,
component_display_name
,
category
category
,
advanced_component_types
[
category
]
)
)
)
)
categories
.
add
(
category
)
categories
.
add
(
category
)
...
@@ -288,6 +397,14 @@ def get_component_templates(courselike, library=False):
...
@@ -288,6 +397,14 @@ def get_component_templates(courselike, library=False):
return
component_templates
return
component_templates
def
_filter_disabled_blocks
(
all_blocks
):
"""
Filter out disabled xblocks from the provided list of xblock names.
"""
disabled_block_names
=
[
block
.
name
for
block
in
disabled_xblocks
()]
return
[
block_name
for
block_name
in
all_blocks
if
block_name
not
in
disabled_block_names
]
@login_required
@login_required
def
_get_item_in_course
(
request
,
usage_key
):
def
_get_item_in_course
(
request
,
usage_key
):
"""
"""
...
...
cms/djangoapps/contentstore/views/tests/test_item.py
View file @
d4cc7b8f
...
@@ -24,7 +24,7 @@ from contentstore.views.item import (
...
@@ -24,7 +24,7 @@ from contentstore.views.item import (
)
)
from
contentstore.tests.utils
import
CourseTestCase
from
contentstore.tests.utils
import
CourseTestCase
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
xblock_django.models
import
XBlock
DisableConfi
g
from
xblock_django.models
import
XBlock
Configuration
,
XBlockStudioConfiguration
,
XBlockStudioConfigurationFla
g
from
xmodule.capa_module
import
CapaDescriptor
from
xmodule.capa_module
import
CapaDescriptor
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
...
@@ -1457,12 +1457,19 @@ class TestComponentTemplates(CourseTestCase):
...
@@ -1457,12 +1457,19 @@ class TestComponentTemplates(CourseTestCase):
def
setUp
(
self
):
def
setUp
(
self
):
super
(
TestComponentTemplates
,
self
)
.
setUp
()
super
(
TestComponentTemplates
,
self
)
.
setUp
()
self
.
templates
=
get_component_templates
(
self
.
course
)
# Advanced Module support levels.
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'poll'
,
enabled
=
True
,
support_level
=
"fs"
)
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'survey'
,
enabled
=
True
,
support_level
=
"ps"
)
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'annotatable'
,
enabled
=
True
,
support_level
=
"us"
)
# Basic component support levels.
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'html'
,
enabled
=
True
,
support_level
=
"fs"
)
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'discussion'
,
enabled
=
True
,
support_level
=
"ps"
)
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'problem'
,
enabled
=
True
,
support_level
=
"us"
)
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'video'
,
enabled
=
True
,
support_level
=
"us"
)
# XBlock masquerading as a problem
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'openassessment'
,
enabled
=
True
,
support_level
=
"us"
)
# Initialize the deprecated modules settings with empty list
self
.
templates
=
get_component_templates
(
self
.
course
)
XBlockDisableConfig
.
objects
.
create
(
disabled_create_blocks
=
''
,
enabled
=
True
)
def
get_templates_of_type
(
self
,
template_type
):
def
get_templates_of_type
(
self
,
template_type
):
"""
"""
...
@@ -1481,12 +1488,40 @@ class TestComponentTemplates(CourseTestCase):
...
@@ -1481,12 +1488,40 @@ class TestComponentTemplates(CourseTestCase):
"""
"""
Test the handling of the basic component templates.
Test the handling of the basic component templates.
"""
"""
self
.
assertIsNotNone
(
self
.
get_templates_of_type
(
'discussion'
)
)
self
.
_verify_basic_component
(
"discussion"
,
"Discussion"
)
self
.
assertIsNotNone
(
self
.
get_templates_of_type
(
'html'
)
)
self
.
_verify_basic_component
(
"video"
,
"Video"
)
self
.
assert
IsNotNone
(
self
.
get_templates_of_type
(
'problem'
)
)
self
.
assert
Greater
(
self
.
get_templates_of_type
(
'html'
),
0
)
self
.
assert
IsNotNone
(
self
.
get_templates_of_type
(
'video'
)
)
self
.
assert
Greater
(
self
.
get_templates_of_type
(
'problem'
),
0
)
self
.
assertIsNone
(
self
.
get_templates_of_type
(
'advanced'
))
self
.
assertIsNone
(
self
.
get_templates_of_type
(
'advanced'
))
# Now fully disable video through XBlockConfiguration
XBlockConfiguration
.
objects
.
create
(
name
=
'video'
,
enabled
=
False
)
self
.
templates
=
get_component_templates
(
self
.
course
)
self
.
assertIsNone
(
self
.
get_templates_of_type
(
'video'
))
def
test_basic_components_support_levels
(
self
):
"""
Test that support levels can be set on basic component templates.
"""
XBlockStudioConfigurationFlag
.
objects
.
create
(
enabled
=
True
)
self
.
templates
=
get_component_templates
(
self
.
course
)
self
.
_verify_basic_component
(
"discussion"
,
"Discussion"
,
"ps"
)
self
.
assertEqual
([],
self
.
get_templates_of_type
(
"video"
))
self
.
assertEqual
([],
self
.
get_templates_of_type
(
"problem"
))
self
.
course
.
allow_unsupported_xblocks
=
True
self
.
templates
=
get_component_templates
(
self
.
course
)
self
.
_verify_basic_component
(
"video"
,
"Video"
,
"us"
)
problem_templates
=
self
.
get_templates_of_type
(
'problem'
)
problem_no_boilerplate
=
self
.
get_template
(
problem_templates
,
u'Blank Advanced Problem'
)
self
.
assertIsNotNone
(
problem_no_boilerplate
)
self
.
assertEqual
(
'us'
,
problem_no_boilerplate
[
'support_level'
])
# Now fully disable video through XBlockConfiguration
XBlockConfiguration
.
objects
.
create
(
name
=
'video'
,
enabled
=
False
)
self
.
templates
=
get_component_templates
(
self
.
course
)
self
.
assertIsNone
(
self
.
get_templates_of_type
(
'video'
))
def
test_advanced_components
(
self
):
def
test_advanced_components
(
self
):
"""
"""
Test the handling of advanced component templates.
Test the handling of advanced component templates.
...
@@ -1510,6 +1545,11 @@ class TestComponentTemplates(CourseTestCase):
...
@@ -1510,6 +1545,11 @@ class TestComponentTemplates(CourseTestCase):
self
.
assertNotEqual
(
only_template
.
get
(
'category'
),
'video'
)
self
.
assertNotEqual
(
only_template
.
get
(
'category'
),
'video'
)
self
.
assertNotEqual
(
only_template
.
get
(
'category'
),
'openassessment'
)
self
.
assertNotEqual
(
only_template
.
get
(
'category'
),
'openassessment'
)
# Now fully disable word_cloud through XBlockConfiguration
XBlockConfiguration
.
objects
.
create
(
name
=
'word_cloud'
,
enabled
=
False
)
self
.
templates
=
get_component_templates
(
self
.
course
)
self
.
assertIsNone
(
self
.
get_templates_of_type
(
'advanced'
))
def
test_advanced_problems
(
self
):
def
test_advanced_problems
(
self
):
"""
"""
Test the handling of advanced problem templates.
Test the handling of advanced problem templates.
...
@@ -1520,44 +1560,101 @@ class TestComponentTemplates(CourseTestCase):
...
@@ -1520,44 +1560,101 @@ class TestComponentTemplates(CourseTestCase):
self
.
assertEqual
(
circuit_template
.
get
(
'category'
),
'problem'
)
self
.
assertEqual
(
circuit_template
.
get
(
'category'
),
'problem'
)
self
.
assertEqual
(
circuit_template
.
get
(
'boilerplate_name'
),
'circuitschematic.yaml'
)
self
.
assertEqual
(
circuit_template
.
get
(
'boilerplate_name'
),
'circuitschematic.yaml'
)
@patch
(
'django.conf.settings.DEPRECATED_ADVANCED_COMPONENT_TYPES'
,
[])
def
test_deprecated_no_advance_component_button
(
self
):
def
test_deprecated_no_advance_component_button
(
self
):
"""
"""
Test that there will be no `Advanced` button on unit page if
units are
Test that there will be no `Advanced` button on unit page if
xblocks have disabled
deprecated provided
that they are the only modules in `Advanced Module List`
Studio support given
that they are the only modules in `Advanced Module List`
"""
"""
XBlockDisableConfig
.
objects
.
create
(
disabled_create_blocks
=
'poll survey'
,
enabled
=
True
)
# Update poll and survey to have "enabled=False".
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'poll'
,
enabled
=
False
,
support_level
=
"fs"
)
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'survey'
,
enabled
=
False
,
support_level
=
"fs"
)
XBlockStudioConfigurationFlag
.
objects
.
create
(
enabled
=
True
)
self
.
course
.
advanced_modules
.
extend
([
'poll'
,
'survey'
])
self
.
course
.
advanced_modules
.
extend
([
'poll'
,
'survey'
])
templates
=
get_component_templates
(
self
.
course
)
templates
=
get_component_templates
(
self
.
course
)
button_names
=
[
template
[
'display_name'
]
for
template
in
templates
]
button_names
=
[
template
[
'display_name'
]
for
template
in
templates
]
self
.
assertNotIn
(
'Advanced'
,
button_names
)
self
.
assertNotIn
(
'Advanced'
,
button_names
)
@patch
(
'django.conf.settings.DEPRECATED_ADVANCED_COMPONENT_TYPES'
,
[])
def
test_cannot_create_deprecated_problems
(
self
):
def
test_cannot_create_deprecated_problems
(
self
):
"""
"""
Test that
we can't create problems if they are deprecated
Test that
xblocks that have Studio support disabled do not show on the "new component" menu.
"""
"""
XBlockDisableConfig
.
objects
.
create
(
disabled_create_blocks
=
'poll survey'
,
enabled
=
True
)
# Update poll to have "enabled=False".
XBlockStudioConfiguration
.
objects
.
create
(
name
=
'poll'
,
enabled
=
False
,
support_level
=
"fs"
)
XBlockStudioConfigurationFlag
.
objects
.
create
(
enabled
=
True
)
self
.
course
.
advanced_modules
.
extend
([
'annotatable'
,
'poll'
,
'survey'
])
self
.
course
.
advanced_modules
.
extend
([
'annotatable'
,
'poll'
,
'survey'
])
templates
=
get_component_templates
(
self
.
course
)
# Annotatable doesn't show up because it is unsupported (in test setUp).
button_names
=
[
template
[
'display_name'
]
for
template
in
templates
]
self
.
_verify_advanced_xblocks
([
'Survey'
],
[
'ps'
])
self
.
assertIn
(
'Advanced'
,
button_names
)
self
.
assertEqual
(
len
(
templates
[
0
][
'templates'
]),
1
)
# Now enable unsupported components.
template_display_names
=
[
template
[
'display_name'
]
for
template
in
templates
[
0
][
'templates'
]]
self
.
course
.
allow_unsupported_xblocks
=
True
self
.
assertEqual
(
template_display_names
,
[
'Annotation'
])
self
.
_verify_advanced_xblocks
([
'Annotation'
,
'Survey'
],
[
'us'
,
'ps'
])
# Now disable Annotatable completely through XBlockConfiguration
XBlockConfiguration
.
objects
.
create
(
name
=
'annotatable'
,
enabled
=
False
)
self
.
_verify_advanced_xblocks
([
'Survey'
],
[
'ps'
])
@patch
(
'django.conf.settings.DEPRECATED_ADVANCED_COMPONENT_TYPES'
,
[
'poll'
])
def
test_create_support_level_flag_off
(
self
):
def
test_create_non_deprecated_problems
(
self
):
"""
"""
Test that we can create problems if they are not deprecated
Test that we can create any advanced xblock (that isn't completely disabled through
XBlockConfiguration) if XBlockStudioConfigurationFlag is False.
"""
XBlockStudioConfigurationFlag
.
objects
.
create
(
enabled
=
False
)
self
.
course
.
advanced_modules
.
extend
([
'annotatable'
,
'survey'
])
self
.
_verify_advanced_xblocks
([
'Annotation'
,
'Survey'
],
[
True
,
True
])
def
test_xblock_masquerading_as_problem
(
self
):
"""
Test the integration of xblocks masquerading as problems.
"""
def
get_openassessment
():
""" Helper method to return the openassessment template from problem list """
self
.
templates
=
get_component_templates
(
self
.
course
)
problem_templates
=
self
.
get_templates_of_type
(
'problem'
)
return
self
.
get_template
(
problem_templates
,
u'Peer Assessment'
)
def
verify_openassessment_present
(
support_level
):
""" Helper method to verify that openassessment template is present """
openassessment
=
get_openassessment
()
self
.
assertIsNotNone
(
openassessment
)
self
.
assertEqual
(
openassessment
.
get
(
'category'
),
'openassessment'
)
self
.
assertEqual
(
openassessment
.
get
(
'support_level'
),
support_level
)
verify_openassessment_present
(
True
)
# Now enable XBlockStudioConfigurationFlag. The openassessment block is marked
# unsupported, so will no longer show up.
XBlockStudioConfigurationFlag
.
objects
.
create
(
enabled
=
True
)
self
.
assertIsNone
(
get_openassessment
())
# Now allow unsupported components.
self
.
course
.
allow_unsupported_xblocks
=
True
verify_openassessment_present
(
'us'
)
# Now disable openassessment completely through XBlockConfiguration
XBlockConfiguration
.
objects
.
create
(
name
=
'openassessment'
,
enabled
=
False
)
self
.
assertIsNone
(
get_openassessment
())
def
_verify_advanced_xblocks
(
self
,
expected_xblocks
,
expected_support_levels
):
"""
Verify the names of the advanced xblocks showing in the "new component" menu.
"""
"""
self
.
course
.
advanced_modules
.
extend
([
'annotatable'
,
'poll'
,
'survey'
])
templates
=
get_component_templates
(
self
.
course
)
templates
=
get_component_templates
(
self
.
course
)
button_names
=
[
template
[
'display_name'
]
for
template
in
templates
]
button_names
=
[
template
[
'display_name'
]
for
template
in
templates
]
self
.
assertIn
(
'Advanced'
,
button_names
)
self
.
assertIn
(
'Advanced'
,
button_names
)
self
.
assertEqual
(
len
(
templates
[
0
][
'templates'
]),
2
)
self
.
assertEqual
(
len
(
templates
[
0
][
'templates'
]),
len
(
expected_xblocks
)
)
template_display_names
=
[
template
[
'display_name'
]
for
template
in
templates
[
0
][
'templates'
]]
template_display_names
=
[
template
[
'display_name'
]
for
template
in
templates
[
0
][
'templates'
]]
self
.
assertEqual
(
template_display_names
,
[
'Annotation'
,
'Survey'
])
self
.
assertEqual
(
template_display_names
,
expected_xblocks
)
template_support_levels
=
[
template
[
'support_level'
]
for
template
in
templates
[
0
][
'templates'
]]
self
.
assertEqual
(
template_support_levels
,
expected_support_levels
)
def
_verify_basic_component
(
self
,
component_type
,
display_name
,
support_level
=
True
):
"""
Verify the display name and support level of basic components (that have no boilerplates).
"""
templates
=
self
.
get_templates_of_type
(
component_type
)
self
.
assertEqual
(
1
,
len
(
templates
))
self
.
assertEqual
(
display_name
,
templates
[
0
][
'display_name'
])
self
.
assertEqual
(
support_level
,
templates
[
0
][
'support_level'
])
@ddt.ddt
@ddt.ddt
...
...
cms/djangoapps/models/settings/course_metadata.py
View file @
d4cc7b8f
...
@@ -2,7 +2,9 @@
...
@@ -2,7 +2,9 @@
Django module for Course Metadata class -- manages advanced settings and related parameters
Django module for Course Metadata class -- manages advanced settings and related parameters
"""
"""
from
xblock.fields
import
Scope
from
xblock.fields
import
Scope
from
xblock_django.models
import
XBlockStudioConfigurationFlag
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.conf
import
settings
from
django.conf
import
settings
...
@@ -93,6 +95,11 @@ class CourseMetadata(object):
...
@@ -93,6 +95,11 @@ class CourseMetadata(object):
filtered_list
.
append
(
'enable_ccx'
)
filtered_list
.
append
(
'enable_ccx'
)
filtered_list
.
append
(
'ccx_connector'
)
filtered_list
.
append
(
'ccx_connector'
)
# If the XBlockStudioConfiguration table is not being used, there is no need to
# display the "Allow Unsupported XBlocks" setting.
if
not
XBlockStudioConfigurationFlag
.
is_enabled
():
filtered_list
.
append
(
'allow_unsupported_xblocks'
)
return
filtered_list
return
filtered_list
@classmethod
@classmethod
...
...
cms/envs/aws.py
View file @
d4cc7b8f
...
@@ -398,9 +398,6 @@ ADVANCED_SECURITY_CONFIG = ENV_TOKENS.get('ADVANCED_SECURITY_CONFIG', {})
...
@@ -398,9 +398,6 @@ ADVANCED_SECURITY_CONFIG = ENV_TOKENS.get('ADVANCED_SECURITY_CONFIG', {})
################ ADVANCED COMPONENT/PROBLEM TYPES ###############
################ ADVANCED COMPONENT/PROBLEM TYPES ###############
ADVANCED_PROBLEM_TYPES
=
ENV_TOKENS
.
get
(
'ADVANCED_PROBLEM_TYPES'
,
ADVANCED_PROBLEM_TYPES
)
ADVANCED_PROBLEM_TYPES
=
ENV_TOKENS
.
get
(
'ADVANCED_PROBLEM_TYPES'
,
ADVANCED_PROBLEM_TYPES
)
DEPRECATED_ADVANCED_COMPONENT_TYPES
=
ENV_TOKENS
.
get
(
'DEPRECATED_ADVANCED_COMPONENT_TYPES'
,
DEPRECATED_ADVANCED_COMPONENT_TYPES
)
################ VIDEO UPLOAD PIPELINE ###############
################ VIDEO UPLOAD PIPELINE ###############
...
...
cms/envs/common.py
View file @
d4cc7b8f
...
@@ -1132,19 +1132,6 @@ XBLOCK_SETTINGS = {
...
@@ -1132,19 +1132,6 @@ XBLOCK_SETTINGS = {
}
}
}
}
################################ XBlock Deprecation ################################
# The following settings are used for deprecating XBlocks.
# Adding components in this list will disable the creation of new problems for
# those advanced components in Studio. Existing problems will work fine
# and one can edit them in Studio.
# DEPRECATED. Please use /admin/xblock_django/xblockdisableconfig instead.
DEPRECATED_ADVANCED_COMPONENT_TYPES
=
[]
# XBlocks can be disabled from rendering in LMS Courseware by adding them to
# /admin/xblock_django/xblockdisableconfig/.
################################ Settings for Credit Course Requirements ################################
################################ Settings for Credit Course Requirements ################################
# Initial delay used for retrying tasks.
# Initial delay used for retrying tasks.
# Additional retries use longer delays.
# Additional retries use longer delays.
...
...
cms/static/js/models/component_template.js
View file @
d4cc7b8f
...
@@ -10,7 +10,8 @@ define(["backbone"], function (Backbone) {
...
@@ -10,7 +10,8 @@ define(["backbone"], function (Backbone) {
// category (may or may not match "type")
// category (may or may not match "type")
// boilerplate_name (may be null)
// boilerplate_name (may be null)
// is_common (only used for problems)
// is_common (only used for problems)
templates
:
[]
templates
:
[],
support_legend
:
{}
},
},
parse
:
function
(
response
)
{
parse
:
function
(
response
)
{
// Returns true only for templates that both have no boilerplate and are of
// Returns true only for templates that both have no boilerplate and are of
...
@@ -24,6 +25,7 @@ define(["backbone"], function (Backbone) {
...
@@ -24,6 +25,7 @@ define(["backbone"], function (Backbone) {
this
.
type
=
response
.
type
;
this
.
type
=
response
.
type
;
this
.
templates
=
response
.
templates
;
this
.
templates
=
response
.
templates
;
this
.
display_name
=
response
.
display_name
;
this
.
display_name
=
response
.
display_name
;
this
.
support_legend
=
response
.
support_legend
;
// Sort the templates.
// Sort the templates.
this
.
templates
.
sort
(
function
(
a
,
b
)
{
this
.
templates
.
sort
(
function
(
a
,
b
)
{
...
...
cms/static/js/spec/models/component_template_spec.js
View file @
d4cc7b8f
...
@@ -49,7 +49,8 @@ define(["js/models/component_template"],
...
@@ -49,7 +49,8 @@ define(["js/models/component_template"],
"boilerplate_name"
:
"alternate_word_cloud.yaml"
,
"boilerplate_name"
:
"alternate_word_cloud.yaml"
,
"display_name"
:
"Word Cloud"
"display_name"
:
"Word Cloud"
}],
}],
"type"
:
"problem"
"type"
:
"problem"
,
"support_legend"
:
{
"show_legend"
:
false
}
};
};
it
(
'orders templates correctly'
,
function
()
{
it
(
'orders templates correctly'
,
function
()
{
...
...
cms/static/js/spec/views/pages/container_spec.js
View file @
d4cc7b8f
define
([
"jquery"
,
"underscore"
,
"underscore.string"
,
"edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers"
,
define
([
"jquery"
,
"underscore"
,
"underscore.string"
,
"edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers"
,
"common/js/spec_helpers/template_helpers"
,
"js/spec_helpers/edit_helpers"
,
"common/js/spec_helpers/template_helpers"
,
"js/spec_helpers/edit_helpers"
,
"js/views/pages/container"
,
"js/views/pages/paged_container"
,
"js/models/xblock_info"
,
"jquery.simulate"
],
"js/views/pages/container"
,
"js/views/pages/paged_container"
,
"js/models/xblock_info"
,
function
(
$
,
_
,
str
,
AjaxHelpers
,
TemplateHelpers
,
EditHelpers
,
ContainerPage
,
PagedContainerPage
,
XBlockInfo
)
{
"js/collections/component_template"
,
"jquery.simulate"
],
function
(
$
,
_
,
str
,
AjaxHelpers
,
TemplateHelpers
,
EditHelpers
,
ContainerPage
,
PagedContainerPage
,
XBlockInfo
,
ComponentTemplates
)
{
'use strict'
;
'use strict'
;
function
parameterized_suite
(
label
,
globalPageOptions
)
{
function
parameterized_suite
(
label
,
globalPageOptions
)
{
...
@@ -55,18 +57,19 @@ define(["jquery", "underscore", "underscore.string", "edx-ui-toolkit/js/utils/sp
...
@@ -55,18 +57,19 @@ define(["jquery", "underscore", "underscore.string", "edx-ui-toolkit/js/utils/sp
);
);
};
};
getContainerPage
=
function
(
options
)
{
getContainerPage
=
function
(
options
,
componentTemplates
)
{
var
default_options
=
{
var
default_options
=
{
model
:
model
,
model
:
model
,
templates
:
EditHelpers
.
mockComponentTemplates
,
templates
:
componentTemplates
===
undefined
?
EditHelpers
.
mockComponentTemplates
:
componentTemplates
,
el
:
$
(
'#content'
)
el
:
$
(
'#content'
)
};
};
return
new
PageClass
(
_
.
extend
(
options
||
{},
globalPageOptions
,
default_options
));
return
new
PageClass
(
_
.
extend
(
options
||
{},
globalPageOptions
,
default_options
));
};
};
renderContainerPage
=
function
(
test
,
html
,
options
)
{
renderContainerPage
=
function
(
test
,
html
,
options
,
componentTemplates
)
{
requests
=
AjaxHelpers
.
requests
(
test
);
requests
=
AjaxHelpers
.
requests
(
test
);
containerPage
=
getContainerPage
(
options
);
containerPage
=
getContainerPage
(
options
,
componentTemplates
);
containerPage
.
render
();
containerPage
.
render
();
respondWithHtml
(
html
);
respondWithHtml
(
html
);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/locator-container'
);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/locator-container'
);
...
@@ -652,6 +655,138 @@ define(["jquery", "underscore", "underscore.string", "edx-ui-toolkit/js/utils/sp
...
@@ -652,6 +655,138 @@ define(["jquery", "underscore", "underscore.string", "edx-ui-toolkit/js/utils/sp
"parent_locator"
:
"locator-group-A"
"parent_locator"
:
"locator-group-A"
});
});
});
});
it
(
'does not show the support legend if show_legend is false'
,
function
()
{
// By default, show_legend is false in the mock component Templates.
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
showTemplatePicker
();
expect
(
containerPage
.
$
(
'.support-documentation'
).
length
).
toBe
(
0
);
});
it
(
'does show the support legend if show_legend is true'
,
function
()
{
var
templates
=
new
ComponentTemplates
([
{
"templates"
:
[
{
"category"
:
"html"
,
"boilerplate_name"
:
null
,
"display_name"
:
"Text"
},
{
"category"
:
"html"
,
"boilerplate_name"
:
"announcement.yaml"
,
"display_name"
:
"Announcement"
},
{
"category"
:
"html"
,
"boilerplate_name"
:
"raw.yaml"
,
"display_name"
:
"Raw HTML"
}],
"type"
:
"html"
,
"support_legend"
:
{
"show_legend"
:
true
,
"documentation_label"
:
"Documentation Label:"
,
"allow_unsupported_xblocks"
:
false
}
}],
{
parse
:
true
}),
supportDocumentation
;
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{},
templates
);
showTemplatePicker
();
supportDocumentation
=
containerPage
.
$
(
'.support-documentation'
);
// On this page, groups are being shown, each of which has a new component menu.
expect
(
supportDocumentation
.
length
).
toBeGreaterThan
(
0
);
// check that the documentation label is displayed
expect
(
$
(
supportDocumentation
[
0
]).
find
(
'.support-documentation-link'
).
text
().
trim
())
.
toBe
(
'Documentation Label:'
);
// show_unsupported_xblocks is false, so only 2 support levels should be shown
expect
(
$
(
supportDocumentation
[
0
]).
find
(
'.support-documentation-level'
).
length
).
toBe
(
2
);
});
it
(
'does show unsupported level if enabled'
,
function
()
{
var
templates
=
new
ComponentTemplates
([
{
"templates"
:
[
{
"category"
:
"html"
,
"boilerplate_name"
:
null
,
"display_name"
:
"Text"
},
{
"category"
:
"html"
,
"boilerplate_name"
:
"announcement.yaml"
,
"display_name"
:
"Announcement"
},
{
"category"
:
"html"
,
"boilerplate_name"
:
"raw.yaml"
,
"display_name"
:
"Raw HTML"
}],
"type"
:
"html"
,
"support_legend"
:
{
"show_legend"
:
true
,
"documentation_label"
:
"Documentation Label:"
,
"allow_unsupported_xblocks"
:
true
}
}],
{
parse
:
true
}),
supportDocumentation
;
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{},
templates
);
showTemplatePicker
();
supportDocumentation
=
containerPage
.
$
(
'.support-documentation'
);
// show_unsupported_xblocks is true, so 3 support levels should be shown
expect
(
$
(
supportDocumentation
[
0
]).
find
(
'.support-documentation-level'
).
length
).
toBe
(
3
);
// verify only one has the unsupported item
expect
(
$
(
supportDocumentation
[
0
]).
find
(
'.fa-circle-o'
).
length
).
toBe
(
1
);
});
it
(
'does render support level indicators if present in JSON'
,
function
()
{
var
templates
=
new
ComponentTemplates
([
{
"templates"
:
[
{
"category"
:
"html"
,
"boilerplate_name"
:
null
,
"display_name"
:
"Text"
,
"support_level"
:
"fs"
},
{
"category"
:
"html"
,
"boilerplate_name"
:
"announcement.yaml"
,
"display_name"
:
"Announcement"
,
"support_level"
:
"ps"
},
{
"category"
:
"html"
,
"boilerplate_name"
:
"raw.yaml"
,
"display_name"
:
"Raw HTML"
,
"support_level"
:
"us"
}],
"type"
:
"html"
,
"support_legend"
:
{
"show_legend"
:
true
,
"documentation_label"
:
"Documentation Label:"
,
"allow_unsupported_xblocks"
:
true
}
}],
{
parse
:
true
}),
supportLevelIndicators
,
getScreenReaderText
;
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{},
templates
);
showTemplatePicker
();
supportLevelIndicators
=
$
(
containerPage
.
$
(
'.new-component-template'
)[
0
])
.
find
(
'.support-level'
);
expect
(
supportLevelIndicators
.
length
).
toBe
(
3
);
getScreenReaderText
=
function
(
index
){
return
$
(
$
(
supportLevelIndicators
[
index
]).
siblings
()[
0
]).
text
().
trim
();
};
// Verify one level of each type was rendered.
expect
(
getScreenReaderText
(
0
)).
toBe
(
'Fully Supported'
);
expect
(
getScreenReaderText
(
1
)).
toBe
(
'Provisionally Supported'
);
expect
(
getScreenReaderText
(
2
)).
toBe
(
'Not Supported'
);
});
});
});
});
});
});
});
...
...
cms/static/js/spec_helpers/edit_helpers.js
View file @
d4cc7b8f
...
@@ -41,12 +41,13 @@ define(["jquery", "underscore", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
...
@@ -41,12 +41,13 @@ define(["jquery", "underscore", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
mockComponentTemplates
=
new
ComponentTemplates
([
mockComponentTemplates
=
new
ComponentTemplates
([
{
{
templates
:
[
"templates"
:
[
{
{
category
:
'discussion'
,
"category"
:
"discussion"
,
display_name
:
'Discussion'
"display_name"
:
"Discussion"
}],
}],
type
:
'discussion'
"type"
:
"discussion"
,
"support_legend"
:
{
"show_legend"
:
false
}
},
{
},
{
"templates"
:
[
"templates"
:
[
{
{
...
@@ -62,7 +63,8 @@ define(["jquery", "underscore", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
...
@@ -62,7 +63,8 @@ define(["jquery", "underscore", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
"boilerplate_name"
:
"raw.yaml"
,
"boilerplate_name"
:
"raw.yaml"
,
"display_name"
:
"Raw HTML"
"display_name"
:
"Raw HTML"
}],
}],
"type"
:
"html"
"type"
:
"html"
,
"support_legend"
:
{
"show_legend"
:
false
}
}],
}],
{
{
parse
:
true
parse
:
true
...
@@ -76,6 +78,8 @@ define(["jquery", "underscore", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
...
@@ -76,6 +78,8 @@ define(["jquery", "underscore", "edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
TemplateHelpers
.
installTemplate
(
'add-xblock-component-button'
);
TemplateHelpers
.
installTemplate
(
'add-xblock-component-button'
);
TemplateHelpers
.
installTemplate
(
'add-xblock-component-menu'
);
TemplateHelpers
.
installTemplate
(
'add-xblock-component-menu'
);
TemplateHelpers
.
installTemplate
(
'add-xblock-component-menu-problem'
);
TemplateHelpers
.
installTemplate
(
'add-xblock-component-menu-problem'
);
TemplateHelpers
.
installTemplate
(
'add-xblock-component-support-legend'
);
TemplateHelpers
.
installTemplate
(
'add-xblock-component-support-level'
);
// Add templates needed by the edit XBlock modal
// Add templates needed by the edit XBlock modal
TemplateHelpers
.
installTemplate
(
'edit-xblock-modal'
);
TemplateHelpers
.
installTemplate
(
'edit-xblock-modal'
);
...
...
cms/static/js/views/components/add_xblock_menu.js
View file @
d4cc7b8f
define
([
"jquery"
,
"js/views/baseview"
],
define
([
"jquery"
,
"js/views/baseview"
,
'edx-ui-toolkit/js/utils/html-utils'
],
function
(
$
,
BaseView
)
{
function
(
$
,
BaseView
,
HtmlUtils
)
{
return
BaseView
.
extend
({
return
BaseView
.
extend
({
className
:
function
()
{
className
:
function
()
{
...
@@ -9,8 +9,19 @@ define(["jquery", "js/views/baseview"],
...
@@ -9,8 +9,19 @@ define(["jquery", "js/views/baseview"],
BaseView
.
prototype
.
initialize
.
call
(
this
);
BaseView
.
prototype
.
initialize
.
call
(
this
);
var
template_name
=
this
.
model
.
type
===
"problem"
?
"add-xblock-component-menu-problem"
:
var
template_name
=
this
.
model
.
type
===
"problem"
?
"add-xblock-component-menu-problem"
:
"add-xblock-component-menu"
;
"add-xblock-component-menu"
;
var
support_indicator_template
=
this
.
loadTemplate
(
"add-xblock-component-support-level"
);
var
support_legend_template
=
this
.
loadTemplate
(
"add-xblock-component-support-legend"
);
this
.
template
=
this
.
loadTemplate
(
template_name
);
this
.
template
=
this
.
loadTemplate
(
template_name
);
this
.
$el
.
html
(
this
.
template
({
type
:
this
.
model
.
type
,
templates
:
this
.
model
.
templates
}));
HtmlUtils
.
setHtml
(
this
.
$el
,
HtmlUtils
.
HTML
(
this
.
template
({
type
:
this
.
model
.
type
,
templates
:
this
.
model
.
templates
,
support_legend
:
this
.
model
.
support_legend
,
support_indicator_template
:
support_indicator_template
,
support_legend_template
:
support_legend_template
,
HtmlUtils
:
HtmlUtils
}))
);
// Make the tabs on problems into "real tabs"
// Make the tabs on problems into "real tabs"
this
.
$
(
'.tab-group'
).
tabs
();
this
.
$
(
'.tab-group'
).
tabs
();
}
}
...
...
cms/static/sass/_build-v1.scss
View file @
d4cc7b8f
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
// +Base - Utilities
// +Base - Utilities
// ====================
// ====================
@import
'variables'
;
@import
'
partials/
variables'
;
@import
'mixins'
;
@import
'mixins'
;
@import
'mixins-inherited'
;
@import
'mixins-inherited'
;
...
...
cms/static/sass/elements/_modules.scss
View file @
d4cc7b8f
...
@@ -168,18 +168,47 @@
...
@@ -168,18 +168,47 @@
// specific menu types
// specific menu types
&
.new-component-problem
{
&
.new-component-problem
{
padding-bottom
:
(
$baseline
/
2
);
.problem-type-tabs
{
.problem-type-tabs
{
display
:
inline-block
;
display
:
inline-block
;
}
}
}
}
.support-documentation
{
float
:
right
;
@include
margin
(
$baseline
,
0
,
(
$baseline
/
2
)
,
(
$baseline
/
2
));
@include
font-size
(
14
);
.support-documentation-level
{
padding-right
:
(
$baseline
/
2
);
}
.support-documentation-link
{
// Override JQuery ui-widget-content link color (black) with our usual link color and hover action.
color
:
$uxpl-blue-base
;
text-decoration
:
none
;
padding-right
:
(
$baseline
/
2
);
&
:hover
{
color
:
$uxpl-blue-hover-active
;
text-decoration
:
underline
;
}
}
}
.support-level
{
padding-right
:
(
$baseline
/
2
);
}
.icon
{
color
:
$uxpl-primary-accent
;
}
}
}
// individual menus
// individual menus
// --------------------
// --------------------
.new-component-template
{
.new-component-template
{
@include
clearfix
();
@include
clearfix
();
margin-bottom
:
0
;
li
{
li
{
border
:
none
;
border
:
none
;
...
@@ -201,11 +230,16 @@
...
@@ -201,11 +230,16 @@
background
:
$white
;
background
:
$white
;
color
:
$gray-d3
;
color
:
$gray-d3
;
text-align
:
left
;
text-align
:
left
;
font-family
:
$f-sans-serif
;
&
:hover
{
&
:hover
{
@include
transition
(
background-color
$tmg-f2
linear
0s
);
@include
transition
(
background-color
$tmg-f2
linear
0s
);
background
:
tint
(
$green
,
30%
);
background
:
tint
(
$green
,
30%
);
color
:
$white
;
color
:
$white
;
.icon
{
color
:
$white
;
}
}
}
}
}
}
}
...
...
cms/static/sass/partials/_variables.scss
View file @
d4cc7b8f
...
@@ -39,6 +39,16 @@ $f-monospace: 'Bitstream Vera Sans Mono', Consolas, Courier, monospace;
...
@@ -39,6 +39,16 @@ $f-monospace: 'Bitstream Vera Sans Mono', Consolas, Courier, monospace;
// ====================
// ====================
$transparent
:
rgba
(
0
,
0
,
0
,
0
);
// used when color value is needed for UI width/transitions but element is transparent
$transparent
:
rgba
(
0
,
0
,
0
,
0
);
// used when color value is needed for UI width/transitions but element is transparent
// +Colors - UXPL new pattern library colors
// ====================
$uxpl-blue-base
:
rgba
(
0
,
116
,
180
,
1
);
// wcag2a compliant
$uxpl-blue-hover-active
:
lighten
(
$uxpl-blue-base
,
7%
);
// wcag2a compliant
$uxpl-green-base
:
rgba
(
0
,
129
,
0
,
1
);
// wcag2a compliant
$uxpl-green-hover-active
:
lighten
(
$uxpl-green-base
,
7%
);
// wcag2a compliant
$uxpl-primary-accent
:
rgb
(
14
,
166
,
236
);
// +Colors - Primary
// +Colors - Primary
// ====================
// ====================
$black
:
rgb
(
0
,
0
,
0
);
$black
:
rgb
(
0
,
0
,
0
);
...
@@ -87,12 +97,6 @@ $blue-t1: rgba($blue, 0.25);
...
@@ -87,12 +97,6 @@ $blue-t1: rgba($blue, 0.25);
$blue-t2
:
rgba
(
$blue
,
0
.50
);
$blue-t2
:
rgba
(
$blue
,
0
.50
);
$blue-t3
:
rgba
(
$blue
,
0
.75
);
$blue-t3
:
rgba
(
$blue
,
0
.75
);
$uxpl-blue-base
:
rgba
(
0
,
116
,
180
,
1
);
// wcag2a compliant
$uxpl-blue-hover-active
:
lighten
(
$uxpl-blue-base
,
7%
);
// wcag2a compliant
$uxpl-green-base
:
rgba
(
0
,
129
,
0
,
1
);
// wcag2a compliant
$uxpl-green-hover-active
:
lighten
(
$uxpl-green-base
,
7%
);
// wcag2a compliant
$pink
:
rgb
(
183
,
37
,
103
);
// #b72567;
$pink
:
rgb
(
183
,
37
,
103
);
// #b72567;
$pink-l1
:
tint
(
$pink
,
20%
);
$pink-l1
:
tint
(
$pink
,
20%
);
$pink-l2
:
tint
(
$pink
,
40%
);
$pink-l2
:
tint
(
$pink
,
40%
);
...
...
cms/templates/js/add-xblock-component-menu-problem.underscore
View file @
d4cc7b8f
...
@@ -7,10 +7,10 @@
...
@@ -7,10 +7,10 @@
%>">
%>">
<ul class="problem-type-tabs nav-tabs" tabindex='-1'>
<ul class="problem-type-tabs nav-tabs" tabindex='-1'>
<li class="current">
<li class="current">
<a class="link-tab" href="#tab1"><%
=
gettext("Common Problem Types") %></a>
<a class="link-tab" href="#tab1"><%
-
gettext("Common Problem Types") %></a>
</li>
</li>
<li>
<li>
<a class="link-tab" href="#tab2"><%
=
gettext("Advanced") %></a>
<a class="link-tab" href="#tab2"><%
-
gettext("Advanced") %></a>
</li>
</li>
</ul>
</ul>
<div class="tab current" id="tab1">
<div class="tab current" id="tab1">
...
@@ -19,15 +19,17 @@
...
@@ -19,15 +19,17 @@
<% if (templates[i].tab == "common") { %>
<% if (templates[i].tab == "common") { %>
<% if (!templates[i].boilerplate_name) { %>
<% if (!templates[i].boilerplate_name) { %>
<li class="editor-md empty">
<li class="editor-md empty">
<button type="button" class="button-component" data-category="<%= templates[i].category %>">
<button type="button" class="button-component" data-category="<%- templates[i].category %>">
<span class="name"><%= templates[i].display_name %></span>
<%= HtmlUtils.HTML(support_indicator_template({support_level: templates[i].support_level})) %>
<span class="name"><%- templates[i].display_name %></span>
</button>
</button>
</li>
</li>
<% } else { %>
<% } else { %>
<li class="editor-md">
<li class="editor-md">
<button type="button" class="button-component" data-category="<%= templates[i].category %>"
<button type="button" class="button-component" data-category="<%- templates[i].category %>"
data-boilerplate="<%= templates[i].boilerplate_name %>">
data-boilerplate="<%- templates[i].boilerplate_name %>">
<span class="name"><%= templates[i].display_name %></span>
<%= HtmlUtils.HTML(support_indicator_template({support_level: templates[i].support_level})) %>
<span class="name"><%- templates[i].display_name %></span>
</button>
</button>
</li>
</li>
<% } %>
<% } %>
...
@@ -40,14 +42,16 @@
...
@@ -40,14 +42,16 @@
<% for (var i = 0; i < templates.length; i++) { %>
<% for (var i = 0; i < templates.length; i++) { %>
<% if (templates[i].tab == "advanced") { %>
<% if (templates[i].tab == "advanced") { %>
<li class="editor-manual">
<li class="editor-manual">
<button type="button" class="button-component" data-category="<%= templates[i].category %>"
<button type="button" class="button-component" data-category="<%- templates[i].category %>"
data-boilerplate="<%= templates[i].boilerplate_name %>">
data-boilerplate="<%- templates[i].boilerplate_name %>">
<span class="name"><%= templates[i].display_name %></span>
<%= HtmlUtils.HTML(support_indicator_template({support_level: templates[i].support_level})) %>
<span class="name"><%- templates[i].display_name %></span>
</button>
</button>
</li>
</li>
<% } %>
<% } %>
<% } %>
<% } %>
</ul>
</ul>
</div>
</div>
<button class="cancel-button" data-type="<%= type %>"><%= gettext("Cancel") %></button>
<button class="cancel-button" data-type="<%- type %>"><%- gettext("Cancel") %></button>
<%= HtmlUtils.HTML(support_legend_template({support_legend: support_legend})) %>
</div>
</div>
cms/templates/js/add-xblock-component-menu.underscore
View file @
d4cc7b8f
...
@@ -10,20 +10,23 @@
...
@@ -10,20 +10,23 @@
<% for (var i = 0; i < templates.length; i++) { %>
<% for (var i = 0; i < templates.length; i++) { %>
<% if (!templates[i].boilerplate_name) { %>
<% if (!templates[i].boilerplate_name) { %>
<li class="editor-md empty">
<li class="editor-md empty">
<button type="button" class="button-component" data-category="<%= templates[i].category %>">
<button type="button" class="button-component" data-category="<%- templates[i].category %>">
<span class="name"><%= templates[i].display_name %></span>
<%= HtmlUtils.HTML(support_indicator_template({support_level: templates[i].support_level})) %>
<span class="name"><%- templates[i].display_name %></span>
</button>
</button>
</li>
</li>
<% } else { %>
<% } else { %>
<li class="editor-md">
<li class="editor-md">
<button type="button" class="button-component" data-category="<%= templates[i].category %>"
<button type="button" class="button-component" data-category="<%- templates[i].category %>"
data-boilerplate="<%= templates[i].boilerplate_name %>">
data-boilerplate="<%- templates[i].boilerplate_name %>">
<span class="name"><%= templates[i].display_name %></span>
<%= HtmlUtils.HTML(support_indicator_template({support_level: templates[i].support_level})) %>
<span class="name"><%- templates[i].display_name %></span>
</button>
</button>
</li>
</li>
<% } %>
<% } %>
<% } %>
<% } %>
</ul>
</ul>
<button class="cancel-button" data-type="<%= type %>"><%= gettext("Cancel") %></button>
<button class="cancel-button" data-type="<%- type %>"><%- gettext("Cancel") %></button>
<%= HtmlUtils.HTML(support_legend_template({support_legend: support_legend})) %>
</div>
</div>
<% } %>
<% } %>
cms/templates/js/add-xblock-component-support-legend.underscore
0 → 100644
View file @
d4cc7b8f
<% if (support_legend.show_legend) { %>
<span class="support-documentation">
<a class="support-documentation-link"
href="http://edx.readthedocs.io/projects/edx-partner-course-staff/en/latest/exercises_tools/create_exercises_and_tools.html#levels-of-support-for-tools" target="_blank">
<%- support_legend.documentation_label %>
</a>
<span class="support-documentation-level">
<span class="icon fa fa-circle" aria-hidden="true"></span>
<span><%- gettext('Supported') %></span>
</span>
<span class="support-documentation-level">
<span class="icon fa fa-adjust" aria-hidden="true"></span>
<span><%- gettext('Provisional') %></span>
</span>
<% if (support_legend.allow_unsupported_xblocks) { %>
<span class="support-documentation-level">
<span class="icon fa fa-circle-o" aria-hidden="true"></span>
<span><%- gettext('Not Supported') %></span>
</span>
<% } %>
</span>
<% } %>
cms/templates/js/add-xblock-component-support-level.underscore
0 → 100644
View file @
d4cc7b8f
<% if (support_level === "fs"){ %>
<span class="icon support-level fa fa-circle" aria-hidden="true"></span>
<span class="sr"><%- gettext('Fully Supported') %></span>
<% } else if (support_level === "ps"){ %>
<span class="icon support-level fa fa-adjust" aria-hidden="true"></span>
<span class="sr"><%- gettext('Provisionally Supported') %></span>
<% } else if (support_level === "us"){ %>
<span class="icon support-level fa fa-circle-o" aria-hidden="true"></span>
<span class="sr"><%- gettext('Not Supported') %></span>
<% } %>
common/djangoapps/xblock_django/api.py
View file @
d4cc7b8f
...
@@ -22,11 +22,11 @@ def disabled_xblocks():
...
@@ -22,11 +22,11 @@ def disabled_xblocks():
def
authorable_xblocks
(
allow_unsupported
=
False
,
name
=
None
):
def
authorable_xblocks
(
allow_unsupported
=
False
,
name
=
None
):
"""
"""
If Studio XBlock support state is enabled (via `XBlockStudioConfigurationFlag`), this method returns
This method returns the QuerySet of XBlocks that can be created in Studio (by default, only fully supported
the QuerySet of XBlocks that can be created in Studio (by default, only fully supported and provisionally
and provisionally supported XBlocks), as stored in `XBlockStudioConfiguration`.
supported). If `XBlockStudioConfigurationFlag` is not enabled, this method returns None.
Note that this method does NOT check the value `XBlockStudioConfigurationFlag`, nor does it take into account
Note that this method does not take into account fully disabled xblocks (as returned
fully disabled xblocks (as returned by `disabled_xblocks`) or deprecated xblocks
by `disabled_xblocks`) or deprecated xblocks
(as returned by `deprecated_xblocks`).
(as returned by `deprecated_xblocks`).
Arguments:
Arguments:
allow_unsupported (bool): If `True`, enabled but unsupported XBlocks will also be returned.
allow_unsupported (bool): If `True`, enabled but unsupported XBlocks will also be returned.
...
@@ -36,13 +36,10 @@ def authorable_xblocks(allow_unsupported=False, name=None):
...
@@ -36,13 +36,10 @@ def authorable_xblocks(allow_unsupported=False, name=None):
name (str): If provided, filters the returned XBlocks to those with the provided name. This is
name (str): If provided, filters the returned XBlocks to those with the provided name. This is
useful for XBlocks with lots of template types.
useful for XBlocks with lots of template types.
Returns:
Returns:
QuerySet:
If `XBlockStudioConfigurationFlag` is enabled, returns authorable XBlocks,
QuerySet:
Returns authorable XBlocks, taking into account `support_level`, `enabled` and `name`
taking into account `support_level`, `enabled` and `name` (if specified).
(if specified) as specified by `XBlockStudioConfiguration`. Does not take into account whether or not
If `XBlockStudioConfigurationFlag` is disabled, returns None
.
`XBlockStudioConfigurationFlag` is enabled
.
"""
"""
if
not
XBlockStudioConfigurationFlag
.
is_enabled
():
return
None
blocks
=
XBlockStudioConfiguration
.
objects
.
current_set
()
.
filter
(
enabled
=
True
)
blocks
=
XBlockStudioConfiguration
.
objects
.
current_set
()
.
filter
(
enabled
=
True
)
if
not
allow_unsupported
:
if
not
allow_unsupported
:
blocks
=
blocks
.
exclude
(
support_level
=
XBlockStudioConfiguration
.
UNSUPPORTED
)
blocks
=
blocks
.
exclude
(
support_level
=
XBlockStudioConfiguration
.
UNSUPPORTED
)
...
...
common/djangoapps/xblock_django/models.py
View file @
d4cc7b8f
...
@@ -41,27 +41,10 @@ class XBlockDisableConfig(ConfigurationModel):
...
@@ -41,27 +41,10 @@ class XBlockDisableConfig(ConfigurationModel):
return
block_type
in
config
.
disabled_blocks
.
split
()
return
block_type
in
config
.
disabled_blocks
.
split
()
@classmethod
def
disabled_create_block_types
(
cls
):
""" Return list of deprecated XBlock types. Merges types in settings file and field. """
config
=
cls
.
current
()
xblock_types
=
config
.
disabled_create_blocks
.
split
()
if
config
.
enabled
else
[]
# Merge settings list with one in the admin config;
if
hasattr
(
settings
,
'DEPRECATED_ADVANCED_COMPONENT_TYPES'
):
xblock_types
.
extend
(
xblock_type
for
xblock_type
in
settings
.
DEPRECATED_ADVANCED_COMPONENT_TYPES
if
xblock_type
not
in
xblock_types
)
return
xblock_types
def
__unicode__
(
self
):
def
__unicode__
(
self
):
config
=
XBlockDisableConfig
.
current
()
config
=
XBlockDisableConfig
.
current
()
return
u"Disabled xblocks = {disabled_xblocks}
\n
Deprecated xblocks = {disabled_create_block_types}"
.
format
(
return
u"Disabled xblocks = {disabled_xblocks}"
.
format
(
disabled_xblocks
=
config
.
disabled_blocks
,
disabled_xblocks
=
config
.
disabled_blocks
disabled_create_block_types
=
config
.
disabled_create_block_types
)
)
...
...
common/djangoapps/xblock_django/tests/test_api.py
View file @
d4cc7b8f
...
@@ -61,28 +61,21 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
...
@@ -61,28 +61,21 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
disabled_xblock_names
=
[
block
.
name
for
block
in
disabled_xblocks
()]
disabled_xblock_names
=
[
block
.
name
for
block
in
disabled_xblocks
()]
self
.
assertItemsEqual
([
"survey"
,
"poll"
],
disabled_xblock_names
)
self
.
assertItemsEqual
([
"survey"
,
"poll"
],
disabled_xblock_names
)
def
test_authorable_blocks_flag_disabled
(
self
):
"""
Tests authorable_xblocks returns None if the configuration flag is not enabled.
"""
self
.
assertFalse
(
XBlockStudioConfigurationFlag
.
is_enabled
())
self
.
assertIsNone
(
authorable_xblocks
())
def
test_authorable_blocks_empty_model
(
self
):
def
test_authorable_blocks_empty_model
(
self
):
"""
"""
Tests authorable_xblocks returns an empty list if
the configuration flag is enabled but
Tests authorable_xblocks returns an empty list if
XBlockStudioConfiguration table is empty, regardless
the XBlockStudioConfiguration table is empty
.
of whether or not XBlockStudioConfigurationFlag is enabled
.
"""
"""
XBlockStudioConfigurationFlag
(
enabled
=
True
)
.
save
()
XBlockStudioConfiguration
.
objects
.
all
()
.
delete
()
XBlockStudioConfiguration
.
objects
.
all
()
.
delete
()
self
.
assertFalse
(
XBlockStudioConfigurationFlag
.
is_enabled
())
self
.
assertEqual
(
0
,
len
(
authorable_xblocks
(
allow_unsupported
=
True
)))
XBlockStudioConfigurationFlag
(
enabled
=
True
)
.
save
()
self
.
assertEqual
(
0
,
len
(
authorable_xblocks
(
allow_unsupported
=
True
)))
self
.
assertEqual
(
0
,
len
(
authorable_xblocks
(
allow_unsupported
=
True
)))
def
test_authorable_blocks
(
self
):
def
test_authorable_blocks
(
self
):
"""
"""
Tests authorable_xblocks when
configuration flag is enabled and
name is not specified.
Tests authorable_xblocks when name is not specified.
"""
"""
XBlockStudioConfigurationFlag
(
enabled
=
True
)
.
save
()
authorable_xblock_names
=
[
block
.
name
for
block
in
authorable_xblocks
()]
authorable_xblock_names
=
[
block
.
name
for
block
in
authorable_xblocks
()]
self
.
assertItemsEqual
([
"done"
,
"problem"
,
"problem"
,
"html"
],
authorable_xblock_names
)
self
.
assertItemsEqual
([
"done"
,
"problem"
,
"problem"
,
"html"
],
authorable_xblock_names
)
...
@@ -99,7 +92,7 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
...
@@ -99,7 +92,7 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
def
test_authorable_blocks_by_name
(
self
):
def
test_authorable_blocks_by_name
(
self
):
"""
"""
Tests authorable_xblocks when
configuration flag is enabled and
name is specified.
Tests authorable_xblocks when name is specified.
"""
"""
def
verify_xblock_fields
(
name
,
template
,
support_level
,
block
):
def
verify_xblock_fields
(
name
,
template
,
support_level
,
block
):
"""
"""
...
@@ -109,8 +102,6 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
...
@@ -109,8 +102,6 @@ class XBlockSupportTestCase(CacheIsolationTestCase):
self
.
assertEqual
(
template
,
block
.
template
)
self
.
assertEqual
(
template
,
block
.
template
)
self
.
assertEqual
(
support_level
,
block
.
support_level
)
self
.
assertEqual
(
support_level
,
block
.
support_level
)
XBlockStudioConfigurationFlag
(
enabled
=
True
)
.
save
()
# There are no xblocks with name video.
# There are no xblocks with name video.
authorable_blocks
=
authorable_xblocks
(
name
=
"video"
)
authorable_blocks
=
authorable_xblocks
(
name
=
"video"
)
self
.
assertEqual
(
0
,
len
(
authorable_blocks
))
self
.
assertEqual
(
0
,
len
(
authorable_blocks
))
...
...
common/djangoapps/xblock_django/tests/test_models.py
deleted
100644 → 0
View file @
71bebec5
"""
Tests for deprecated xblocks in XBlockDisableConfig.
"""
import
ddt
from
mock
import
patch
from
django.test
import
TestCase
from
xblock_django.models
import
XBlockDisableConfig
@ddt.ddt
class
XBlockDisableConfigTestCase
(
TestCase
):
"""
Tests for the DjangoXBlockUserService.
"""
def
setUp
(
self
):
super
(
XBlockDisableConfigTestCase
,
self
)
.
setUp
()
# Initialize the deprecated modules settings with empty list
XBlockDisableConfig
.
objects
.
create
(
disabled_blocks
=
''
,
enabled
=
True
)
@ddt.data
(
(
'poll'
,
[
'poll'
]),
(
'poll survey annotatable textannotation'
,
[
'poll'
,
'survey'
,
'annotatable'
,
'textannotation'
]),
(
''
,
[])
)
@ddt.unpack
def
test_deprecated_blocks_splitting
(
self
,
xblocks
,
expected_result
):
"""
Tests that it correctly splits the xblocks defined in field.
"""
XBlockDisableConfig
.
objects
.
create
(
disabled_create_blocks
=
xblocks
,
enabled
=
True
)
self
.
assertEqual
(
XBlockDisableConfig
.
disabled_create_block_types
(),
expected_result
)
@patch
(
'django.conf.settings.DEPRECATED_ADVANCED_COMPONENT_TYPES'
,
[
'poll'
,
'survey'
])
def
test_deprecated_blocks_file
(
self
):
"""
Tests that deprecated modules contain entries from settings file DEPRECATED_ADVANCED_COMPONENT_TYPES
"""
self
.
assertEqual
(
XBlockDisableConfig
.
disabled_create_block_types
(),
[
'poll'
,
'survey'
])
@patch
(
'django.conf.settings.DEPRECATED_ADVANCED_COMPONENT_TYPES'
,
[
'poll'
,
'survey'
])
def
test_deprecated_blocks_file_and_config
(
self
):
"""
Tests that deprecated types defined in both settings and config model are read.
"""
XBlockDisableConfig
.
objects
.
create
(
disabled_create_blocks
=
'annotatable'
,
enabled
=
True
)
self
.
assertEqual
(
XBlockDisableConfig
.
disabled_create_block_types
(),
[
'annotatable'
,
'poll'
,
'survey'
])
common/lib/xmodule/xmodule/course_module.py
View file @
d4cc7b8f
...
@@ -408,7 +408,7 @@ class CourseFields(object):
...
@@ -408,7 +408,7 @@ class CourseFields(object):
)
)
advanced_modules
=
List
(
advanced_modules
=
List
(
display_name
=
_
(
"Advanced Module List"
),
display_name
=
_
(
"Advanced Module List"
),
help
=
_
(
"Enter the names of the advanced
component
s to use in your course."
),
help
=
_
(
"Enter the names of the advanced
module
s to use in your course."
),
scope
=
Scope
.
settings
scope
=
Scope
.
settings
)
)
has_children
=
True
has_children
=
True
...
@@ -830,6 +830,15 @@ class CourseFields(object):
...
@@ -830,6 +830,15 @@ class CourseFields(object):
},
},
scope
=
Scope
.
settings
scope
=
Scope
.
settings
)
)
allow_unsupported_xblocks
=
Boolean
(
display_name
=
_
(
"Add Unsupported Problems and Tools"
),
help
=
_
(
"Enter true or false. If true, you can add unsupported problems and tools to your course in Studio. "
"Unsupported problems and tools are not recommended for use in courses due to non-compliance with one or "
"more of the base requirements, such as testing, accessibility, internationalization, and documentation."
),
scope
=
Scope
.
settings
,
default
=
False
)
class
CourseModule
(
CourseFields
,
SequenceModule
):
# pylint: disable=abstract-method
class
CourseModule
(
CourseFields
,
SequenceModule
):
# pylint: disable=abstract-method
...
...
lms/envs/common.py
View file @
d4cc7b8f
...
@@ -2905,10 +2905,6 @@ APP_UPGRADE_CACHE_TIMEOUT = 3600
...
@@ -2905,10 +2905,6 @@ APP_UPGRADE_CACHE_TIMEOUT = 3600
# if you want to avoid an overlap in ids while searching for history across the two tables.
# if you want to avoid an overlap in ids while searching for history across the two tables.
STUDENTMODULEHISTORYEXTENDED_OFFSET
=
10000
STUDENTMODULEHISTORYEXTENDED_OFFSET
=
10000
# Deprecated xblock types
DEPRECATED_ADVANCED_COMPONENT_TYPES
=
[]
# Cutoff date for granting audit certificates
# Cutoff date for granting audit certificates
AUDIT_CERT_CUTOFF_DATE
=
None
AUDIT_CERT_CUTOFF_DATE
=
None
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment