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
ef581e11
Commit
ef581e11
authored
Jul 25, 2014
by
Andy Armstrong
Committed by
cahrens
Aug 07, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Apply code review comments and fix tests
parent
9b986049
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
364 additions
and
295 deletions
+364
-295
cms/djangoapps/contentstore/tests/utils.py
+14
-14
cms/djangoapps/contentstore/utils.py
+0
-14
cms/djangoapps/contentstore/views/component.py
+8
-4
cms/djangoapps/contentstore/views/item.py
+37
-29
cms/djangoapps/contentstore/views/tests/test_course_index.py
+3
-2
cms/djangoapps/contentstore/views/tests/test_item.py
+108
-74
cms/static/js/models/xblock_info.js
+8
-7
cms/static/js/spec/views/pages/container_subviews_spec.js
+47
-33
cms/static/js/spec/views/pages/course_outline_spec.js
+1
-5
cms/static/js/spec/views/unit_outline_spec.js
+6
-6
cms/static/js/views/baseview.js
+3
-0
cms/static/js/views/pages/container_subviews.js
+17
-13
cms/static/js/views/unit_outline.js
+0
-1
cms/static/js/views/utils/xblock_utils.js
+52
-2
cms/static/js/views/xblock_outline.js
+6
-1
cms/templates/course_outline.html
+1
-1
cms/templates/js/course-outline.underscore
+4
-15
cms/templates/js/publish-xblock.underscore
+11
-24
cms/templates/js/unit-outline.underscore
+1
-13
cms/templates/widgets/units.html
+1
-2
common/lib/xmodule/xmodule/modulestore/__init__.py
+6
-6
common/lib/xmodule/xmodule/modulestore/mixed.py
+3
-3
common/lib/xmodule/xmodule/modulestore/mongo/draft.py
+8
-8
common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
+7
-7
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+7
-7
common/test/acceptance/tests/base_studio_test.py
+2
-1
common/test/acceptance/tests/test_studio_general.py
+1
-1
common/test/acceptance/tests/test_studio_outline.py
+1
-1
common/test/acceptance/tests/test_studio_split_test.py
+1
-1
No files found.
cms/djangoapps/contentstore/tests/utils.py
View file @
ef581e11
...
@@ -9,7 +9,7 @@ from django.test.client import Client
...
@@ -9,7 +9,7 @@ from django.test.client import Client
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
from
xmodule.contentstore.django
import
contentstore
from
xmodule.contentstore.django
import
contentstore
from
xmodule.modulestore
import
Legacy
PublishState
,
ModuleStoreEnum
,
mongo
from
xmodule.modulestore
import
PublishState
,
ModuleStoreEnum
,
mongo
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.modulestore.inheritance
import
own_metadata
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
...
@@ -151,16 +151,16 @@ class CourseTestCase(ModuleStoreTestCase):
...
@@ -151,16 +151,16 @@ class CourseTestCase(ModuleStoreTestCase):
# create a Draft vertical
# create a Draft vertical
vertical
=
self
.
store
.
get_item
(
course_id
.
make_usage_key
(
'vertical'
,
self
.
TEST_VERTICAL
),
depth
=
1
)
vertical
=
self
.
store
.
get_item
(
course_id
.
make_usage_key
(
'vertical'
,
self
.
TEST_VERTICAL
),
depth
=
1
)
draft_vertical
=
self
.
store
.
convert_to_draft
(
vertical
.
location
,
self
.
user
.
id
)
draft_vertical
=
self
.
store
.
convert_to_draft
(
vertical
.
location
,
self
.
user
.
id
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
draft_vertical
),
Legacy
PublishState
.
draft
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
draft_vertical
),
PublishState
.
draft
)
# create a Private (draft only) vertical
# create a Private (draft only) vertical
private_vertical
=
self
.
store
.
create_item
(
self
.
user
.
id
,
course_id
,
'vertical'
,
self
.
PRIVATE_VERTICAL
)
private_vertical
=
self
.
store
.
create_item
(
self
.
user
.
id
,
course_id
,
'vertical'
,
self
.
PRIVATE_VERTICAL
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
private_vertical
),
Legacy
PublishState
.
private
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
private_vertical
),
PublishState
.
private
)
# create a Published (no draft) vertical
# create a Published (no draft) vertical
public_vertical
=
self
.
store
.
create_item
(
self
.
user
.
id
,
course_id
,
'vertical'
,
self
.
PUBLISHED_VERTICAL
)
public_vertical
=
self
.
store
.
create_item
(
self
.
user
.
id
,
course_id
,
'vertical'
,
self
.
PUBLISHED_VERTICAL
)
public_vertical
=
self
.
store
.
publish
(
public_vertical
.
location
,
self
.
user
.
id
)
public_vertical
=
self
.
store
.
publish
(
public_vertical
.
location
,
self
.
user
.
id
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
public_vertical
),
Legacy
PublishState
.
public
)
self
.
assertEqual
(
self
.
store
.
compute_publish_state
(
public_vertical
),
PublishState
.
public
)
# add the new private and new public as children of the sequential
# add the new private and new public as children of the sequential
sequential
=
self
.
store
.
get_item
(
course_id
.
make_usage_key
(
'sequential'
,
self
.
SEQUENTIAL
))
sequential
=
self
.
store
.
get_item
(
course_id
.
make_usage_key
(
'sequential'
,
self
.
SEQUENTIAL
))
...
@@ -197,7 +197,7 @@ class CourseTestCase(ModuleStoreTestCase):
...
@@ -197,7 +197,7 @@ class CourseTestCase(ModuleStoreTestCase):
def
verify_item_publish_state
(
item
,
publish_state
):
def
verify_item_publish_state
(
item
,
publish_state
):
"""Verifies the publish state of the item is as expected."""
"""Verifies the publish state of the item is as expected."""
if
publish_state
in
(
LegacyPublishState
.
private
,
Legacy
PublishState
.
draft
):
if
publish_state
in
(
PublishState
.
private
,
PublishState
.
draft
):
self
.
assertTrue
(
getattr
(
item
,
'is_draft'
,
False
))
self
.
assertTrue
(
getattr
(
item
,
'is_draft'
,
False
))
else
:
else
:
self
.
assertFalse
(
getattr
(
item
,
'is_draft'
,
False
))
self
.
assertFalse
(
getattr
(
item
,
'is_draft'
,
False
))
...
@@ -210,18 +210,18 @@ class CourseTestCase(ModuleStoreTestCase):
...
@@ -210,18 +210,18 @@ class CourseTestCase(ModuleStoreTestCase):
return
item
return
item
# verify that the draft vertical is draft
# verify that the draft vertical is draft
vertical
=
get_and_verify_publish_state
(
'vertical'
,
self
.
TEST_VERTICAL
,
Legacy
PublishState
.
draft
)
vertical
=
get_and_verify_publish_state
(
'vertical'
,
self
.
TEST_VERTICAL
,
PublishState
.
draft
)
for
child
in
vertical
.
get_children
():
for
child
in
vertical
.
get_children
():
verify_item_publish_state
(
child
,
Legacy
PublishState
.
draft
)
verify_item_publish_state
(
child
,
PublishState
.
draft
)
# make sure that we don't have a sequential that is not in draft mode
# make sure that we don't have a sequential that is not in draft mode
sequential
=
get_and_verify_publish_state
(
'sequential'
,
self
.
SEQUENTIAL
,
Legacy
PublishState
.
public
)
sequential
=
get_and_verify_publish_state
(
'sequential'
,
self
.
SEQUENTIAL
,
PublishState
.
public
)
# verify that we have the private vertical
# verify that we have the private vertical
private_vertical
=
get_and_verify_publish_state
(
'vertical'
,
self
.
PRIVATE_VERTICAL
,
Legacy
PublishState
.
private
)
private_vertical
=
get_and_verify_publish_state
(
'vertical'
,
self
.
PRIVATE_VERTICAL
,
PublishState
.
private
)
# verify that we have the public vertical
# verify that we have the public vertical
public_vertical
=
get_and_verify_publish_state
(
'vertical'
,
self
.
PUBLISHED_VERTICAL
,
Legacy
PublishState
.
public
)
public_vertical
=
get_and_verify_publish_state
(
'vertical'
,
self
.
PUBLISHED_VERTICAL
,
PublishState
.
public
)
# verify verticals are children of sequential
# verify verticals are children of sequential
for
vert
in
[
vertical
,
private_vertical
,
public_vertical
]:
for
vert
in
[
vertical
,
private_vertical
,
public_vertical
]:
...
@@ -332,7 +332,7 @@ class CourseTestCase(ModuleStoreTestCase):
...
@@ -332,7 +332,7 @@ class CourseTestCase(ModuleStoreTestCase):
it'll return public in that case
it'll return public in that case
"""
"""
supposed_state
=
self
.
store
.
compute_publish_state
(
item
)
supposed_state
=
self
.
store
.
compute_publish_state
(
item
)
if
supposed_state
==
Legacy
PublishState
.
draft
and
isinstance
(
item
.
runtime
.
modulestore
,
DraftModuleStore
):
if
supposed_state
==
PublishState
.
draft
and
isinstance
(
item
.
runtime
.
modulestore
,
DraftModuleStore
):
# see if the draft differs from the published
# see if the draft differs from the published
published
=
self
.
store
.
get_item
(
item
.
location
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
)
published
=
self
.
store
.
get_item
(
item
.
location
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
)
if
item
.
get_explicitly_set_fields_by_scope
()
!=
published
.
get_explicitly_set_fields_by_scope
():
if
item
.
get_explicitly_set_fields_by_scope
()
!=
published
.
get_explicitly_set_fields_by_scope
():
...
@@ -345,13 +345,13 @@ class CourseTestCase(ModuleStoreTestCase):
...
@@ -345,13 +345,13 @@ class CourseTestCase(ModuleStoreTestCase):
# checking children: if published differs from item, return draft
# checking children: if published differs from item, return draft
return
supposed_state
return
supposed_state
# published == item in all respects, so return public
# published == item in all respects, so return public
return
Legacy
PublishState
.
public
return
PublishState
.
public
elif
supposed_state
==
Legacy
PublishState
.
public
and
item
.
location
.
category
in
DIRECT_ONLY_CATEGORIES
:
elif
supposed_state
==
PublishState
.
public
and
item
.
location
.
category
in
DIRECT_ONLY_CATEGORIES
:
if
not
all
([
if
not
all
([
self
.
store
.
has_item
(
child_loc
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
draft_only
)
self
.
store
.
has_item
(
child_loc
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
draft_only
)
for
child_loc
in
item
.
children
for
child_loc
in
item
.
children
]):
]):
return
Legacy
PublishState
.
draft
return
PublishState
.
draft
else
:
else
:
return
supposed_state
return
supposed_state
else
:
else
:
...
...
cms/djangoapps/contentstore/utils.py
View file @
ef581e11
...
@@ -150,20 +150,6 @@ def course_image_url(course):
...
@@ -150,20 +150,6 @@ def course_image_url(course):
return
path
return
path
def
compute_publish_state
(
xblock
):
"""
Returns whether this xblock is draft, public, or private.
Returns:
LegacyPublishState.draft - content is in the process of being edited, but still has a previous
version deployed to LMS
LegacyPublishState.public - content is locked and deployed to LMS
LegacyPublishState.private - content is editable and not deployed to LMS
"""
return
modulestore
()
.
compute_publish_state
(
xblock
)
def
is_currently_visible_to_students
(
xblock
):
def
is_currently_visible_to_students
(
xblock
):
"""
"""
Returns true if there is a published version of the xblock that is currently visible to students.
Returns true if there is a published version of the xblock that is currently visible to students.
...
...
cms/djangoapps/contentstore/views/component.py
View file @
ef581e11
...
@@ -11,8 +11,8 @@ from django.conf import settings
...
@@ -11,8 +11,8 @@ from django.conf import settings
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
edxmako.shortcuts
import
render_to_response
from
edxmako.shortcuts
import
render_to_response
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore
import
LegacyPublishState
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.django.request
import
webob_to_django_response
,
django_to_webob_request
from
xblock.django.request
import
webob_to_django_response
,
django_to_webob_request
...
@@ -21,7 +21,7 @@ from xblock.fields import Scope
...
@@ -21,7 +21,7 @@ from xblock.fields import Scope
from
xblock.plugin
import
PluginMissingError
from
xblock.plugin
import
PluginMissingError
from
xblock.runtime
import
Mixologist
from
xblock.runtime
import
Mixologist
from
contentstore.utils
import
get_lms_link_for_item
,
compute_publish_state
from
contentstore.utils
import
get_lms_link_for_item
from
contentstore.views.helpers
import
get_parent_xblock
,
is_unit
,
xblock_type_display_name
from
contentstore.views.helpers
import
get_parent_xblock
,
is_unit
,
xblock_type_display_name
from
contentstore.views.item
import
create_xblock_info
from
contentstore.views.item
import
create_xblock_info
...
@@ -100,8 +100,8 @@ def subsection_handler(request, usage_key_string):
...
@@ -100,8 +100,8 @@ def subsection_handler(request, usage_key_string):
can_view_live
=
False
can_view_live
=
False
subsection_units
=
item
.
get_children
()
subsection_units
=
item
.
get_children
()
for
unit
in
subsection_units
:
for
unit
in
subsection_units
:
state
=
compute_publish_state
(
unit
)
has_published
=
modulestore
()
.
has_item
(
unit
.
location
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
)
if
state
in
(
LegacyPublishState
.
public
,
LegacyPublishState
.
draft
)
:
if
has_published
:
can_view_live
=
True
can_view_live
=
True
break
break
...
@@ -178,6 +178,10 @@ def container_handler(request, usage_key_string):
...
@@ -178,6 +178,10 @@ def container_handler(request, usage_key_string):
# about the block's ancestors and siblings for use by the Unit Outline.
# about the block's ancestors and siblings for use by the Unit Outline.
xblock_info
=
create_xblock_info
(
xblock
,
include_ancestor_info
=
is_unit_page
)
xblock_info
=
create_xblock_info
(
xblock
,
include_ancestor_info
=
is_unit_page
)
# On the unit page only, add 'has_changes' to indicate when there are changes that can be discarded.
if
is_unit_page
:
xblock_info
[
'has_changes'
]
=
modulestore
()
.
has_changes
(
xblock
.
location
)
# Create the link for preview.
# Create the link for preview.
preview_lms_base
=
settings
.
FEATURES
.
get
(
'PREVIEW_LMS_BASE'
)
preview_lms_base
=
settings
.
FEATURES
.
get
(
'PREVIEW_LMS_BASE'
)
# need to figure out where this item is in the list of children as the
# need to figure out where this item is in the list of children as the
...
...
cms/djangoapps/contentstore/views/item.py
View file @
ef581e11
...
@@ -636,9 +636,9 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
...
@@ -636,9 +636,9 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
"id"
:
unicode
(
xblock
.
location
),
"id"
:
unicode
(
xblock
.
location
),
"display_name"
:
xblock
.
display_name_with_default
,
"display_name"
:
xblock
.
display_name_with_default
,
"category"
:
xblock
.
category
,
"category"
:
xblock
.
category
,
"published"
:
published
,
"edited_on"
:
get_default_time_display
(
xblock
.
subtree_edited_on
)
if
xblock
.
subtree_edited_on
else
None
,
"edited_on"
:
get_default_time_display
(
xblock
.
subtree_edited_on
)
if
xblock
.
subtree_edited_on
else
None
,
"edited_by"
:
safe_get_username
(
xblock
.
subtree_edited_by
),
"edited_by"
:
safe_get_username
(
xblock
.
subtree_edited_by
),
"published"
:
published
,
"published_on"
:
get_default_time_display
(
xblock
.
published_date
)
if
xblock
.
published_date
else
None
,
"published_on"
:
get_default_time_display
(
xblock
.
published_date
)
if
xblock
.
published_date
else
None
,
"published_by"
:
safe_get_username
(
xblock
.
published_by
),
"published_by"
:
safe_get_username
(
xblock
.
published_by
),
'studio_url'
:
xblock_studio_url
(
xblock
),
'studio_url'
:
xblock_studio_url
(
xblock
),
...
@@ -646,7 +646,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
...
@@ -646,7 +646,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
"release_date"
:
release_date
,
"release_date"
:
release_date
,
"release_date_from"
:
_get_release_date_from
(
xblock
)
if
release_date
else
None
,
"release_date_from"
:
_get_release_date_from
(
xblock
)
if
release_date
else
None
,
"currently_visible_to_students"
:
currently_visible_to_students
,
"currently_visible_to_students"
:
currently_visible_to_students
,
"
publish_state"
:
_compute_publish
_state
(
xblock
,
child_info
)
if
not
xblock
.
category
==
'course'
else
None
"
visibility_state"
:
_compute_visibility
_state
(
xblock
,
child_info
)
if
not
xblock
.
category
==
'course'
else
None
}
}
if
data
is
not
None
:
if
data
is
not
None
:
xblock_info
[
"data"
]
=
data
xblock_info
[
"data"
]
=
data
...
@@ -659,63 +659,71 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
...
@@ -659,63 +659,71 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
return
xblock_info
return
xblock_info
class
Publish
State
(
object
):
class
Visibility
State
(
object
):
"""
"""
Represents the possible publish states for an xblock:
Represents the possible visibility states for an xblock:
live - the block and all of its children are live to students (except for staff only items)
ready - the block and all of its children are ready to go live in the future
live - the block and all of its descendants are live to students (excluding staff only items)
unscheduled - the block and all of its children are unscheduled
Note: Live means both published and released.
has_unpublished_content - the block or its children have unpublished content that is not staff only
ready - the block is ready to go live and all of its descendants are live or ready (excluding staff only items)
Note: content is ready when it is published and scheduled with a release date in the future.
unscheduled - the block and all of its descendants have no release date (excluding staff only items)
Note: it is valid for items to be published with no release date in which case they are still unscheduled.
needs_attention - the block or its descendants are not fully live, ready or unscheduled (excluding staff only items)
For example: one subsection has draft content, or there's both unreleased and released content in one section.
staff_only - all of the block's content is to be shown to staff only
staff_only - all of the block's content is to be shown to staff only
Note: staff only items do not affect their parent's state.
"""
"""
live
=
'live'
live
=
'live'
ready
=
'ready'
ready
=
'ready'
unscheduled
=
'unscheduled'
unscheduled
=
'unscheduled'
# unscheduled
has_unpublished_content
=
'has_unpublished_content
'
needs_attention
=
'needs_attention
'
staff_only
=
'staff_only'
staff_only
=
'staff_only'
def
_compute_
publish
_state
(
xblock
,
child_info
):
def
_compute_
visibility
_state
(
xblock
,
child_info
):
"""
"""
Returns the current publish state for the specified xblock and its children
Returns the current publish state for the specified xblock and its children
"""
"""
if
xblock
.
visible_to_staff_only
:
if
xblock
.
visible_to_staff_only
:
return
Publish
State
.
staff_only
return
Visibility
State
.
staff_only
elif
is_unit
(
xblock
)
and
modulestore
()
.
has_changes
(
xblock
.
location
):
elif
is_unit
(
xblock
)
and
modulestore
()
.
has_changes
(
xblock
.
location
):
return
PublishState
.
has_unpublished_content
return
VisibilityState
.
needs_attention
is_unscheduled
=
xblock
.
start
==
DEFAULT_START_DATE
is_unscheduled
=
xblock
.
start
==
DEFAULT_START_DATE
is_live
=
datetime
.
now
(
UTC
)
>
xblock
.
start
children
=
child_info
and
child_info
[
'children'
]
children
=
child_info
and
child_info
[
'children'
]
if
children
and
len
(
children
)
>
0
:
if
children
and
len
(
children
)
>
0
:
all_staff_only
=
True
all_staff_only
=
True
all_unscheduled
=
True
all_unscheduled
=
True
all_live
=
True
all_live
=
True
for
child
in
child_info
[
'children'
]:
for
child
in
child_info
[
'children'
]:
child_state
=
child
[
'
publish
_state'
]
child_state
=
child
[
'
visibility
_state'
]
if
child_state
==
PublishState
.
has_unpublished_content
:
if
child_state
==
VisibilityState
.
needs_attention
:
return
child_state
return
child_state
elif
not
child_state
==
Publish
State
.
staff_only
:
elif
not
child_state
==
Visibility
State
.
staff_only
:
all_staff_only
=
False
all_staff_only
=
False
if
not
child_state
==
Publish
State
.
unscheduled
:
if
not
child_state
==
Visibility
State
.
unscheduled
:
all_unscheduled
=
False
all_unscheduled
=
False
if
not
child_state
==
Publish
State
.
live
:
if
not
child_state
==
Visibility
State
.
live
:
all_live
=
False
all_live
=
False
if
all_staff_only
:
if
all_staff_only
:
return
Publish
State
.
staff_only
return
Visibility
State
.
staff_only
elif
all_unscheduled
:
elif
all_unscheduled
:
if
not
is_unscheduled
:
return
VisibilityState
.
unscheduled
if
is_unscheduled
else
VisibilityState
.
needs_attention
return
PublishState
.
has_unpublished_content
else
:
return
PublishState
.
unscheduled
elif
all_live
:
elif
all_live
:
return
PublishState
.
live
return
VisibilityState
.
live
if
is_live
else
VisibilityState
.
needs_attention
else
:
else
:
return
PublishState
.
ready
return
VisibilityState
.
ready
if
not
is_unscheduled
else
VisibilityState
.
needs_attention
if
is_unscheduled
:
if
is_unscheduled
:
return
Publish
State
.
unscheduled
return
Visibility
State
.
unscheduled
elif
datetime
.
now
(
UTC
)
>
xblock
.
start
:
elif
is_live
:
return
Publish
State
.
live
return
Visibility
State
.
live
else
:
else
:
return
Publish
State
.
ready
return
Visibility
State
.
ready
def
_create_xblock_ancestor_info
(
xblock
):
def
_create_xblock_ancestor_info
(
xblock
):
...
...
cms/djangoapps/contentstore/views/tests/test_course_index.py
View file @
ef581e11
...
@@ -8,6 +8,7 @@ from contentstore.tests.utils import CourseTestCase
...
@@ -8,6 +8,7 @@ from contentstore.tests.utils import CourseTestCase
from
contentstore.utils
import
reverse_course_url
,
add_instructor
from
contentstore.utils
import
reverse_course_url
,
add_instructor
from
contentstore.views.access
import
has_course_access
from
contentstore.views.access
import
has_course_access
from
contentstore.views.course
import
course_outline_initial_state
from
contentstore.views.course
import
course_outline_initial_state
from
contentstore.views.item
import
create_xblock_info
,
VisibilityState
from
course_action_state.models
import
CourseRerunState
from
course_action_state.models
import
CourseRerunState
from
contentstore.views.item
import
create_xblock_info
from
contentstore.views.item
import
create_xblock_info
from
contentstore.views.item
import
create_xblock_info
,
PublishState
from
contentstore.views.item
import
create_xblock_info
,
PublishState
...
@@ -230,7 +231,7 @@ class TestCourseOutline(CourseTestCase):
...
@@ -230,7 +231,7 @@ class TestCourseOutline(CourseTestCase):
self
.
assertEqual
(
json_response
[
'category'
],
'course'
)
self
.
assertEqual
(
json_response
[
'category'
],
'course'
)
self
.
assertEqual
(
json_response
[
'id'
],
'i4x://MITx/999/course/Robot_Super_Course'
)
self
.
assertEqual
(
json_response
[
'id'
],
'i4x://MITx/999/course/Robot_Super_Course'
)
self
.
assertEqual
(
json_response
[
'display_name'
],
'Robot Super Course'
)
self
.
assertEqual
(
json_response
[
'display_name'
],
'Robot Super Course'
)
self
.
assertIsNone
(
json_response
[
'
publish
_state'
])
self
.
assertIsNone
(
json_response
[
'
visibility
_state'
])
# Now verify the first child
# Now verify the first child
children
=
json_response
[
'child_info'
][
'children'
]
children
=
json_response
[
'child_info'
][
'children'
]
...
@@ -239,7 +240,7 @@ class TestCourseOutline(CourseTestCase):
...
@@ -239,7 +240,7 @@ class TestCourseOutline(CourseTestCase):
self
.
assertEqual
(
first_child_response
[
'category'
],
'chapter'
)
self
.
assertEqual
(
first_child_response
[
'category'
],
'chapter'
)
self
.
assertEqual
(
first_child_response
[
'id'
],
'i4x://MITx/999/chapter/Week_1'
)
self
.
assertEqual
(
first_child_response
[
'id'
],
'i4x://MITx/999/chapter/Week_1'
)
self
.
assertEqual
(
first_child_response
[
'display_name'
],
'Week 1'
)
self
.
assertEqual
(
first_child_response
[
'display_name'
],
'Week 1'
)
self
.
assertEqual
(
first_child_response
[
'
publish_state'
],
Publish
State
.
unscheduled
)
self
.
assertEqual
(
first_child_response
[
'
visibility_state'
],
Visibility
State
.
unscheduled
)
self
.
assertTrue
(
len
(
first_child_response
[
'child_info'
][
'children'
])
>
0
)
self
.
assertTrue
(
len
(
first_child_response
[
'child_info'
][
'children'
])
>
0
)
# Finally, validate the entire response for consistency
# Finally, validate the entire response for consistency
...
...
cms/djangoapps/contentstore/views/tests/test_item.py
View file @
ef581e11
...
@@ -19,11 +19,11 @@ from contentstore.views.component import (
...
@@ -19,11 +19,11 @@ from contentstore.views.component import (
component_handler
,
get_component_templates
component_handler
,
get_component_templates
)
)
from
contentstore.views.item
import
create_xblock_info
,
ALWAYS
,
Publish
State
from
contentstore.views.item
import
create_xblock_info
,
ALWAYS
,
Visibility
State
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
xmodule.capa_module
import
CapaDescriptor
from
xmodule.capa_module
import
CapaDescriptor
from
xmodule.modulestore
import
LegacyPublishState
,
ModuleStoreEnum
from
xmodule.modulestore
import
ModuleStoreEnum
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.tests.factories
import
ItemFactory
from
xmodule.modulestore.tests.factories
import
ItemFactory
from
xmodule.x_module
import
STUDIO_VIEW
,
STUDENT_VIEW
from
xmodule.x_module
import
STUDIO_VIEW
,
STUDENT_VIEW
...
@@ -425,19 +425,6 @@ class TestEditItem(ItemTest):
...
@@ -425,19 +425,6 @@ class TestEditItem(ItemTest):
self
.
course_update_url
=
reverse_usage_url
(
"xblock_handler"
,
self
.
usage_key
)
self
.
course_update_url
=
reverse_usage_url
(
"xblock_handler"
,
self
.
usage_key
)
def
verify_publish_state
(
self
,
usage_key
,
expected_publish_state
):
"""
Helper method that gets the item from the module store and verifies that the publish state is as expected.
Returns the item corresponding to the given usage_key.
"""
item
=
self
.
get_item_from_modulestore
(
usage_key
,
(
expected_publish_state
==
LegacyPublishState
.
private
)
or
(
expected_publish_state
==
LegacyPublishState
.
draft
)
)
self
.
assertEqual
(
expected_publish_state
,
self
.
store
.
compute_publish_state
(
item
))
return
item
def
test_delete_field
(
self
):
def
test_delete_field
(
self
):
"""
"""
Sending null in for a field 'deletes' it
Sending null in for a field 'deletes' it
...
@@ -543,15 +530,18 @@ class TestEditItem(ItemTest):
...
@@ -543,15 +530,18 @@ class TestEditItem(ItemTest):
self
.
assertEqual
(
unit1_usage_key
,
children
[
2
])
self
.
assertEqual
(
unit1_usage_key
,
children
[
2
])
self
.
assertEqual
(
unit2_usage_key
,
children
[
1
])
self
.
assertEqual
(
unit2_usage_key
,
children
[
1
])
def
_is_location_published
(
self
,
location
):
return
modulestore
()
.
has_item
(
location
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
)
def
test_make_public
(
self
):
def
test_make_public
(
self
):
""" Test making a private problem public (publishing it). """
""" Test making a private problem public (publishing it). """
# When the problem is first created, it is only in draft (because of its category).
# When the problem is first created, it is only in draft (because of its category).
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
private
)
self
.
assertFalse
(
self
.
_is_location_published
(
self
.
problem_usage_key
)
)
self
.
client
.
ajax_post
(
self
.
client
.
ajax_post
(
self
.
problem_update_url
,
self
.
problem_update_url
,
data
=
{
'publish'
:
'make_public'
}
data
=
{
'publish'
:
'make_public'
}
)
)
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
public
)
self
.
assertTrue
(
self
.
_is_location_published
(
self
.
problem_usage_key
)
)
def
test_make_draft
(
self
):
def
test_make_draft
(
self
):
""" Test creating a draft version of a public problem. """
""" Test creating a draft version of a public problem. """
...
@@ -564,7 +554,8 @@ class TestEditItem(ItemTest):
...
@@ -564,7 +554,8 @@ class TestEditItem(ItemTest):
self
.
problem_update_url
,
self
.
problem_update_url
,
data
=
{
'publish'
:
'discard_changes'
}
data
=
{
'publish'
:
'discard_changes'
}
)
)
published
=
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
public
)
self
.
assertTrue
(
self
.
_is_location_published
(
self
.
problem_usage_key
))
published
=
modulestore
()
.
get_item
(
self
.
problem_usage_key
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
)
self
.
assertIsNone
(
published
.
due
)
self
.
assertIsNone
(
published
.
due
)
def
test_republish
(
self
):
def
test_republish
(
self
):
...
@@ -576,7 +567,7 @@ class TestEditItem(ItemTest):
...
@@ -576,7 +567,7 @@ class TestEditItem(ItemTest):
}
}
# When the problem is first created, it is only in draft (because of its category).
# When the problem is first created, it is only in draft (because of its category).
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
private
)
self
.
assertFalse
(
self
.
_is_location_published
(
self
.
problem_usage_key
)
)
# Republishing when only in draft will update the draft but not cause a public item to be created.
# Republishing when only in draft will update the draft but not cause a public item to be created.
self
.
client
.
ajax_post
(
self
.
client
.
ajax_post
(
...
@@ -588,7 +579,7 @@ class TestEditItem(ItemTest):
...
@@ -588,7 +579,7 @@ class TestEditItem(ItemTest):
}
}
}
}
)
)
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
private
)
self
.
assertFalse
(
self
.
_is_location_published
(
self
.
problem_usage_key
)
)
draft
=
self
.
get_item_from_modulestore
(
self
.
problem_usage_key
,
verify_is_draft
=
True
)
draft
=
self
.
get_item_from_modulestore
(
self
.
problem_usage_key
,
verify_is_draft
=
True
)
self
.
assertEqual
(
draft
.
display_name
,
new_display_name
)
self
.
assertEqual
(
draft
.
display_name
,
new_display_name
)
...
@@ -609,7 +600,7 @@ class TestEditItem(ItemTest):
...
@@ -609,7 +600,7 @@ class TestEditItem(ItemTest):
}
}
}
}
)
)
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
public
)
self
.
assertTrue
(
self
.
_is_location_published
(
self
.
problem_usage_key
)
)
published
=
modulestore
()
.
get_item
(
published
=
modulestore
()
.
get_item
(
self
.
problem_usage_key
,
self
.
problem_usage_key
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
...
@@ -625,7 +616,8 @@ class TestEditItem(ItemTest):
...
@@ -625,7 +616,8 @@ class TestEditItem(ItemTest):
self
.
problem_update_url
,
self
.
problem_update_url
,
data
=
{
'publish'
:
'make_public'
}
data
=
{
'publish'
:
'make_public'
}
)
)
published
=
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
public
)
self
.
assertTrue
(
self
.
_is_location_published
(
self
.
problem_usage_key
))
published
=
modulestore
()
.
get_item
(
self
.
problem_usage_key
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
)
# Update the draft version and check that published is different.
# Update the draft version and check that published is different.
self
.
client
.
ajax_post
(
self
.
client
.
ajax_post
(
...
@@ -659,7 +651,8 @@ class TestEditItem(ItemTest):
...
@@ -659,7 +651,8 @@ class TestEditItem(ItemTest):
self
.
problem_update_url
,
self
.
problem_update_url
,
data
=
{
'publish'
:
'make_public'
}
data
=
{
'publish'
:
'make_public'
}
)
)
published
=
self
.
verify_publish_state
(
self
.
problem_usage_key
,
LegacyPublishState
.
public
)
self
.
assertTrue
(
self
.
_is_location_published
(
self
.
problem_usage_key
))
published
=
modulestore
()
.
get_item
(
self
.
problem_usage_key
,
revision
=
ModuleStoreEnum
.
RevisionOption
.
published_only
)
# Now make a draft
# Now make a draft
self
.
client
.
ajax_post
(
self
.
client
.
ajax_post
(
...
@@ -704,8 +697,8 @@ class TestEditItem(ItemTest):
...
@@ -704,8 +697,8 @@ class TestEditItem(ItemTest):
# The unit and its children should be private initially
# The unit and its children should be private initially
unit_update_url
=
reverse_usage_url
(
'xblock_handler'
,
unit_usage_key
)
unit_update_url
=
reverse_usage_url
(
'xblock_handler'
,
unit_usage_key
)
self
.
verify_publish_state
(
unit_usage_key
,
LegacyPublishState
.
private
)
self
.
assertFalse
(
self
.
_is_location_published
(
unit_usage_key
)
)
self
.
verify_publish_state
(
html_usage_key
,
LegacyPublishState
.
private
)
self
.
assertFalse
(
self
.
_is_location_published
(
html_usage_key
)
)
# Make the unit public and verify that the problem is also made public
# Make the unit public and verify that the problem is also made public
resp
=
self
.
client
.
ajax_post
(
resp
=
self
.
client
.
ajax_post
(
...
@@ -713,8 +706,8 @@ class TestEditItem(ItemTest):
...
@@ -713,8 +706,8 @@ class TestEditItem(ItemTest):
data
=
{
'publish'
:
'make_public'
}
data
=
{
'publish'
:
'make_public'
}
)
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
verify_publish_state
(
unit_usage_key
,
LegacyPublishState
.
public
)
self
.
assertTrue
(
self
.
_is_location_published
(
unit_usage_key
)
)
self
.
verify_publish_state
(
html_usage_key
,
LegacyPublishState
.
public
)
self
.
assertTrue
(
self
.
_is_location_published
(
html_usage_key
)
)
# Make a draft for the unit and verify that the problem also has a draft
# Make a draft for the unit and verify that the problem also has a draft
resp
=
self
.
client
.
ajax_post
(
resp
=
self
.
client
.
ajax_post
(
...
@@ -725,8 +718,10 @@ class TestEditItem(ItemTest):
...
@@ -725,8 +718,10 @@ class TestEditItem(ItemTest):
}
}
)
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
assertEqual
(
resp
.
status_code
,
200
)
self
.
verify_publish_state
(
unit_usage_key
,
LegacyPublishState
.
draft
)
self
.
assertTrue
(
self
.
_is_location_published
(
unit_usage_key
))
self
.
verify_publish_state
(
html_usage_key
,
LegacyPublishState
.
draft
)
self
.
assertTrue
(
self
.
_is_location_published
(
html_usage_key
))
self
.
assertTrue
(
modulestore
()
.
get_item
(
unit_usage_key
)
.
has_changes
())
self
.
assertTrue
(
modulestore
()
.
get_item
(
html_usage_key
)
.
has_changes
())
class
TestEditSplitModule
(
ItemTest
):
class
TestEditSplitModule
(
ItemTest
):
...
@@ -1243,10 +1238,14 @@ class TestXBlockPublishingInfo(ItemTest):
...
@@ -1243,10 +1238,14 @@ class TestXBlockPublishingInfo(ItemTest):
"""
"""
Unit tests for XBlock's outline handling.
Unit tests for XBlock's outline handling.
"""
"""
def
_create_child
(
self
,
parent
,
category
,
display_name
,
publish_item
=
False
):
FIRST_SUBSECTION_PATH
=
[
0
]
FIRST_UNIT_PATH
=
[
0
,
0
]
SECOND_UNIT_PATH
=
[
0
,
1
]
def
_create_child
(
self
,
parent
,
category
,
display_name
,
publish_item
=
False
,
staff_only
=
False
):
return
ItemFactory
.
create
(
return
ItemFactory
.
create
(
parent_location
=
parent
.
location
,
category
=
category
,
display_name
=
display_name
,
parent_location
=
parent
.
location
,
category
=
category
,
display_name
=
display_name
,
user_id
=
self
.
user
.
id
,
publish_item
=
publish_item
user_id
=
self
.
user
.
id
,
publish_item
=
publish_item
,
visible_to_staff_only
=
staff_only
)
)
def
_get_child
(
self
,
xblock_info
,
index
):
def
_get_child
(
self
,
xblock_info
,
index
):
...
@@ -1291,87 +1290,122 @@ class TestXBlockPublishingInfo(ItemTest):
...
@@ -1291,87 +1290,122 @@ class TestXBlockPublishingInfo(ItemTest):
xblock
.
display_name
=
display_name
xblock
.
display_name
=
display_name
self
.
store
.
update_item
(
xblock
,
self
.
user
.
id
)
self
.
store
.
update_item
(
xblock
,
self
.
user
.
id
)
def
test_empty_chapter_publishing_info
(
self
):
def
_verify_visibility_state
(
self
,
xblock_info
,
expected_state
,
path
=
None
):
"""
Verify the publish state of an item in the xblock_info. If no path is provided
then the root item is verified.
"""
if
path
:
direct_child
=
self
.
_get_child
(
xblock_info
,
path
[
0
])
remaining_path
=
path
[
1
:]
if
len
(
path
)
>
1
else
None
self
.
_verify_visibility_state
(
direct_child
,
expected_state
,
remaining_path
)
else
:
self
.
assertEqual
(
xblock_info
[
'visibility_state'
],
expected_state
)
def
test_empty_chapter
(
self
):
empty_chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Empty Chapter"
)
empty_chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Empty Chapter"
)
xblock_info
=
self
.
_get_xblock_info
(
empty_chapter
.
location
)
xblock_info
=
self
.
_get_xblock_info
(
empty_chapter
.
location
)
self
.
assertEqual
(
xblock_info
[
'
publish_state'
],
Publish
State
.
unscheduled
)
self
.
assertEqual
(
xblock_info
[
'
visibility_state'
],
Visibility
State
.
unscheduled
)
def
test_empty_se
ction_publishing_info
(
self
):
def
test_empty_se
quential
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
self
.
_create_child
(
chapter
,
'sequential'
,
"Empty Sequential"
)
self
.
_create_child
(
chapter
,
'sequential'
,
"Empty Sequential"
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
self
.
assertEqual
(
xblock_info
[
'
publish_state'
],
Publish
State
.
unscheduled
)
self
.
assertEqual
(
xblock_info
[
'
visibility_state'
],
Visibility
State
.
unscheduled
)
self
.
assertEqual
(
self
.
_get_child
(
xblock_info
,
0
)[
'
publish_state'
],
Publish
State
.
unscheduled
)
self
.
assertEqual
(
self
.
_get_child
(
xblock_info
,
0
)[
'
visibility_state'
],
Visibility
State
.
unscheduled
)
def
test_published_unit
_publishing_info
(
self
):
def
test_published_unit
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Staff Only Unit"
,
staff_only
=
True
)
self
.
_set_release_date
(
chapter
.
location
,
datetime
.
now
(
UTC
)
+
timedelta
(
days
=
1
))
self
.
_set_release_date
(
chapter
.
location
,
datetime
.
now
(
UTC
)
+
timedelta
(
days
=
1
))
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
self
.
assertEqual
(
xblock_info
[
'publish_state'
],
PublishState
.
ready
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
ready
)
sequential_child_info
=
self
.
_get_child
(
xblock_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
ready
,
path
=
self
.
FIRST_SUBSECTION_PATH
)
self
.
assertEqual
(
sequential_child_info
[
'publish_state'
],
PublishState
.
ready
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
ready
,
path
=
self
.
FIRST_UNIT_PATH
)
unit_child_info
=
self
.
_get_child
(
sequential_child_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
self
.
SECOND_UNIT_PATH
)
self
.
assertEqual
(
unit_child_info
[
'publish_state'
],
PublishState
.
ready
)
def
test_released_unit
_publishing_info
(
self
):
def
test_released_unit
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Staff Only Unit"
,
staff_only
=
True
)
self
.
_set_release_date
(
chapter
.
location
,
datetime
.
now
(
UTC
)
-
timedelta
(
days
=
1
))
self
.
_set_release_date
(
chapter
.
location
,
datetime
.
now
(
UTC
)
-
timedelta
(
days
=
1
))
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
self
.
assertEqual
(
xblock_info
[
'publish_state'
],
PublishState
.
live
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
)
sequential_child_info
=
self
.
_get_child
(
xblock_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
self
.
FIRST_SUBSECTION_PATH
)
self
.
assertEqual
(
sequential_child_info
[
'publish_state'
],
PublishState
.
live
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
self
.
FIRST_UNIT_PATH
)
unit_child_info
=
self
.
_get_child
(
sequential_child_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
self
.
SECOND_UNIT_PATH
)
self
.
assertEqual
(
unit_child_info
[
'publish_state'
],
PublishState
.
live
)
def
test_unpublished_changes
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
unit
=
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Staff Only Unit"
,
staff_only
=
True
)
self
.
_set_display_name
(
unit
.
location
,
'Updated Unit'
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
needs_attention
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
needs_attention
,
path
=
self
.
FIRST_SUBSECTION_PATH
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
needs_attention
,
path
=
self
.
FIRST_UNIT_PATH
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
self
.
SECOND_UNIT_PATH
)
def
test_partially_released_section
_publishing_info
(
self
):
def
test_partially_released_section
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
released_sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Released Sequential"
)
released_sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Released Sequential"
)
self
.
_create_child
(
released_sequential
,
'vertical'
,
"Released Unit"
,
publish_item
=
True
)
self
.
_create_child
(
released_sequential
,
'vertical'
,
"Released Unit"
,
publish_item
=
True
)
self
.
_create_child
(
released_sequential
,
'vertical'
,
"Staff Only Unit"
,
staff_only
=
True
)
self
.
_set_release_date
(
chapter
.
location
,
datetime
.
now
(
UTC
)
-
timedelta
(
days
=
1
))
self
.
_set_release_date
(
chapter
.
location
,
datetime
.
now
(
UTC
)
-
timedelta
(
days
=
1
))
published_sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Published Sequential"
)
published_sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Published Sequential"
)
self
.
_create_child
(
published_sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
published_sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
published_sequential
,
'vertical'
,
"Staff Only Unit"
,
staff_only
=
True
)
self
.
_set_release_date
(
published_sequential
.
location
,
datetime
.
now
(
UTC
)
+
timedelta
(
days
=
1
))
self
.
_set_release_date
(
published_sequential
.
location
,
datetime
.
now
(
UTC
)
+
timedelta
(
days
=
1
))
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
# Verify the state of the released sequential
# Verify the state of the released sequential
released_sequential_child_info
=
self
.
_get_child
(
xblock_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
[
0
])
released_unit_child_info
=
self
.
_get_child
(
released_sequential_child_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
[
0
,
0
])
self
.
assertEqual
(
released_unit_child_info
[
'publish_state'
],
PublishState
.
live
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
[
0
,
1
])
self
.
assertEqual
(
released_sequential_child_info
[
'publish_state'
],
PublishState
.
live
)
# Verify the state of the published sequential
# Verify the state of the published sequential
public_sequential_child_info
=
self
.
_get_child
(
xblock_info
,
1
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
ready
,
path
=
[
1
])
public_unit_child_info
=
self
.
_get_child
(
public_sequential_child_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
ready
,
path
=
[
1
,
0
])
self
.
assertEqual
(
public_sequential_child_info
[
'publish_state'
],
PublishState
.
ready
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
[
1
,
1
])
self
.
assertEqual
(
public_unit_child_info
[
'publish_state'
],
PublishState
.
ready
)
# Finally verify the state of the chapter
# Finally verify the state of the chapter
self
.
assertEqual
(
xblock_info
[
'publish_state'
],
Publish
State
.
ready
)
self
.
_verify_visibility_state
(
xblock_info
,
Visibility
State
.
ready
)
def
test_
unpublished_changes_publishing_info
(
self
):
def
test_
staff_only
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
unit
=
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
unit
=
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
)
self
.
_set_
display_name
(
unit
.
location
,
'Updated Unit'
)
self
.
_set_
staff_only
(
unit
.
location
,
True
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
self
.
assertEqual
(
xblock_info
[
'publish_state'
],
PublishState
.
has_unpublished_content
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
)
sequential_child_info
=
self
.
_get_child
(
xblock_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
self
.
FIRST_SUBSECTION_PATH
)
self
.
assertEqual
(
sequential_child_info
[
'publish_state'
],
PublishState
.
has_unpublished_content
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
self
.
FIRST_UNIT_PATH
)
unit_child_info
=
self
.
_get_child
(
sequential_child_info
,
0
)
self
.
assertEqual
(
unit_child_info
[
'publish_state'
],
PublishState
.
has_unpublished_content
)
def
test_
staff_only_publishing_info
(
self
):
def
test_
unscheduled_section_with_live_subsection
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
unit
=
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_set_staff_only
(
unit
.
location
,
True
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Staff Only Unit"
,
staff_only
=
True
)
self
.
_set_release_date
(
sequential
.
location
,
datetime
.
now
(
UTC
)
-
timedelta
(
days
=
1
))
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
needs_attention
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
self
.
FIRST_SUBSECTION_PATH
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
self
.
FIRST_UNIT_PATH
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
self
.
SECOND_UNIT_PATH
)
def
test_unreleased_section_with_live_subsection
(
self
):
chapter
=
self
.
_create_child
(
self
.
course
,
'chapter'
,
"Test Chapter"
)
sequential
=
self
.
_create_child
(
chapter
,
'sequential'
,
"Test Sequential"
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Published Unit"
,
publish_item
=
True
)
self
.
_create_child
(
sequential
,
'vertical'
,
"Staff Only Unit"
,
staff_only
=
True
)
self
.
_set_release_date
(
chapter
.
location
,
datetime
.
now
(
UTC
)
+
timedelta
(
days
=
1
))
self
.
_set_release_date
(
sequential
.
location
,
datetime
.
now
(
UTC
)
-
timedelta
(
days
=
1
))
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
xblock_info
=
self
.
_get_xblock_info
(
chapter
.
location
)
self
.
assertEqual
(
xblock_info
[
'publish_state'
],
PublishState
.
staff_only
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
needs_attention
)
sequential_child_info
=
self
.
_get_child
(
xblock_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
self
.
FIRST_SUBSECTION_PATH
)
self
.
assertEqual
(
sequential_child_info
[
'publish_state'
],
PublishState
.
staff_only
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
live
,
path
=
self
.
FIRST_UNIT_PATH
)
unit_child_info
=
self
.
_get_child
(
sequential_child_info
,
0
)
self
.
_verify_visibility_state
(
xblock_info
,
VisibilityState
.
staff_only
,
path
=
self
.
SECOND_UNIT_PATH
)
self
.
assertEqual
(
unit_child_info
[
'publish_state'
],
PublishState
.
staff_only
)
cms/static/js/models/xblock_info.js
View file @
ef581e11
...
@@ -45,14 +45,15 @@ define(["backbone", "underscore", "js/utils/module"], function(Backbone, _, Modu
...
@@ -45,14 +45,15 @@ define(["backbone", "underscore", "js/utils/module"], function(Backbone, _, Modu
*/
*/
"published_by"
:
null
,
"published_by"
:
null
,
/**
/**
* Represents the possible publish states for an xblock:
* True if the xblock has changes.
* is_live - the block and all of its children are live to students (except for staff only items)
* Note: this is not always provided as a performance optimization.
* is_ready - the block and all of its children are ready to go live in the future
* unscheduled - the block and all of its children are unscheduled
* has_unpublished_content - the block or its children have unpublished content that is not staff only
* is_staff_only - all of the block's content is to be shown to staff only
*/
*/
"publish_state"
:
null
,
"has_changes"
:
null
,
/**
* Represents the possible publish states for an xblock. See the documentation
* for XBlockVisibility to see a comprehensive enumeration of the states.
*/
"visibility_state"
:
null
,
/**
/**
* True iff the release date of the xblock is in the past.
* True iff the release date of the xblock is in the past.
*/
*/
...
...
cms/static/js/spec/views/pages/container_subviews_spec.js
View file @
ef581e11
define
([
"jquery"
,
"underscore"
,
"underscore.string"
,
"js/spec_helpers/create_sinon"
,
"js/spec_helpers/edit_helpers"
,
define
([
"jquery"
,
"underscore"
,
"underscore.string"
,
"js/spec_helpers/create_sinon"
,
"js/spec_helpers/edit_helpers"
,
"js/views/feedback_prompt"
,
"js/views/pages/container"
,
"js/views/pages/container_subviews"
,
"js/views/feedback_prompt"
,
"js/views/pages/container"
,
"js/views/pages/container_subviews"
,
"js/models/xblock_info"
],
"js/models/xblock_info"
,
"js/views/utils/xblock_utils"
],
function
(
$
,
_
,
str
,
create_sinon
,
edit_helpers
,
Prompt
,
ContainerPage
,
ContainerSubviews
,
XBlockInfo
)
{
function
(
$
,
_
,
str
,
create_sinon
,
edit_helpers
,
Prompt
,
ContainerPage
,
ContainerSubviews
,
XBlockInfo
,
XBlockUtils
)
{
var
VisibilityState
=
XBlockUtils
.
VisibilityState
;
describe
(
"Container Subviews"
,
function
()
{
describe
(
"Container Subviews"
,
function
()
{
var
model
,
containerPage
,
requests
,
createContainerPage
,
renderContainerPage
,
var
model
,
containerPage
,
requests
,
createContainerPage
,
renderContainerPage
,
...
@@ -23,7 +25,9 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -23,7 +25,9 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
id
:
'locator-container'
,
id
:
'locator-container'
,
display_name
:
'Test Container'
,
display_name
:
'Test Container'
,
category
:
'vertical'
,
category
:
'vertical'
,
publish_state
:
'unscheduled'
,
published
:
false
,
has_changes
:
false
,
visibility_state
:
'unscheduled'
,
edited_on
:
"Jul 02, 2014 at 14:20 UTC"
,
edited_by
:
"joe"
,
edited_on
:
"Jul 02, 2014 at 14:20 UTC"
,
edited_by
:
"joe"
,
published_on
:
"Jul 01, 2014 at 12:45 UTC"
,
published_by
:
"amako"
,
published_on
:
"Jul 01, 2014 at 12:45 UTC"
,
published_by
:
"amako"
,
currently_visible_to_students
:
false
currently_visible_to_students
:
false
...
@@ -85,22 +89,23 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -85,22 +89,23 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
'updates when publish state changes'
,
function
()
{
it
(
'updates when publish state changes'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
publish
_state
:
'ready'
});
fetch
({
publish
ed
:
true
});
expect
(
containerPage
.
$
(
viewPublishedCss
)).
not
.
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
viewPublishedCss
)).
not
.
toHaveClass
(
disabledCss
);
fetch
({
publish
_state
:
'unscheduled'
});
fetch
({
publish
ed
:
false
});
expect
(
containerPage
.
$
(
viewPublishedCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
viewPublishedCss
)).
toHaveClass
(
disabledCss
);
});
});
it
(
'updates when has_changes attribute changes'
,
function
()
{
it
(
'updates when has_changes attribute changes'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
publish_state
:
'has-unpublished-changes'
});
fetch
({
has_changes
:
true
});
expect
(
containerPage
.
$
(
previewCss
)).
not
.
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
previewCss
)).
not
.
toHaveClass
(
disabledCss
);
fetch
({
publish
_state
:
'ready'
});
fetch
({
publish
ed
:
true
,
has_changes
:
false
});
expect
(
containerPage
.
$
(
previewCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
previewCss
)).
toHaveClass
(
disabledCss
);
fetch
({
publish_state
:
'unscheduled'
});
// If published is false, preview is always enabled.
fetch
({
published
:
false
,
has_changes
:
false
});
expect
(
containerPage
.
$
(
previewCss
)).
not
.
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
previewCss
)).
not
.
toHaveClass
(
disabledCss
);
});
});
});
});
...
@@ -123,7 +128,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -123,7 +128,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// Helper function to do the discard operation, up until the server response.
// Helper function to do the discard operation, up until the server response.
containerPage
.
render
();
containerPage
.
render
();
respondWithHtml
(
mockContainerXBlockHtml
);
respondWithHtml
(
mockContainerXBlockHtml
);
fetch
({
publish
_state
:
'has_unpublished_content'
});
fetch
({
publish
ed
:
true
,
has_changes
:
true
,
visibility_state
:
VisibilityState
.
needsAttention
});
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
not
.
toHaveClass
(
'is-disabled'
);
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
not
.
toHaveClass
(
'is-disabled'
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
hasWarningsClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
hasWarningsClass
);
// Click discard changes
// Click discard changes
...
@@ -151,26 +156,29 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -151,26 +156,29 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
};
};
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
publishState
:
'unscheduled'
});
fetch
({
published
:
false
,
has_changes
:
false
});
verifyPrivateState
();
fetch
({
published
:
false
,
has_changes
:
true
});
verifyPrivateState
();
verifyPrivateState
();
});
});
it
(
'renders correctly with published content'
,
function
()
{
it
(
'renders correctly with published content'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
publish
_state
:
'ready'
});
fetch
({
publish
ed
:
true
,
has_changes
:
false
,
visibility_state
:
VisibilityState
.
ready
});
expect
(
containerPage
.
$
(
headerCss
).
text
()).
toContain
(
'Published'
);
expect
(
containerPage
.
$
(
headerCss
).
text
()).
toContain
(
'Published'
);
expect
(
containerPage
.
$
(
publishButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
publishButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
readyClass
);
fetch
({
publish
_state
:
'has_unpublished_content'
});
fetch
({
publish
ed
:
true
,
has_changes
:
true
,
visibility_state
:
VisibilityState
.
needsAttention
});
expect
(
containerPage
.
$
(
headerCss
).
text
()).
toContain
(
'Draft (Unpublished changes)'
);
expect
(
containerPage
.
$
(
headerCss
).
text
()).
toContain
(
'Draft (Unpublished changes)'
);
expect
(
containerPage
.
$
(
publishButtonCss
)).
not
.
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
publishButtonCss
)).
not
.
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
not
.
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
not
.
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
hasWarningsClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
hasWarningsClass
);
fetch
({
publish
_state
:
'live'
});
fetch
({
publish
ed
:
true
,
has_changes
:
false
,
visibility_state
:
VisibilityState
.
live
});
expect
(
containerPage
.
$
(
headerCss
).
text
()).
toContain
(
'Published'
);
expect
(
containerPage
.
$
(
headerCss
).
text
()).
toContain
(
'Published
and Live
'
);
expect
(
containerPage
.
$
(
publishButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
publishButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
discardChangesButtonCss
)).
toHaveClass
(
disabledCss
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
liveClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
liveClass
);
...
@@ -179,7 +187,9 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -179,7 +187,9 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
'can publish private content'
,
function
()
{
it
(
'can publish private content'
,
function
()
{
var
notificationSpy
=
edit_helpers
.
createNotificationSpy
();
var
notificationSpy
=
edit_helpers
.
createNotificationSpy
();
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
hasWarningsClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
liveClass
);
// Click publish
// Click publish
containerPage
.
$
(
publishButtonCss
).
click
();
containerPage
.
$
(
publishButtonCss
).
click
();
...
@@ -195,15 +205,17 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -195,15 +205,17 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
create_sinon
.
expectJsonRequest
(
requests
,
"GET"
,
"/xblock/locator-container"
);
create_sinon
.
expectJsonRequest
(
requests
,
"GET"
,
"/xblock/locator-container"
);
// Response to fetch
// Response to fetch
respondWithJson
(
createXBlockInfo
({
publish_state
:
'ready'
}));
respondWithJson
(
createXBlockInfo
({
published
:
true
,
has_changes
:
false
,
visibility_state
:
VisibilityState
.
ready
}));
// Verify updates displayed
// Verify updates displayed
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
toHaveClass
(
readyClass
);
// Verify that the "publish
_state" value has been updated
// Verify that the "publish
ed" value has been cleared out of the model.
expect
(
containerPage
.
model
.
get
(
"publish
_state"
)).
toBe
(
'ready'
);
expect
(
containerPage
.
model
.
get
(
"publish
"
)).
toBeNull
(
);
});
});
it
(
'
can does not fetc
h if publish fails'
,
function
()
{
it
(
'
does not refres
h if publish fails'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
...
@@ -218,8 +230,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -218,8 +230,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
// Verify still in draft state.
// Verify still in draft state.
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
// Verify that the "publish
_state" value has been updated
// Verify that the "publish
ed" value has been cleared out of the model.
expect
(
containerPage
.
model
.
get
(
"publish
_state"
)).
toBe
(
'unscheduled'
);
expect
(
containerPage
.
model
.
get
(
"publish
"
)).
toBeNull
(
);
});
});
it
(
'can discard changes'
,
function
()
{
it
(
'can discard changes'
,
function
()
{
...
@@ -260,7 +272,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -260,7 +272,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
});
});
it
(
'does not discard changes on cancel'
,
function
()
{
it
(
'does not discard changes on cancel'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{
publish_state
:
'has_unpublished_content'
});
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
published
:
true
,
has_changes
:
true
});
var
numRequests
=
requests
.
length
;
var
numRequests
=
requests
.
length
;
// Click discard changes
// Click discard changes
...
@@ -284,10 +297,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -284,10 +297,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
'renders the last saved date and user when there are changes'
,
function
()
{
it
(
'renders the last saved date and user when there are changes'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
fetch
({
has_changes
:
true
,
edited_on
:
"Jul 02, 2014 at 14:20 UTC"
,
edited_by
:
"joe"
});
publish_state
:
'has_unpublished_content'
,
edited_on
:
"Jul 02, 2014 at 14:20 UTC"
,
edited_by
:
"joe"
});
expect
(
containerPage
.
$
(
lastDraftCss
).
text
()).
expect
(
containerPage
.
$
(
lastDraftCss
).
text
()).
toContain
(
"Draft saved on Jul 02, 2014 at 14:20 UTC by joe"
);
toContain
(
"Draft saved on Jul 02, 2014 at 14:20 UTC by joe"
);
});
});
...
@@ -296,7 +306,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -296,7 +306,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
'renders correctly when unreleased'
,
function
()
{
it
(
'renders correctly when unreleased'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
fetch
({
publish_state
:
'ready'
,
released_to_students
:
false
,
visibility_state
:
VisibilityState
.
ready
,
released_to_students
:
false
,
release_date
:
"Jul 02, 2014 at 14:20 UTC"
,
release_date_from
:
'Section "Week 1"'
release_date
:
"Jul 02, 2014 at 14:20 UTC"
,
release_date_from
:
'Section "Week 1"'
});
});
expect
(
containerPage
.
$
(
releaseDateTitleCss
).
text
()).
toContain
(
"Scheduled:"
);
expect
(
containerPage
.
$
(
releaseDateTitleCss
).
text
()).
toContain
(
"Scheduled:"
);
...
@@ -307,7 +317,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -307,7 +317,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
'renders correctly when released'
,
function
()
{
it
(
'renders correctly when released'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
fetch
({
publish_state
:
'live'
,
released_to_students
:
true
,
visibility_state
:
VisibilityState
.
live
,
released_to_students
:
true
,
release_date
:
"Jul 02, 2014 at 14:20 UTC"
,
release_date_from
:
'Section "Week 1"'
release_date
:
"Jul 02, 2014 at 14:20 UTC"
,
release_date_from
:
'Section "Week 1"'
});
});
expect
(
containerPage
.
$
(
releaseDateTitleCss
).
text
()).
toContain
(
"Released:"
);
expect
(
containerPage
.
$
(
releaseDateTitleCss
).
text
()).
toContain
(
"Released:"
);
...
@@ -318,7 +328,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -318,7 +328,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
'renders correctly when the release date is not set'
,
function
()
{
it
(
'renders correctly when the release date is not set'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
fetch
({
publish_state
:
'unscheduled'
,
"released_to_students"
:
false
,
visibility_state
:
VisibilityState
.
unscheduled
,
"released_to_students"
:
false
,
release_date
:
null
,
release_date_from
:
null
release_date
:
null
,
release_date_from
:
null
});
});
expect
(
containerPage
.
$
(
releaseDateTitleCss
).
text
()).
toContain
(
"Release:"
);
expect
(
containerPage
.
$
(
releaseDateTitleCss
).
text
()).
toContain
(
"Release:"
);
...
@@ -328,7 +338,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -328,7 +338,7 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
'renders correctly when the unit is not published'
,
function
()
{
it
(
'renders correctly when the unit is not published'
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
fetch
({
fetch
({
publish_state
:
'has_unpublished_content'
,
released_to_students
:
true
,
visibility_state
:
VisibilityState
.
needsAttention
,
released_to_students
:
true
,
release_date
:
"Jul 02, 2014 at 14:20 UTC"
,
release_date_from
:
'Section "Week 1"'
release_date
:
"Jul 02, 2014 at 14:20 UTC"
,
release_date_from
:
'Section "Week 1"'
});
});
containerPage
.
xblockPublisher
.
render
();
containerPage
.
xblockPublisher
.
render
();
...
@@ -362,7 +372,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -362,7 +372,8 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
});
});
create_sinon
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/locator-container'
);
create_sinon
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/locator-container'
);
create_sinon
.
respondWithJson
(
requests
,
createXBlockInfo
({
create_sinon
.
respondWithJson
(
requests
,
createXBlockInfo
({
publish_state
:
isStaffOnly
?
'staff_only'
:
'unscheduled'
published
:
containerPage
.
model
.
get
(
'published'
),
visibility_state
:
isStaffOnly
?
VisibilityState
.
staffOnly
:
VisibilityState
.
live
}));
}));
};
};
...
@@ -385,14 +396,15 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -385,14 +396,15 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
"can be set to staff only"
,
function
()
{
it
(
"can be set to staff only"
,
function
()
{
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
renderContainerPage
(
this
,
mockContainerXBlockHtml
);
containerPage
.
$
(
'.action-staff-lock'
).
click
();
requestStaffOnly
(
true
);
requestStaffOnly
(
true
);
verifyStaffOnly
(
true
);
verifyStaffOnly
(
true
);
});
});
it
(
"can remove staff only setting"
,
function
()
{
it
(
"can remove staff only setting"
,
function
()
{
promptSpy
=
edit_helpers
.
createPromptSpy
();
promptSpy
=
edit_helpers
.
createPromptSpy
();
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{
publish_state
:
'staff_only'
});
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{
visibility_state
:
VisibilityState
.
staffOnly
});
requestStaffOnly
(
false
);
requestStaffOnly
(
false
);
verifyStaffOnly
(
false
);
verifyStaffOnly
(
false
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
expect
(
containerPage
.
$
(
bitPublishingCss
)).
not
.
toHaveClass
(
readyClass
);
...
@@ -401,7 +413,9 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
...
@@ -401,7 +413,9 @@ define(["jquery", "underscore", "underscore.string", "js/spec_helpers/create_sin
it
(
"does not refresh if removing staff only is canceled"
,
function
()
{
it
(
"does not refresh if removing staff only is canceled"
,
function
()
{
var
requestCount
;
var
requestCount
;
promptSpy
=
edit_helpers
.
createPromptSpy
();
promptSpy
=
edit_helpers
.
createPromptSpy
();
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{
publish_state
:
'staff_only'
});
renderContainerPage
(
this
,
mockContainerXBlockHtml
,
{
visibility_state
:
VisibilityState
.
staffOnly
});
requestCount
=
requests
.
length
;
requestCount
=
requests
.
length
;
containerPage
.
$
(
'.action-staff-lock'
).
click
();
containerPage
.
$
(
'.action-staff-lock'
).
click
();
edit_helpers
.
confirmPrompt
(
promptSpy
,
true
);
// Click 'No' to cancel
edit_helpers
.
confirmPrompt
(
promptSpy
,
true
);
// Click 'No' to cancel
...
...
cms/static/js/spec/views/pages/course_outline_spec.js
View file @
ef581e11
...
@@ -118,7 +118,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -118,7 +118,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
category
:
'vertical'
,
category
:
'vertical'
,
studio_url
:
'/container/mock-unit'
,
studio_url
:
'/container/mock-unit'
,
is_container
:
true
,
is_container
:
true
,
publish
_state
:
'unscheduled'
,
visibility
_state
:
'unscheduled'
,
edited_on
:
'Jul 02, 2014 at 20:56 UTC'
,
edited_on
:
'Jul 02, 2014 at 20:56 UTC'
,
edited_by
:
'MockUser'
edited_by
:
'MockUser'
}])
}])
...
@@ -432,9 +432,5 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -432,9 +432,5 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
expect
(
unitAnchor
.
attr
(
'href'
)).
toBe
(
'/container/mock-unit'
);
expect
(
unitAnchor
.
attr
(
'href'
)).
toBe
(
'/container/mock-unit'
);
});
});
});
});
describe
(
"Publishing State"
,
function
()
{
// TODO: implement this!!!!
});
});
});
});
});
cms/static/js/spec/views/unit_outline_spec.js
View file @
ef581e11
...
@@ -25,14 +25,14 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -25,14 +25,14 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
category
:
'vertical'
,
category
:
'vertical'
,
display_name
:
displayName
,
display_name
:
displayName
,
studio_url
:
'/container/mock-unit'
,
studio_url
:
'/container/mock-unit'
,
publish
_state
:
'unscheduled'
,
visibility
_state
:
'unscheduled'
,
ancestor_info
:
{
ancestor_info
:
{
ancestors
:
[{
ancestors
:
[{
id
:
'mock-subsection'
,
id
:
'mock-subsection'
,
category
:
'sequential'
,
category
:
'sequential'
,
display_name
:
'Mock Subsection'
,
display_name
:
'Mock Subsection'
,
studio_url
:
'/course/mock-course?show=mock-subsection'
,
studio_url
:
'/course/mock-course?show=mock-subsection'
,
publish
_state
:
'unscheduled'
,
visibility
_state
:
'unscheduled'
,
child_info
:
{
child_info
:
{
category
:
'vertical'
,
category
:
'vertical'
,
display_name
:
'Unit'
,
display_name
:
'Unit'
,
...
@@ -41,13 +41,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -41,13 +41,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
category
:
'vertical'
,
category
:
'vertical'
,
display_name
:
displayName
,
display_name
:
displayName
,
studio_url
:
'/container/mock-unit'
,
studio_url
:
'/container/mock-unit'
,
publish
_state
:
'unscheduled'
visibility
_state
:
'unscheduled'
},
{
},
{
id
:
'mock-unit-2'
,
id
:
'mock-unit-2'
,
category
:
'vertical'
,
category
:
'vertical'
,
display_name
:
'Mock Unit 2'
,
display_name
:
'Mock Unit 2'
,
studio_url
:
'/container/mock-unit-2'
,
studio_url
:
'/container/mock-unit-2'
,
publish
_state
:
'unscheduled'
visibility
_state
:
'unscheduled'
}]
}]
}
}
},
{
},
{
...
@@ -55,13 +55,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -55,13 +55,13 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
category
:
'chapter'
,
category
:
'chapter'
,
display_name
:
'Section'
,
display_name
:
'Section'
,
studio_url
:
'/course/slashes:mock-course?show=mock-section'
,
studio_url
:
'/course/slashes:mock-course?show=mock-section'
,
publish
_state
:
'unscheduled'
visibility
_state
:
'unscheduled'
},
{
},
{
id
:
'mock-course'
,
id
:
'mock-course'
,
category
:
'course'
,
category
:
'course'
,
display_name
:
'Mock Course'
,
display_name
:
'Mock Course'
,
studio_url
:
'/course/mock-course'
,
studio_url
:
'/course/mock-course'
,
publish
_state
:
'unscheduled'
visibility
_state
:
'unscheduled'
}]
}]
},
},
metadata
:
{
metadata
:
{
...
...
cms/static/js/views/baseview.js
View file @
ef581e11
...
@@ -17,6 +17,9 @@ define(["jquery", "underscore", "backbone", "gettext", "js/utils/handle_iframe_b
...
@@ -17,6 +17,9 @@ define(["jquery", "underscore", "backbone", "gettext", "js/utils/handle_iframe_b
},
},
options
:
{
options
:
{
// UX is moving towards using 'is-collapsed' in preference over 'collapsed',
// but use the old scheme as the default so that existing code doesn't need
// to be rewritten.
collapsedClass
:
'collapsed'
collapsedClass
:
'collapsed'
},
},
...
...
cms/static/js/views/pages/container_subviews.js
View file @
ef581e11
/**
/**
* Subviews (usually small side panels) for XBlockContainerPage.
* Subviews (usually small side panels) for XBlockContainerPage.
*/
*/
define
([
"jquery"
,
"underscore"
,
"gettext"
,
"js/views/baseview"
,
"js/views/utils/view_utils"
],
define
([
"jquery"
,
"underscore"
,
"gettext"
,
"js/views/baseview"
,
"js/views/utils/view_utils"
,
function
(
$
,
_
,
gettext
,
BaseView
,
ViewUtils
)
{
"js/views/utils/xblock_utils"
],
function
(
$
,
_
,
gettext
,
BaseView
,
ViewUtils
,
XBlockViewUtils
)
{
var
disabledCss
=
"is-disabled"
;
var
VisibilityState
=
XBlockViewUtils
.
VisibilityState
,
disabledCss
=
"is-disabled"
;
/**
/**
* A view that refreshes the view when certain values in the XBlockInfo have changed
* A view that refreshes the view when certain values in the XBlockInfo have changed
...
@@ -53,20 +54,19 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
...
@@ -53,20 +54,19 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
*/
*/
var
PreviewActionController
=
ContainerStateListenerView
.
extend
({
var
PreviewActionController
=
ContainerStateListenerView
.
extend
({
shouldRefresh
:
function
(
model
)
{
shouldRefresh
:
function
(
model
)
{
return
ViewUtils
.
hasChangedAttributes
(
model
,
[
'
edited_on'
,
'published_on'
,
'publish_state
'
]);
return
ViewUtils
.
hasChangedAttributes
(
model
,
[
'
has_changes'
,
'published
'
]);
},
},
render
:
function
()
{
render
:
function
()
{
var
previewAction
=
this
.
$el
.
find
(
'.button-preview'
),
var
previewAction
=
this
.
$el
.
find
(
'.button-preview'
),
viewLiveAction
=
this
.
$el
.
find
(
'.button-view'
),
viewLiveAction
=
this
.
$el
.
find
(
'.button-view'
);
publishState
=
this
.
model
.
get
(
'publish_state'
);
if
(
this
.
model
.
get
(
'published'
))
{
if
(
publishState
!==
'unscheduled'
)
{
viewLiveAction
.
removeClass
(
disabledCss
);
viewLiveAction
.
removeClass
(
disabledCss
);
}
}
else
{
else
{
viewLiveAction
.
addClass
(
disabledCss
);
viewLiveAction
.
addClass
(
disabledCss
);
}
}
if
(
publishState
!==
'live'
&&
publishState
!==
'ready'
)
{
if
(
this
.
model
.
get
(
'has_changes'
)
||
!
this
.
model
.
get
(
'published'
)
)
{
previewAction
.
removeClass
(
disabledCss
);
previewAction
.
removeClass
(
disabledCss
);
}
}
else
{
else
{
...
@@ -99,14 +99,18 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
...
@@ -99,14 +99,18 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
},
},
onSync
:
function
(
model
)
{
onSync
:
function
(
model
)
{
if
(
ViewUtils
.
hasChangedAttributes
(
model
,
[
'edited_on'
,
'published_on'
,
'publish_state'
]))
{
if
(
ViewUtils
.
hasChangedAttributes
(
model
,
[
'has_changes'
,
'published'
,
'edited_on'
,
'edited_by'
,
'visibility_state'
]))
{
this
.
render
();
this
.
render
();
}
}
},
},
render
:
function
()
{
render
:
function
()
{
this
.
$el
.
html
(
this
.
template
({
this
.
$el
.
html
(
this
.
template
({
publishState
:
this
.
model
.
get
(
'publish_state'
),
visibilityState
:
this
.
model
.
get
(
'visibility_state'
),
visibilityClass
:
XBlockViewUtils
.
getXBlockVisibilityClass
(
this
.
model
.
get
(
'visibility_state'
)),
hasChanges
:
this
.
model
.
get
(
'has_changes'
),
editedOn
:
this
.
model
.
get
(
'edited_on'
),
editedOn
:
this
.
model
.
get
(
'edited_on'
),
editedBy
:
this
.
model
.
get
(
'edited_by'
),
editedBy
:
this
.
model
.
get
(
'edited_by'
),
published
:
this
.
model
.
get
(
'published'
),
published
:
this
.
model
.
get
(
'published'
),
...
@@ -162,7 +166,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
...
@@ -162,7 +166,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
if
(
e
&&
e
.
preventDefault
)
{
if
(
e
&&
e
.
preventDefault
)
{
e
.
preventDefault
();
e
.
preventDefault
();
}
}
enableStaffLock
=
xblockInfo
.
get
(
'
publish_state'
)
!==
'staff_only'
;
enableStaffLock
=
xblockInfo
.
get
(
'
visibility_state'
)
!==
VisibilityState
.
staffOnly
;
revertCheckBox
=
function
()
{
revertCheckBox
=
function
()
{
self
.
checkStaffLock
(
!
enableStaffLock
);
self
.
checkStaffLock
(
!
enableStaffLock
);
...
@@ -221,7 +225,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
...
@@ -221,7 +225,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
},
},
onSync
:
function
(
model
)
{
onSync
:
function
(
model
)
{
if
(
ViewUtils
.
hasChangedAttributes
(
model
,
[
'published
_on
'
]))
{
if
(
ViewUtils
.
hasChangedAttributes
(
model
,
[
'published
'
,
'published_on'
,
'published_by
'
]))
{
this
.
render
();
this
.
render
();
}
}
},
},
...
...
cms/static/js/views/unit_outline.js
View file @
ef581e11
...
@@ -10,7 +10,6 @@ define(['js/views/xblock_outline'],
...
@@ -10,7 +10,6 @@ define(['js/views/xblock_outline'],
// takes XBlockInfo as a model
// takes XBlockInfo as a model
templateName
:
'unit-outline'
,
templateName
:
'unit-outline'
,
className
:
'group-configurations-list'
,
render
:
function
()
{
render
:
function
()
{
XBlockOutlineView
.
prototype
.
render
.
call
(
this
);
XBlockOutlineView
.
prototype
.
render
.
call
(
this
);
...
...
cms/static/js/views/utils/xblock_utils.js
View file @
ef581e11
...
@@ -3,7 +3,36 @@
...
@@ -3,7 +3,36 @@
*/
*/
define
([
"jquery"
,
"underscore"
,
"gettext"
,
"js/views/utils/view_utils"
,
"js/utils/module"
],
define
([
"jquery"
,
"underscore"
,
"gettext"
,
"js/views/utils/view_utils"
,
"js/utils/module"
],
function
(
$
,
_
,
gettext
,
ViewUtils
,
ModuleUtils
)
{
function
(
$
,
_
,
gettext
,
ViewUtils
,
ModuleUtils
)
{
var
addXBlock
,
deleteXBlock
,
createUpdateRequestData
,
updateXBlockField
;
var
addXBlock
,
deleteXBlock
,
createUpdateRequestData
,
updateXBlockField
,
VisibilityState
,
getXBlockVisibilityClass
;
/**
* Represents the possible visibility states for an xblock:
*
* live - the block and all of its descendants are live to students (excluding staff only)
* Note: Live means both published and released.
*
* ready - the block is ready to go live and all of its descendants are live or ready (excluding staff only)
* Note: content is ready when it is published and scheduled with a release date in the future.
*
* unscheduled - the block and all of its descendants have no release date (excluding staff only)
* Note: it is valid for items to be published with no release date in which case they are unscheduled.
*
* needsAttention - the block or its descendants need attention
* i.e. there is some content that is not fully live, ready, unscheduled or staff only.
* For example: one subsection has draft content, or there's both unreleased and released content
* in one section.
*
* staffOnly - all of the block's content is to be shown to staff only
* Note: staff only items do not affect their parent's state.
*/
VisibilityState
=
{
live
:
'live'
,
ready
:
'ready'
,
unscheduled
:
'unscheduled'
,
needsAttention
:
'needs_attention'
,
staffOnly
:
'staff_only'
};
/**
/**
* Adds an xblock based upon the data attributes of the specified add button. A promise
* Adds an xblock based upon the data attributes of the specified add button. A promise
...
@@ -83,9 +112,30 @@ define(["jquery", "underscore", "gettext", "js/views/utils/view_utils", "js/util
...
@@ -83,9 +112,30 @@ define(["jquery", "underscore", "gettext", "js/views/utils/view_utils", "js/util
});
});
};
};
/**
* Returns the CSS class to represent the specified xblock visibility state.
*/
getXBlockVisibilityClass
=
function
(
visibilityState
)
{
if
(
visibilityState
===
VisibilityState
.
staffOnly
)
{
return
'is-staff-only'
;
}
if
(
visibilityState
===
VisibilityState
.
live
)
{
return
'is-live'
;
}
if
(
visibilityState
===
VisibilityState
.
ready
)
{
return
'is-ready'
;
}
if
(
visibilityState
===
VisibilityState
.
needsAttention
)
{
return
'has-warnings'
;
}
return
''
;
};
return
{
return
{
'VisibilityState'
:
VisibilityState
,
'addXBlock'
:
addXBlock
,
'addXBlock'
:
addXBlock
,
'deleteXBlock'
:
deleteXBlock
,
'deleteXBlock'
:
deleteXBlock
,
'updateXBlockField'
:
updateXBlockField
'updateXBlockField'
:
updateXBlockField
,
'getXBlockVisibilityClass'
:
getXBlockVisibilityClass
};
};
});
});
cms/static/js/views/xblock_outline.js
View file @
ef581e11
...
@@ -68,6 +68,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
...
@@ -68,6 +68,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
}
}
html
=
this
.
template
({
html
=
this
.
template
({
xblockInfo
:
xblockInfo
,
xblockInfo
:
xblockInfo
,
visibilityClass
:
XBlockViewUtils
.
getXBlockVisibilityClass
(
xblockInfo
.
get
(
'visibility_state'
)),
parentInfo
:
this
.
parentInfo
,
parentInfo
:
this
.
parentInfo
,
xblockType
:
xblockType
,
xblockType
:
xblockType
,
parentType
:
parentType
,
parentType
:
parentType
,
...
@@ -200,7 +201,11 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
...
@@ -200,7 +201,11 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
}
else
{
}
else
{
locatorElement
=
this
.
$
(
'.outline-item[data-locator="'
+
locatorToShow
+
'"]'
);
locatorElement
=
this
.
$
(
'.outline-item[data-locator="'
+
locatorToShow
+
'"]'
);
}
}
ViewUtils
.
setScrollOffset
(
locatorElement
,
scrollOffset
);
if
(
locatorElement
.
length
>
0
)
{
ViewUtils
.
setScrollOffset
(
locatorElement
,
scrollOffset
);
}
else
{
console
.
error
(
"Failed to show item with locator "
+
locatorToShow
+
""
);
}
if
(
editDisplayName
)
{
if
(
editDisplayName
)
{
locatorElement
.
find
(
'> div[class$="header"] .xblock-field-value-edit'
).
click
();
locatorElement
.
find
(
'> div[class$="header"] .xblock-field-value-edit'
).
click
();
}
}
...
...
cms/templates/course_outline.html
View file @
ef581e11
...
@@ -72,7 +72,7 @@ from contentstore.utils import reverse_usage_url
...
@@ -72,7 +72,7 @@ from contentstore.utils import reverse_usage_url
<
%
<
%
course_locator =
context_course.location
course_locator =
context_course.location
%
>
%
>
<article
class=
"outline"
data-locator=
"${course_locator}"
data-course-key=
"${course_locator.course_key}"
>
<article
class=
"outline
outline-course
"
data-locator=
"${course_locator}"
data-course-key=
"${course_locator.course_key}"
>
</article>
</article>
</div>
</div>
<div
class=
"ui-loading"
>
<div
class=
"ui-loading"
>
...
...
cms/templates/js/course-outline.underscore
View file @
ef581e11
<%
<%
var category = xblockInfo.get('category');
var category = xblockInfo.get('category');
var releasedToStudents = xblockInfo.get('released_to_students');
var releasedToStudents = xblockInfo.get('released_to_students');
var publishState = xblockInfo.get('publish_state');
var visibilityState = xblockInfo.get('visibility_state');
var publishClass = '';
if (publishState === 'staff_only') {
publishClass = 'is-staff-only';
} else if (publishState === 'live') {
publishClass = 'is-live';
} else if (publishState === 'ready') {
publishClass = 'is-ready';
} else if (publishState === 'has_unpublished_content') {
publishClass = 'has-warnings';
}
var listType = 'list-unknown';
var listType = 'list-unknown';
if (xblockType === 'course') {
if (xblockType === 'course') {
...
@@ -25,10 +14,10 @@ if (xblockType === 'course') {
...
@@ -25,10 +14,10 @@ if (xblockType === 'course') {
var statusMessage = null;
var statusMessage = null;
var statusType = null;
var statusType = null;
if (
publish
State === 'staff_only') {
if (
visibility
State === 'staff_only') {
statusType = 'staff-only';
statusType = 'staff-only';
statusMessage = 'Contains staff only content';
statusMessage = 'Contains staff only content';
} else if (
publishState === 'has_unpublished_content
') {
} else if (
visibilityState === 'needs_attention
') {
if (category === 'vertical') {
if (category === 'vertical') {
statusType = 'warning';
statusType = 'warning';
if (releasedToStudents) {
if (releasedToStudents) {
...
@@ -49,7 +38,7 @@ if (statusType === 'warning') {
...
@@ -49,7 +38,7 @@ if (statusType === 'warning') {
}
}
%>
%>
<% if (parentInfo) { %>
<% if (parentInfo) { %>
<li class="outline-item outline-<%= xblockType %> <%=
publish
Class %> is-draggable <%= includesChildren ? 'is-collapsible' : '' %> <%= isCollapsed ? 'is-collapsed' : '' %>"
<li class="outline-item outline-<%= xblockType %> <%=
visibility
Class %> is-draggable <%= includesChildren ? 'is-collapsible' : '' %> <%= isCollapsed ? 'is-collapsed' : '' %>"
data-parent="<%= parentInfo.get('id') %>" data-locator="<%= xblockInfo.get('id') %>">
data-parent="<%= parentInfo.get('id') %>" data-locator="<%= xblockInfo.get('id') %>">
<div class="<%= xblockType %>-header">
<div class="<%= xblockType %>-header">
...
...
cms/templates/js/publish-xblock.underscore
View file @
ef581e11
<%
<%
var publishClass = '';
if (publishState === 'staff_only') {
publishClass = 'is-staff-only';
} else if (publishState === 'live') {
publishClass = 'is-live';
} else if (publishState === 'ready') {
publishClass = 'is-ready';
} else if (publishState === 'has_unpublished_content') {
publishClass = 'has-warnings is-draft';
}
var title = gettext("Draft (Never published)");
var title = gettext("Draft (Never published)");
if (
publish
State === 'staff_only') {
if (
visibility
State === 'staff_only') {
title = gettext("Unpublished (Staff only)");
title = gettext("Unpublished (Staff only)");
} else if (
publish
State === 'live') {
} else if (
visibility
State === 'live') {
title = gettext("Published and Live");
title = gettext("Published and Live");
} else if (
publish
State === 'ready') {
} else if (
visibility
State === 'ready') {
title = gettext("Published");
title = gettext("Published");
} else if (
publishState === 'has_unpublished_content
') {
} else if (
visibilityState === 'needs_attention
') {
title = gettext("Draft (Unpublished changes)");
title = gettext("Draft (Unpublished changes)");
}
}
var releaseLabel = gettext("Release:");
var releaseLabel = gettext("Release:");
if (
publish
State === 'live') {
if (
visibility
State === 'live') {
releaseLabel = gettext("Released:");
releaseLabel = gettext("Released:");
} else if (
publish
State === 'ready') {
} else if (
visibility
State === 'ready') {
releaseLabel = gettext("Scheduled:");
releaseLabel = gettext("Scheduled:");
}
}
var canPublish = publishState !== 'ready' && publishState !== 'live';
var visibleToStaffOnly = visibilityState === 'staff_only';
var canDiscardChanges = publishState === 'has_unpublished_content';
var visibleToStaffOnly = publishState === 'staff_only';
%>
%>
<div class="bit-publishing <%=
publish
Class %>">
<div class="bit-publishing <%=
visibility
Class %>">
<h3 class="bar-mod-title pub-status"><span class="sr"><%= gettext("Publishing Status") %></span>
<h3 class="bar-mod-title pub-status"><span class="sr"><%= gettext("Publishing Status") %></span>
<%= title %>
<%= title %>
</h3>
</h3>
<div class="wrapper-last-draft bar-mod-content">
<div class="wrapper-last-draft bar-mod-content">
<p class="copy meta">
<p class="copy meta">
<% if (
publishState === 'has_unpublished_content'
&& editedOn && editedBy) {
<% if (
hasChanges
&& editedOn && editedBy) {
var message = gettext("Draft saved on %(last_saved_date)s by %(edit_username)s") %>
var message = gettext("Draft saved on %(last_saved_date)s by %(edit_username)s") %>
<%= interpolate(message, {
<%= interpolate(message, {
last_saved_date: '<span class="date">' + editedOn + '</span>',
last_saved_date: '<span class="date">' + editedOn + '</span>',
...
@@ -91,12 +78,12 @@ var visibleToStaffOnly = publishState === 'staff_only';
...
@@ -91,12 +78,12 @@ var visibleToStaffOnly = publishState === 'staff_only';
<div class="wrapper-pub-actions bar-mod-actions">
<div class="wrapper-pub-actions bar-mod-actions">
<ul class="action-list">
<ul class="action-list">
<li class="action-item">
<li class="action-item">
<a class="action-publish action-primary <% if (
!canPublish
) { %>is-disabled<% } %>"
<a class="action-publish action-primary <% if (
published && !hasChanges
) { %>is-disabled<% } %>"
href=""><%= gettext("Publish") %>
href=""><%= gettext("Publish") %>
</a>
</a>
</li>
</li>
<li class="action-item">
<li class="action-item">
<a class="action-discard action-secondary <% if (!
canDiscard
Changes) { %>is-disabled<% } %>"
<a class="action-discard action-secondary <% if (!
published || !has
Changes) { %>is-disabled<% } %>"
href=""><%= gettext("Discard Changes") %>
href=""><%= gettext("Discard Changes") %>
</a>
</a>
</li>
</li>
...
...
cms/templates/js/unit-outline.underscore
View file @
ef581e11
<%
<%
var publishState = xblockInfo.get('publish_state');
var publishClass = '';
if (publishState === 'staff_only') {
publishClass = 'is-staff-only';
} else if (publishState === 'live') {
publishClass = 'is-live';
} else if (publishState === 'ready') {
publishClass = 'is-ready';
} else if (publishState === 'has_unpublished_content') {
publishClass = 'has_warnings';
}
var listType = 'list-for-' + xblockType;
var listType = 'list-for-' + xblockType;
if (xblockType === 'course') {
if (xblockType === 'course') {
listType = 'list-sections';
listType = 'list-sections';
...
@@ -21,7 +9,7 @@ if (xblockType === 'course') {
...
@@ -21,7 +9,7 @@ if (xblockType === 'course') {
}
}
%>
%>
<% if (parentInfo) { %>
<% if (parentInfo) { %>
<li class="outline-item outline-<%= xblockType %> <%=
publish
Class %>"
<li class="outline-item outline-<%= xblockType %> <%=
visibility
Class %>"
data-parent="<%= parentInfo.get('id') %>" data-locator="<%= xblockInfo.get('id') %>">
data-parent="<%= parentInfo.get('id') %>" data-locator="<%= xblockInfo.get('id') %>">
<div class="<%= xblockType %>-header">
<div class="<%= xblockType %>-header">
<h3 class="<%= xblockType %>-header-details">
<h3 class="<%= xblockType %>-header-details">
...
...
cms/templates/widgets/units.html
View file @
ef581e11
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%!
from
contentstore
.
utils
import
compute_publish_state
%
>
<
%!
from
contentstore
.
views
.
helpers
import
xblock_studio_url
%
>
<
%!
from
contentstore
.
views
.
helpers
import
xblock_studio_url
%
>
<!--
<!--
...
@@ -18,7 +17,7 @@ This def will enumerate through a passed in subsection and list all of the units
...
@@ -18,7 +17,7 @@ This def will enumerate through a passed in subsection and list all of the units
<
%
include
file=
"_ui-dnd-indicator-before.html"
/>
<
%
include
file=
"_ui-dnd-indicator-before.html"
/>
<
%
<
%
unit_state =
compute_publish_state(unit)
unit_state =
'draft'
#
Note:
this
is
a
hack
since
this
HTML
file
is
being
removed
in
bulk-publishing
if
unit
.
location =
=
selected:
if
unit
.
location =
=
selected:
selected_class =
'editing'
selected_class =
'editing'
else:
else:
...
...
common/lib/xmodule/xmodule/modulestore/__init__.py
View file @
ef581e11
...
@@ -90,10 +90,10 @@ class ModuleStoreEnum(object):
...
@@ -90,10 +90,10 @@ class ModuleStoreEnum(object):
test
=
-
3
test
=
-
3
class
Legacy
PublishState
(
object
):
class
PublishState
(
object
):
"""
"""
The legacy publish state for a given xblock-- either 'draft', 'private', or 'public'. These states
The legacy publish state for a given xblock-- either 'draft', 'private', or 'public'. These states
are no longer used in Studio
directly, but are still referenced in a few places
.
are no longer used in Studio
, but they are still referenced in a few places in LMS
.
"""
"""
draft
=
'draft'
draft
=
'draft'
private
=
'private'
private
=
'private'
...
@@ -301,10 +301,10 @@ class ModuleStoreRead(object):
...
@@ -301,10 +301,10 @@ class ModuleStoreRead(object):
Returns whether this xblock is draft, public, or private.
Returns whether this xblock is draft, public, or private.
Returns:
Returns:
Legacy
PublishState.draft - content is in the process of being edited, but still has a previous
PublishState.draft - content is in the process of being edited, but still has a previous
version deployed to LMS
version deployed to LMS
Legacy
PublishState.public - content is locked and deployed to LMS
PublishState.public - content is locked and deployed to LMS
Legacy
PublishState.private - content is editable and not deployed to LMS
PublishState.private - content is editable and not deployed to LMS
"""
"""
pass
pass
...
@@ -522,7 +522,7 @@ class ModuleStoreReadBase(ModuleStoreRead):
...
@@ -522,7 +522,7 @@ class ModuleStoreReadBase(ModuleStoreRead):
"""
"""
Returns PublishState.public since this is a read-only store.
Returns PublishState.public since this is a read-only store.
"""
"""
return
Legacy
PublishState
.
public
return
PublishState
.
public
def
heartbeat
(
self
):
def
heartbeat
(
self
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/mixed.py
View file @
ef581e11
...
@@ -439,10 +439,10 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
...
@@ -439,10 +439,10 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
Returns whether this xblock is draft, public, or private.
Returns whether this xblock is draft, public, or private.
Returns:
Returns:
Legacy
PublishState.draft - content is in the process of being edited, but still has a previous
PublishState.draft - content is in the process of being edited, but still has a previous
version deployed to LMS
version deployed to LMS
Legacy
PublishState.public - content is locked and deployed to LMS
PublishState.public - content is locked and deployed to LMS
Legacy
PublishState.private - content is editable and not deployed to LMS
PublishState.private - content is editable and not deployed to LMS
"""
"""
course_id
=
xblock
.
scope_ids
.
usage_id
.
course_key
course_id
=
xblock
.
scope_ids
.
usage_id
.
course_key
store
=
self
.
_get_modulestore_for_courseid
(
course_id
)
store
=
self
.
_get_modulestore_for_courseid
(
course_id
)
...
...
common/lib/xmodule/xmodule/modulestore/mongo/draft.py
View file @
ef581e11
...
@@ -11,7 +11,7 @@ import logging
...
@@ -11,7 +11,7 @@ import logging
from
opaque_keys.edx.locations
import
Location
from
opaque_keys.edx.locations
import
Location
from
xmodule.exceptions
import
InvalidVersionError
from
xmodule.exceptions
import
InvalidVersionError
from
xmodule.modulestore
import
Legacy
PublishState
,
ModuleStoreEnum
from
xmodule.modulestore
import
PublishState
,
ModuleStoreEnum
from
xmodule.modulestore.exceptions
import
(
from
xmodule.modulestore.exceptions
import
(
ItemNotFoundError
,
DuplicateItemError
,
InvalidBranchSetting
,
DuplicateCourseError
ItemNotFoundError
,
DuplicateItemError
,
InvalidBranchSetting
,
DuplicateCourseError
)
)
...
@@ -613,7 +613,7 @@ class DraftModuleStore(MongoModuleStore):
...
@@ -613,7 +613,7 @@ class DraftModuleStore(MongoModuleStore):
return
False
return
False
# don't check children if this block has changes (is not public)
# don't check children if this block has changes (is not public)
if
self
.
compute_publish_state
(
item
)
!=
Legacy
PublishState
.
public
:
if
self
.
compute_publish_state
(
item
)
!=
PublishState
.
public
:
return
True
return
True
# if this block doesn't have changes, then check its children
# if this block doesn't have changes, then check its children
elif
item
.
has_children
:
elif
item
.
has_children
:
...
@@ -792,10 +792,10 @@ class DraftModuleStore(MongoModuleStore):
...
@@ -792,10 +792,10 @@ class DraftModuleStore(MongoModuleStore):
Returns whether this xblock is draft, public, or private.
Returns whether this xblock is draft, public, or private.
Returns:
Returns:
Legacy
PublishState.draft - content is in the process of being edited, but still has a previous
PublishState.draft - content is in the process of being edited, but still has a previous
version deployed to LMS
version deployed to LMS
Legacy
PublishState.public - content is locked and deployed to LMS
PublishState.public - content is locked and deployed to LMS
Legacy
PublishState.private - content is editable and not deployed to LMS
PublishState.private - content is editable and not deployed to LMS
"""
"""
if
getattr
(
xblock
,
'is_draft'
,
False
):
if
getattr
(
xblock
,
'is_draft'
,
False
):
published_xblock_location
=
as_published
(
xblock
.
location
)
published_xblock_location
=
as_published
(
xblock
.
location
)
...
@@ -803,11 +803,11 @@ class DraftModuleStore(MongoModuleStore):
...
@@ -803,11 +803,11 @@ class DraftModuleStore(MongoModuleStore):
{
'_id'
:
published_xblock_location
.
to_deprecated_son
()}
{
'_id'
:
published_xblock_location
.
to_deprecated_son
()}
)
)
if
published_item
is
None
:
if
published_item
is
None
:
return
Legacy
PublishState
.
private
return
PublishState
.
private
else
:
else
:
return
Legacy
PublishState
.
draft
return
PublishState
.
draft
else
:
else
:
return
Legacy
PublishState
.
public
return
PublishState
.
public
def
_verify_branch_setting
(
self
,
expected_branch_setting
):
def
_verify_branch_setting
(
self
,
expected_branch_setting
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py
View file @
ef581e11
...
@@ -4,7 +4,7 @@ Module for the dual-branch fall-back Draft->Published Versioning ModuleStore
...
@@ -4,7 +4,7 @@ Module for the dual-branch fall-back Draft->Published Versioning ModuleStore
from
..exceptions
import
ItemNotFoundError
from
..exceptions
import
ItemNotFoundError
from
split
import
SplitMongoModuleStore
,
EXCLUDE_ALL
from
split
import
SplitMongoModuleStore
,
EXCLUDE_ALL
from
xmodule.modulestore
import
ModuleStoreEnum
,
Legacy
PublishState
from
xmodule.modulestore
import
ModuleStoreEnum
,
PublishState
from
xmodule.modulestore.exceptions
import
InsufficientSpecificationError
from
xmodule.modulestore.exceptions
import
InsufficientSpecificationError
from
xmodule.modulestore.draft_and_published
import
ModuleStoreDraftAndPublished
,
DIRECT_ONLY_CATEGORIES
,
UnsupportedRevisionError
from
xmodule.modulestore.draft_and_published
import
ModuleStoreDraftAndPublished
,
DIRECT_ONLY_CATEGORIES
,
UnsupportedRevisionError
...
@@ -251,9 +251,9 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
...
@@ -251,9 +251,9 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
Returns whether this xblock is draft, public, or private.
Returns whether this xblock is draft, public, or private.
Returns:
Returns:
Legacy
PublishState.draft - published exists and is different from draft
PublishState.draft - published exists and is different from draft
Legacy
PublishState.public - published exists and is the same as draft
PublishState.public - published exists and is the same as draft
Legacy
PublishState.private - no published version exists
PublishState.private - no published version exists
"""
"""
# TODO figure out what to say if xblock is not from the HEAD of its branch
# TODO figure out what to say if xblock is not from the HEAD of its branch
def
get_head
(
branch
):
def
get_head
(
branch
):
...
@@ -272,13 +272,13 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
...
@@ -272,13 +272,13 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
if
not
published_head
:
if
not
published_head
:
# published version does not exist
# published version does not exist
return
Legacy
PublishState
.
private
return
PublishState
.
private
elif
get_version
(
draft_head
)
==
get_version
(
published_head
):
elif
get_version
(
draft_head
)
==
get_version
(
published_head
):
# published and draft versions are equal
# published and draft versions are equal
return
Legacy
PublishState
.
public
return
PublishState
.
public
else
:
else
:
# published and draft versions differ
# published and draft versions differ
return
Legacy
PublishState
.
draft
return
PublishState
.
draft
def
convert_to_draft
(
self
,
location
,
user_id
):
def
convert_to_draft
(
self
,
location
,
user_id
):
"""
"""
...
...
common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
View file @
ef581e11
...
@@ -9,7 +9,7 @@ from pytz import UTC
...
@@ -9,7 +9,7 @@ from pytz import UTC
from
xmodule.tests
import
DATA_DIR
from
xmodule.tests
import
DATA_DIR
from
opaque_keys.edx.locations
import
Location
from
opaque_keys.edx.locations
import
Location
from
xmodule.modulestore
import
ModuleStoreEnum
,
Legacy
PublishState
from
xmodule.modulestore
import
ModuleStoreEnum
,
PublishState
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.exceptions
import
InvalidVersionError
from
xmodule.exceptions
import
InvalidVersionError
...
@@ -991,22 +991,22 @@ class TestMixedModuleStore(unittest.TestCase):
...
@@ -991,22 +991,22 @@ class TestMixedModuleStore(unittest.TestCase):
item_location
=
item
.
location
.
version_agnostic
()
item_location
=
item
.
location
.
version_agnostic
()
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
mongo_store
=
self
.
store
.
_get_modulestore_for_courseid
(
self
.
_course_key_from_string
(
self
.
MONGO_COURSEID
))
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
with
check_mongo_calls
(
mongo_store
,
max_find
,
max_send
):
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
Legacy
PublishState
.
private
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
PublishState
.
private
)
# Private -> Public
# Private -> Public
self
.
store
.
publish
(
item_location
,
self
.
user_id
)
self
.
store
.
publish
(
item_location
,
self
.
user_id
)
item
=
self
.
store
.
get_item
(
item_location
)
item
=
self
.
store
.
get_item
(
item_location
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
Legacy
PublishState
.
public
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
PublishState
.
public
)
# Public -> Private
# Public -> Private
self
.
store
.
unpublish
(
item_location
,
self
.
user_id
)
self
.
store
.
unpublish
(
item_location
,
self
.
user_id
)
item
=
self
.
store
.
get_item
(
item_location
)
item
=
self
.
store
.
get_item
(
item_location
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
Legacy
PublishState
.
private
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
PublishState
.
private
)
# Private -> Public
# Private -> Public
self
.
store
.
publish
(
item_location
,
self
.
user_id
)
self
.
store
.
publish
(
item_location
,
self
.
user_id
)
item
=
self
.
store
.
get_item
(
item_location
)
item
=
self
.
store
.
get_item
(
item_location
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
Legacy
PublishState
.
public
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
PublishState
.
public
)
# Public -> Draft with NO changes
# Public -> Draft with NO changes
# Note: This is where Split and Mongo differ
# Note: This is where Split and Mongo differ
...
@@ -1014,14 +1014,14 @@ class TestMixedModuleStore(unittest.TestCase):
...
@@ -1014,14 +1014,14 @@ class TestMixedModuleStore(unittest.TestCase):
item
=
self
.
store
.
get_item
(
item_location
)
item
=
self
.
store
.
get_item
(
item_location
)
self
.
assertEquals
(
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
self
.
store
.
compute_publish_state
(
item
),
LegacyPublishState
.
draft
if
default_ms
==
'draft'
else
Legacy
PublishState
.
public
PublishState
.
draft
if
default_ms
==
'draft'
else
PublishState
.
public
)
)
# Draft WITH changes
# Draft WITH changes
item
.
display_name
=
'new name'
item
.
display_name
=
'new name'
item
=
self
.
store
.
update_item
(
item
,
self
.
user_id
)
item
=
self
.
store
.
update_item
(
item
,
self
.
user_id
)
self
.
assertTrue
(
self
.
store
.
has_changes
(
item
.
location
))
self
.
assertTrue
(
self
.
store
.
has_changes
(
item
.
location
))
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
Legacy
PublishState
.
draft
)
self
.
assertEquals
(
self
.
store
.
compute_publish_state
(
item
),
PublishState
.
draft
)
@ddt.data
(
'draft'
,
'split'
)
@ddt.data
(
'draft'
,
'split'
)
def
test_auto_publish
(
self
,
default_ms
):
def
test_auto_publish
(
self
,
default_ms
):
...
...
common/test/acceptance/tests/base_studio_test.py
View file @
ef581e11
from
..pages.studio.auto_auth
import
AutoAuthPage
from
..pages.studio.auto_auth
import
AutoAuthPage
from
..fixtures.course
import
CourseFixture
from
..fixtures.course
import
CourseFixture
from
acceptance.tests.helpers
import
UniqueCourseTest
from
.helpers
import
UniqueCourseTest
class
StudioCourseTest
(
UniqueCourseTest
):
class
StudioCourseTest
(
UniqueCourseTest
):
...
...
common/test/acceptance/tests/test_studio_general.py
View file @
ef581e11
...
@@ -25,7 +25,7 @@ from ..pages.studio.signup import SignupPage
...
@@ -25,7 +25,7 @@ from ..pages.studio.signup import SignupPage
from
..pages.studio.textbooks
import
TextbooksPage
from
..pages.studio.textbooks
import
TextbooksPage
from
..fixtures.course
import
XBlockFixtureDesc
from
..fixtures.course
import
XBlockFixtureDesc
from
acceptance.tests
.base_studio_test
import
StudioCourseTest
from
.base_studio_test
import
StudioCourseTest
@attr
(
'shard_1'
)
@attr
(
'shard_1'
)
...
...
common/test/acceptance/tests/test_studio_outline.py
View file @
ef581e11
...
@@ -8,7 +8,7 @@ from ..pages.studio.overview import CourseOutlinePage, ContainerPage, ExpandColl
...
@@ -8,7 +8,7 @@ from ..pages.studio.overview import CourseOutlinePage, ContainerPage, ExpandColl
from
..pages.lms.courseware
import
CoursewarePage
from
..pages.lms.courseware
import
CoursewarePage
from
..fixtures.course
import
XBlockFixtureDesc
from
..fixtures.course
import
XBlockFixtureDesc
from
acceptance.tests
.base_studio_test
import
StudioCourseTest
from
.base_studio_test
import
StudioCourseTest
class
CourseOutlineTest
(
StudioCourseTest
):
class
CourseOutlineTest
(
StudioCourseTest
):
...
...
common/test/acceptance/tests/test_studio_split_test.py
View file @
ef581e11
...
@@ -20,7 +20,7 @@ from ..pages.studio.utils import add_advanced_component
...
@@ -20,7 +20,7 @@ from ..pages.studio.utils import add_advanced_component
from
..pages.studio.unit
import
UnitPage
from
..pages.studio.unit
import
UnitPage
from
..pages.xblock.utils
import
wait_for_xblock_initialization
from
..pages.xblock.utils
import
wait_for_xblock_initialization
from
acceptance.tests
.base_studio_test
import
StudioCourseTest
from
.base_studio_test
import
StudioCourseTest
from
test_studio_container
import
ContainerBase
from
test_studio_container
import
ContainerBase
...
...
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