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
c21895a8
Unverified
Commit
c21895a8
authored
Nov 28, 2017
by
Alessandro Roux
Committed by
GitHub
Nov 28, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #16646 from edx/pacing/highlights-setting-UI-for-courses
Pacing/highlights setting ui for courses
parents
7f60dcb2
9f74e705
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
445 additions
and
42 deletions
+445
-42
cms/djangoapps/contentstore/views/item.py
+8
-2
cms/djangoapps/contentstore/views/tests/test_item.py
+5
-3
cms/static/js/models/xblock_info.js
+1
-0
cms/static/js/spec/views/pages/course_outline_spec.js
+129
-15
cms/static/js/views/course_highlights_enable.js
+54
-0
cms/static/js/views/modals/course_outline_modals.js
+88
-1
cms/static/js/views/pages/course_outline.js
+16
-3
cms/static/sass/views/_outline.scss
+27
-3
cms/templates/course_outline.html
+6
-3
cms/templates/js/course-highlights-enable.underscore
+12
-0
cms/templates/js/highlights-editor.underscore
+4
-1
cms/templates/js/highlights-enable-editor.underscore
+24
-0
cms/templates/js/mock/mock-course-outline-page.underscore
+3
-0
common/test/acceptance/tests/studio/test_studio_outline.py
+2
-0
openedx/core/djangoapps/schedules/content_highlights.py
+46
-10
openedx/core/djangoapps/schedules/tests/test_content_highlights.py
+20
-1
No files found.
cms/djangoapps/contentstore/views/item.py
View file @
c21895a8
...
...
@@ -1188,11 +1188,17 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
xblock_info
.
update
({
'hide_after_due'
:
xblock
.
hide_after_due
,
})
elif
xblock
.
category
==
'chapter'
:
elif
xblock
.
category
in
(
'chapter'
,
'course'
):
if
xblock
.
category
==
'chapter'
:
xblock_info
.
update
({
'highlights'
:
xblock
.
highlights
,
'highlights_enabled'
:
highlights_setting
.
is_enabled
(),
})
elif
xblock
.
category
==
'course'
:
xblock_info
.
update
({
'highlights_enabled_for_messaging'
:
course
.
highlights_enabled_for_messaging
,
})
xblock_info
.
update
({
'highlights_enabled'
:
highlights_setting
.
is_enabled
(),
'highlights_preview_only'
:
not
COURSE_UPDATE_WAFFLE_FLAG
.
is_enabled
(
course
.
id
),
'highlights_doc_url'
:
HelpUrlExpert
.
the_one
()
.
url_for_token
(
'content_highlights'
),
})
...
...
cms/djangoapps/contentstore/views/tests/test_item.py
View file @
c21895a8
...
...
@@ -2577,8 +2577,10 @@ class TestXBlockInfo(ItemTest):
self
.
store
.
update_item
(
self
.
course
,
None
)
chapter
=
self
.
store
.
get_item
(
self
.
chapter
.
location
)
with
highlights_setting
.
override
():
xblock_info
=
create_xblock_info
(
chapter
)
self
.
assertTrue
(
xblock_info
[
'highlights_enabled'
])
chapter_xblock_info
=
create_xblock_info
(
chapter
)
course_xblock_info
=
create_xblock_info
(
self
.
course
)
self
.
assertTrue
(
chapter_xblock_info
[
'highlights_enabled'
])
self
.
assertTrue
(
course_xblock_info
[
'highlights_enabled_for_messaging'
])
def
validate_course_xblock_info
(
self
,
xblock_info
,
has_child_info
=
True
,
course_outline
=
False
):
"""
...
...
@@ -2588,6 +2590,7 @@ class TestXBlockInfo(ItemTest):
self
.
assertEqual
(
xblock_info
[
'id'
],
unicode
(
self
.
course
.
location
))
self
.
assertEqual
(
xblock_info
[
'display_name'
],
self
.
course
.
display_name
)
self
.
assertTrue
(
xblock_info
[
'published'
])
self
.
assertFalse
(
xblock_info
[
'highlights_enabled_for_messaging'
])
# Finally, validate the entire response for consistency
self
.
validate_xblock_info_consistency
(
xblock_info
,
has_child_info
=
has_child_info
,
course_outline
=
course_outline
)
...
...
@@ -2608,7 +2611,6 @@ class TestXBlockInfo(ItemTest):
self
.
assertEqual
(
xblock_info
[
'format'
],
None
)
self
.
assertEqual
(
xblock_info
[
'highlights'
],
self
.
chapter
.
highlights
)
self
.
assertFalse
(
xblock_info
[
'highlights_enabled'
])
self
.
assertFalse
(
xblock_info
[
'highlights_enabled_for_messaging'
])
# Finally, validate the entire response for consistency
self
.
validate_xblock_info_consistency
(
xblock_info
,
has_child_info
=
has_child_info
)
...
...
cms/static/js/models/xblock_info.js
View file @
c21895a8
...
...
@@ -165,6 +165,7 @@ function(Backbone, _, str, ModuleUtils) {
*/
highlights
:
[],
highlights_enabled
:
false
,
highlights_enabled_for_messaging
:
false
,
highlights_preview_only
:
true
,
highlights_doc_url
:
''
},
...
...
cms/static/js/spec/views/pages/course_outline_spec.js
View file @
c21895a8
...
...
@@ -32,7 +32,9 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
children
:
[]
},
user_partitions
:
[],
user_partition_info
:
{}
user_partition_info
:
{},
highlights_enabled
:
true
,
highlights_enabled_for_messaging
:
false
},
options
,
{
child_info
:
{
children
:
children
}});
};
...
...
@@ -262,7 +264,8 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
'due-date-editor'
,
'grading-editor'
,
'publish-editor'
,
'staff-lock-editor'
,
'unit-access-editor'
,
'content-visibility-editor'
,
'settings-modal-tabs'
,
'timed-examination-preference-editor'
,
'access-editor'
,
'show-correctness-editor'
,
'highlights-editor'
'show-correctness-editor'
,
'highlights-editor'
,
'highlights-enable-editor'
,
'course-highlights-enable'
]);
appendSetFixtures
(
mockOutlinePage
);
mockCourseJSON
=
createMockCourseJSON
({},
[
...
...
@@ -529,20 +532,17 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
});
});
describe
(
'Section Highlights'
,
function
()
{
var
createCourse
,
createCourseWithHighlights
,
createCourseWithHighlightsDisabled
,
mockHighlightValues
,
highlightsLink
,
highlightInputs
,
openHighlights
,
saveHighlights
,
setHighlights
,
expectHighlightLinkNumberToBe
,
expectHighlightsToBe
,
expectServerHandshakeWithHighlights
,
expectHighlightsToUpdate
,
maxNumHighlights
=
5
;
describe
(
'Content Highlights'
,
function
()
{
var
createCourse
,
createCourseWithHighlights
,
createCourseWithHighlightsDisabled
,
clickSaveOnModal
,
clickCancelOnModal
;
beforeEach
(
function
()
{
setSelfPaced
();
});
createCourse
=
function
(
sectionOptions
)
{
createCourse
=
function
(
sectionOptions
,
courseOptions
)
{
createCourseOutlinePage
(
this
,
createMockCourseJSON
(
{}
,
[
createMockCourseJSON
(
courseOptions
,
[
createMockSectionJSON
(
sectionOptions
)
])
);
...
...
@@ -553,9 +553,99 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
};
createCourseWithHighlightsDisabled
=
function
()
{
createCourse
({
highlights_enabled
:
false
});
var
highlightsDisabled
=
{
highlights_enabled
:
false
};
createCourse
(
highlightsDisabled
,
highlightsDisabled
);
};
clickSaveOnModal
=
function
()
{
$
(
'.wrapper-modal-window .action-save'
).
click
();
};
clickCancelOnModal
=
function
()
{
$
(
'.wrapper-modal-window .action-cancel'
).
click
();
};
describe
(
'Course Highlights Setting'
,
function
()
{
var
highlightsSetting
,
expectHighlightsEnabledToBe
,
expectServerHandshake
,
openHighlightsSettings
;
highlightsSetting
=
function
()
{
return
$
(
'.course-highlights-setting'
);
};
expectHighlightsEnabledToBe
=
function
(
expectedEnabled
)
{
if
(
expectedEnabled
)
{
expect
(
'.status-highlights-enabled-value.button'
).
not
.
toExist
();
expect
(
'.status-highlights-enabled-value.text'
).
toExist
();
}
else
{
expect
(
'.status-highlights-enabled-value.button'
).
toExist
();
expect
(
'.status-highlights-enabled-value.text'
).
not
.
toExist
();
}
}
expectServerHandshake
=
function
()
{
// POST to update course
AjaxHelpers
.
expectJsonRequest
(
requests
,
'POST'
,
'/xblock/mock-course'
,
{
publish
:
'republish'
,
metadata
:
{
highlights_enabled_for_messaging
:
true
}
});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
// GET updated course
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/outline/mock-course'
);
AjaxHelpers
.
respondWithJson
(
requests
,
createMockCourseJSON
({
highlights_enabled_for_messaging
:
true
})
);
};
openHighlightsSettings
=
function
()
{
$
(
'button.status-highlights-enabled-value'
).
click
();
};
it
(
'does not display settings when disabled'
,
function
()
{
createCourseWithHighlightsDisabled
();
expect
(
highlightsSetting
()).
not
.
toExist
();
});
it
(
'displays settings when enabled'
,
function
()
{
createCourseWithHighlights
([]);
expect
(
highlightsSetting
()).
toExist
();
});
it
(
'displays settings as not enabled for messaging'
,
function
()
{
createCourse
();
expectHighlightsEnabledToBe
(
false
);
});
it
(
'displays settings as enabled for messaging'
,
function
()
{
createCourse
({},
{
highlights_enabled_for_messaging
:
true
});
expectHighlightsEnabledToBe
(
true
);
});
it
(
'changes settings when enabled for messaging'
,
function
()
{
createCourse
();
openHighlightsSettings
();
clickSaveOnModal
();
expectServerHandshake
();
expectHighlightsEnabledToBe
(
true
);
});
it
(
'does not change settings when enabling is cancelled'
,
function
()
{
createCourse
();
openHighlightsSettings
();
clickCancelOnModal
();
expectHighlightsEnabledToBe
(
false
);
});
});
describe
(
'Section Highlights'
,
function
()
{
var
mockHighlightValues
,
highlightsLink
,
highlightInputs
,
openHighlights
,
saveHighlights
,
cancelHighlights
,
setHighlights
,
expectHighlightLinkNumberToBe
,
expectHighlightsToBe
,
expectServerHandshakeWithHighlights
,
expectHighlightsToUpdate
,
maxNumHighlights
=
5
;
mockHighlightValues
=
function
(
numberOfHighlights
)
{
var
highlights
=
[],
i
;
...
...
@@ -578,7 +668,11 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
};
saveHighlights
=
function
()
{
$
(
'.wrapper-modal-window .action-save'
).
click
();
clickSaveOnModal
();
};
cancelHighlights
=
function
()
{
clickCancelOnModal
();
};
setHighlights
=
function
(
highlights
)
{
...
...
@@ -608,7 +702,10 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
}
for
(
i
=
expectedHighlights
.
length
;
i
<
maxNumHighlights
;
i
++
)
{
expect
(
highlights
[
i
]).
toHaveValue
(
''
);
expect
(
highlights
[
i
]).
toHaveAttr
(
'placeholder'
,
'A highlight to look forward to this week.'
);
expect
(
highlights
[
i
]).
toHaveAttr
(
'placeholder'
,
'A highlight to look forward to this week.'
);
}
};
...
...
@@ -641,9 +738,9 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
expectHighlightsToBe
(
updatedHighlights
);
};
it
(
'does not display a link when highlights is
disabled'
,
function
()
{
it
(
'does not display link when
disabled'
,
function
()
{
createCourseWithHighlightsDisabled
();
expect
(
highlightsLink
()).
toHaveLength
(
0
);
expect
(
highlightsLink
()).
not
.
toExist
(
);
});
it
(
'displays link when no highlights exist'
,
function
()
{
...
...
@@ -670,6 +767,22 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
expectHighlightsToBe
(
highlights
);
});
it
(
'does not save highlights when cancelled'
,
function
()
{
var
originalHighlights
=
mockHighlightValues
(
2
),
editedHighlights
=
originalHighlights
;
editedHighlights
[
1
]
=
'A New Value'
;
createCourseWithHighlights
(
originalHighlights
);
openHighlights
();
setHighlights
(
editedHighlights
);
cancelHighlights
();
AjaxHelpers
.
expectNoRequests
(
requests
);
openHighlights
();
expectHighlightsToBe
(
originalHighlights
);
});
it
(
'can add highlights'
,
function
()
{
expectHighlightsToUpdate
(
mockHighlightValues
(
0
),
...
...
@@ -691,6 +804,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
expectHighlightsToUpdate
(
originalHighlights
,
editedHighlights
);
});
});
});
describe
(
'Section'
,
function
()
{
var
getDisplayNameWrapper
;
...
...
cms/static/js/views/course_highlights_enable.js
0 → 100644
View file @
c21895a8
define
([
'jquery'
,
'underscore'
,
'backbone'
,
'js/views/utils/xblock_utils'
,
'js/utils/templates'
,
'js/views/modals/course_outline_modals'
,
'edx-ui-toolkit/js/utils/html-utils'
],
function
(
$
,
_
,
Backbone
,
XBlockViewUtils
,
TemplateUtils
,
CourseOutlineModalsFactory
,
HtmlUtils
)
{
'use strict'
;
var
CourseHighlightsEnableView
=
Backbone
.
View
.
extend
({
events
:
{
'click button.status-highlights-enabled-value'
:
'handleEnableButtonPress'
,
'keypress button.status-highlights-enabled-value'
:
'handleEnableButtonPress'
},
initialize
:
function
()
{
this
.
template
=
TemplateUtils
.
loadTemplate
(
'course-highlights-enable'
);
},
handleEnableButtonPress
:
function
(
event
)
{
if
(
event
.
type
===
'click'
||
event
.
key
===
'Enter'
||
event
.
key
===
' '
)
{
event
.
preventDefault
();
this
.
highlightsEnableXBlock
();
}
},
highlightsEnableXBlock
:
function
()
{
var
modal
=
CourseOutlineModalsFactory
.
getModal
(
'highlights_enable'
,
this
.
model
,
{
onSave
:
this
.
refresh
.
bind
(
this
),
xblockType
:
XBlockViewUtils
.
getXBlockType
(
this
.
model
.
get
(
'category'
)
)
});
if
(
modal
)
{
window
.
analytics
.
track
(
'edx.bi.highlights_enable.modal_open'
);
modal
.
show
();
}
},
refresh
:
function
()
{
this
.
model
.
fetch
({
success
:
this
.
render
.
bind
(
this
)
});
},
render
:
function
()
{
var
html
=
this
.
template
(
this
.
model
.
attributes
);
HtmlUtils
.
setHtml
(
this
.
$el
,
HtmlUtils
.
HTML
(
html
));
return
this
;
}
});
return
CourseHighlightsEnableView
;
}
);
cms/static/js/views/modals/course_outline_modals.js
View file @
c21895a8
...
...
@@ -17,7 +17,7 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
AbstractEditor
,
BaseDateEditor
,
ReleaseDateEditor
,
DueDateEditor
,
GradingEditor
,
PublishEditor
,
AbstractVisibilityEditor
,
StaffLockEditor
,
UnitAccessEditor
,
ContentVisibilityEditor
,
TimedExaminationPreferenceEditor
,
AccessEditor
,
ShowCorrectnessEditor
,
HighlightsEditor
;
AccessEditor
,
ShowCorrectnessEditor
,
HighlightsEditor
,
HighlightsEnableXBlockModal
,
HighlightsEnableEditor
;
CourseOutlineXBlockModal
=
BaseModal
.
extend
({
events
:
_
.
extend
({},
BaseModal
.
prototype
.
events
,
{
...
...
@@ -242,7 +242,11 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
callAnalytics
:
function
(
event
)
{
event
.
preventDefault
();
window
.
analytics
.
track
(
'edx.bi.highlights.'
+
event
.
target
.
innerText
.
toLowerCase
());
if
(
event
.
target
.
className
.
indexOf
(
'save'
)
!==
-
1
)
{
this
.
save
(
event
);
}
else
{
this
.
hide
();
}
},
addActionButtons
:
function
()
{
...
...
@@ -251,6 +255,44 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
}
});
HighlightsEnableXBlockModal
=
CourseOutlineXBlockModal
.
extend
({
events
:
_
.
extend
({},
CourseOutlineXBlockModal
.
prototype
.
events
,
{
'click .action-save'
:
'callAnalytics'
,
'click .action-cancel'
:
'callAnalytics'
}),
initialize
:
function
()
{
CourseOutlineXBlockModal
.
prototype
.
initialize
.
call
(
this
);
if
(
this
.
options
.
xblockType
)
{
this
.
options
.
modalName
=
'highlights-enable-'
+
this
.
options
.
xblockType
;
}
},
getTitle
:
function
()
{
return
gettext
(
'Enable Weekly Course Highlight Messages'
);
},
getIntroductionMessage
:
function
()
{
return
''
;
},
callAnalytics
:
function
(
event
)
{
event
.
preventDefault
();
window
.
analytics
.
track
(
'edx.bi.highlights_enable.'
+
event
.
target
.
innerText
.
toLowerCase
());
if
(
event
.
target
.
className
.
indexOf
(
'save'
)
!==
-
1
)
{
this
.
save
(
event
);
}
else
{
this
.
hide
();
}
},
addActionButtons
:
function
()
{
this
.
addActionButton
(
'save'
,
gettext
(
'Enable'
),
true
);
this
.
addActionButton
(
'cancel'
,
gettext
(
'Not yet'
));
}
});
AbstractEditor
=
BaseView
.
extend
({
tagName
:
'section'
,
templateName
:
null
,
...
...
@@ -933,6 +975,42 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
}
});
HighlightsEnableEditor
=
AbstractEditor
.
extend
({
templateName
:
'highlights-enable-editor'
,
className
:
'edit-enable-highlights'
,
currentValue
:
function
()
{
return
true
;
},
hasChanges
:
function
()
{
return
this
.
model
.
get
(
'highlights_enabled_for_messaging'
)
!==
this
.
currentValue
();
},
getRequestData
:
function
()
{
if
(
this
.
hasChanges
())
{
return
{
publish
:
'republish'
,
metadata
:
{
highlights_enabled_for_messaging
:
this
.
currentValue
()
}
};
}
else
{
return
{};
}
},
getContext
:
function
()
{
return
$
.
extend
(
{},
AbstractEditor
.
prototype
.
getContext
.
call
(
this
),
{
highlights_enabled
:
this
.
model
.
get
(
'highlights_enabled_for_messaging'
),
highlights_doc_url
:
this
.
model
.
get
(
'highlights_doc_url'
)
}
);
}
});
return
{
getModal
:
function
(
type
,
xblockInfo
,
options
)
{
if
(
type
===
'edit'
)
{
...
...
@@ -941,6 +1019,8 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
return
this
.
getPublishModal
(
xblockInfo
,
options
);
}
else
if
(
type
===
'highlights'
)
{
return
this
.
getHighlightsModal
(
xblockInfo
,
options
);
}
else
if
(
type
===
'highlights_enable'
)
{
return
this
.
getHighlightsEnableModal
(
xblockInfo
,
options
);
}
else
{
return
null
;
}
...
...
@@ -1018,6 +1098,13 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
editors
:
[
HighlightsEditor
],
model
:
xblockInfo
},
options
));
},
getHighlightsEnableModal
:
function
(
xblockInfo
,
options
)
{
return
new
HighlightsEnableXBlockModal
(
$
.
extend
({
editors
:
[
HighlightsEnableEditor
],
model
:
xblockInfo
},
options
));
}
};
});
cms/static/js/views/pages/course_outline.js
View file @
c21895a8
/**
* This page is used to show the user an outline of the course.
*/
define
([
'jquery'
,
'underscore'
,
'gettext'
,
'js/views/pages/base_page'
,
'js/views/utils/xblock_utils'
,
define
([
'jquery'
,
'underscore'
,
'gettext'
,
'js/views/pages/base_page'
,
'js/views/utils/xblock_utils'
,
'js/views/course_outline'
,
'common/js/components/utils/view_utils'
,
'common/js/components/views/feedback_alert'
,
'common/js/components/views/feedback_notification'
],
function
(
$
,
_
,
gettext
,
BasePage
,
XBlockViewUtils
,
CourseOutlineView
,
ViewUtils
,
AlertView
,
NoteView
)
{
'common/js/components/views/feedback_notification'
,
'js/views/course_highlights_enable'
],
function
(
$
,
_
,
gettext
,
BasePage
,
XBlockViewUtils
,
CourseOutlineView
,
ViewUtils
,
AlertView
,
NoteView
,
CourseHighlightsEnableView
)
{
'use strict'
;
var
expandedLocators
,
CourseOutlinePage
;
CourseOutlinePage
=
BasePage
.
extend
({
...
...
@@ -65,6 +69,15 @@ define(['jquery', 'underscore', 'gettext', 'js/views/pages/base_page', 'js/views
this
.
expandedLocators
.
addAll
(
this
.
initialState
.
expanded_locators
);
}
/* globals course */
if
(
this
.
model
.
get
(
'highlights_enabled'
)
&&
course
.
get
(
'self_paced'
))
{
this
.
highlightsEnableView
=
new
CourseHighlightsEnableView
({
el
:
this
.
$
(
'.status-highlights-enabled'
),
model
:
this
.
model
});
this
.
highlightsEnableView
.
render
();
}
this
.
outlineView
=
new
CourseOutlineView
({
el
:
this
.
$
(
'.outline'
),
model
:
this
.
model
,
...
...
cms/static/sass/views/_outline.scss
View file @
c21895a8
...
...
@@ -184,11 +184,13 @@
margin-bottom
:
$baseline
;
.status-release
,
.status-pacing
{
.status-pacing
,
.status-highlights-enabled
{
@extend
%t-copy-base
;
display
:
inline-block
;
color
:
$color-copy-base
;
margin-right
:
$baseline
;
// STATE: hover
&
:hover
{
...
...
@@ -198,10 +200,17 @@
}
}
.status-highlights-enabled
{
margin-left
:
$baseline
*
1
.6
;
}
.status-release-label
,
.status-release-value
,
.status-pacing-label
,
.status-pacing-value
,
.status-highlights-enabled-label
,
.status-highlights-enabled-value
,
.status-highlights-enabled-info
,
.status-actions
{
display
:
inline-block
;
vertical-align
:
middle
;
...
...
@@ -209,13 +218,28 @@
}
.status-release-label
,
.status-pacing-label
{
.status-pacing-label
,
.status-highlights-enabled-label
{
margin-right
:
(
$baseline
/
4
);
}
.status-release-value
,
.status-pacing-value
{
.status-pacing-value
,
.status-highlights-enabled-value
{
@extend
%t-strong
;
font-size
:
smaller
;
}
.status-highlights-enabled-info
{
font-size
:
smaller
;
margin-left
:
$baseline
/
2
;
}
.status-highlights-enabled-value.button
{
@extend
%btn-primary-blue
;
@extend
%sizing
;
padding
:
5px
8px
;
margin-top
:
2px
;
}
.status-actions
{
...
...
cms/templates/course_outline.html
View file @
c21895a8
...
...
@@ -26,7 +26,7 @@ from openedx.core.djangolib.markup import HTML, Text
<
%
block
name=
"header_extras"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"${static.url('js/vendor/timepicker/jquery.timepicker.css')}"
/>
% for template_name in ['course-outline', 'xblock-string-field-editor', 'basic-modal', 'modal-button', 'course-outline-modal', 'due-date-editor', 'release-date-editor', 'grading-editor', 'publish-editor', 'staff-lock-editor', 'unit-access-editor', 'content-visibility-editor', 'verification-access-editor', 'timed-examination-preference-editor', 'access-editor', 'settings-modal-tabs', 'show-correctness-editor', 'highlights-editor']:
% for template_name in ['course-outline', 'xblock-string-field-editor', 'basic-modal', 'modal-button', 'course-outline-modal', 'due-date-editor', 'release-date-editor', 'grading-editor', 'publish-editor', 'staff-lock-editor', 'unit-access-editor', 'content-visibility-editor', 'verification-access-editor', 'timed-examination-preference-editor', 'access-editor', 'settings-modal-tabs', 'show-correctness-editor', 'highlights-editor'
, 'highlights-enable-editor', 'course-highlights-enable'
]:
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<%
static
:
include
path
=
"js/${template_name}.underscore"
/>
</script>
...
...
@@ -152,7 +152,8 @@ from openedx.core.djangolib.markup import HTML, Text
<article
class=
"content-primary"
role=
"main"
>
<div
class=
"course-status"
>
<div
class=
"status-release"
>
<h2
class=
"status-release-label"
>
${_("Course Start Date:")}
</h2>
<h2
class=
"status-release-label"
>
${_("Course Start Date")}
</h2>
<br>
<p
class=
"status-release-value"
>
${course_release_date}
</p>
<ul
class=
"status-actions"
>
...
...
@@ -166,7 +167,8 @@ from openedx.core.djangolib.markup import HTML, Text
</div>
% if SelfPacedConfiguration.current().enabled:
<div
class=
"status-pacing"
>
<h2
class=
status-pacing-label
>
${_("Course Pacing:")}
</h2>
<h2
class=
status-pacing-label
>
${_("Course Pacing")}
</h2>
<br>
% if context_course.self_paced:
<p
class=
"status-pacing-value"
>
${_("Self-Paced")}
</p>
% else:
...
...
@@ -174,6 +176,7 @@ from openedx.core.djangolib.markup import HTML, Text
% endif
</div>
% endif
<div
class=
"status-highlights-enabled"
></div>
</div>
<div
class=
"wrapper-dnd"
%
if
getattr
(
context_course
,
'
language
')
:
...
...
cms/templates/js/course-highlights-enable.underscore
0 → 100644
View file @
c21895a8
<div class="course-highlights-setting">
<h2 id="highlights-enabled-label" class="status-highlights-enabled-label">
<%- gettext('Weekly Highlight Emails') %>
</h2>
<br>
<% if (highlights_enabled_for_messaging) { %>
<span class="status-highlights-enabled-value text"><%- gettext('Enabled') %></span>
<% } else { %>
<button class="status-highlights-enabled-value button" aria-labelledby="highlights-enabled-label"><%- gettext('Enable Now') %></button>
<% } %>
<a class="status-highlights-enabled-info" href="<%- highlights_doc_url %>">Learn more</a>
</div>
cms/templates/js/highlights-editor.underscore
View file @
c21895a8
...
...
@@ -19,7 +19,10 @@
'read our {linkStart}documentation{linkEnd}.'
),
{
linkStart: edx.HtmlUtils.HTML('<a href="' + highlights_doc_url + '">'),
linkStart: edx.HtmlUtils.interpolateHtml(
edx.HtmlUtils.HTML('<a href={highlightsDocUrl}">'),
{highlightsDocUrl: highlights_doc_url}
),
linkEnd: edx.HtmlUtils.HTML('</a>')
}
) %>
...
...
cms/templates/js/highlights-enable-editor.underscore
0 → 100644
View file @
c21895a8
<p>
<%- gettext(
'When you enable weekly course highlight messages, learners ' +
'automatically receive weekly email messages for each section that ' +
'has highlights. You cannot disable highlights after you start ' +
'sending them.'
) %>
</p>
<p>
<% // xss-lint: disable=underscore-not-escaped %>
<%= edx.HtmlUtils.interpolateHtml(
gettext(
'Are you sure you want to enable weekly course highlight messages? '
+ '{linkStart}Learn more.{linkEnd}'
),
{
linkStart: edx.HtmlUtils.interpolateHtml(
edx.HtmlUtils.HTML('<a href="{highlightsDocUrl}" target="_blank">'),
{highlightsDocUrl: xblockInfo.attributes.highlights_doc_url}
),
linkEnd: edx.HtmlUtils.HTML('</a>')
}
) %>
</p>
cms/templates/js/mock/mock-course-outline-page.underscore
View file @
c21895a8
...
...
@@ -37,6 +37,9 @@
<div class="wrapper-content wrapper">
<section class="content">
<article class="content-primary" role="main">
<div class=course-status"">
<div class="status-highlights-enabled"></div>
</div>
<div class="wrapper-dnd">
<article class="outline outline-course" data-locator="mock-course" data-course-key="slashes:MockCourse">
<div class="no-content add-xblock-component">
...
...
common/test/acceptance/tests/studio/test_studio_outline.py
View file @
c21895a8
...
...
@@ -5,6 +5,7 @@ Acceptance tests for studio related to the outline page.
import
itertools
import
json
from
datetime
import
datetime
,
timedelta
from
unittest
import
skip
from
nose.plugins.attrib
import
attr
from
pytz
import
UTC
...
...
@@ -115,6 +116,7 @@ class CourseOutlineDragAndDropTest(CourseOutlineTest):
expected_ordering
)
@skip
(
"Fails in Firefox 45 but passes in Chrome"
)
def
test_drop_unit_in_collapsed_subsection
(
self
):
"""
Drag vertical "1.1.2" from subsection "1.1" into collapsed subsection "1.2" which already
...
...
openedx/core/djangoapps/schedules/content_highlights.py
View file @
c21895a8
"""
Contains methods for accessing weekly course highlights. Weekly highlights is a
schedule experience built on the Schedules app.
"""
import
logging
from
courseware.module_render
import
get_module_for_descriptor
from
courseware.model_data
import
FieldDataCache
from
openedx.core.djangoapps.schedules.config
import
COURSE_UPDATE_WAFFLE_FLAG
...
...
@@ -6,6 +12,8 @@ from request_cache import get_request_or_stub
from
xmodule.modulestore.django
import
modulestore
log
=
logging
.
getLogger
(
__name__
)
def
course_has_highlights
(
course_key
):
"""
...
...
@@ -13,35 +21,63 @@ def course_has_highlights(course_key):
This ignores access checks, since highlights may be lurking in currently
inaccessible content.
"""
if
not
COURSE_UPDATE_WAFFLE_FLAG
.
is_enabled
(
course_key
):
try
:
course
=
_get_course_with_highlights
(
course_key
)
except
CourseUpdateDoesNotExist
:
return
False
course
=
modulestore
()
.
get_course
(
course_key
,
depth
=
1
)
return
any
(
else
:
highlights_are_available
=
any
(
section
.
highlights
for
section
in
course
.
get_children
()
if
not
section
.
hide_from_toc
)
if
not
highlights_are_available
:
log
.
error
(
"Course team enabled highlights and provided no highlights."
)
return
highlights_are_available
def
get_week_highlights
(
user
,
course_key
,
week_num
):
"""
Get highlights (list of unicode strings) for a given week.
week_num starts at 1.
Raises CourseUpdateDoesNotExist if highlights do not exist for
Raises:
CourseUpdateDoesNotExist: if highlights do not exist for
the requested week_num.
"""
course_descriptor
=
_get_course_with_highlights
(
course_key
)
course_module
=
_get_course_module
(
course_descriptor
,
user
)
sections_with_highlights
=
_get_sections_with_highlights
(
course_module
)
highlights
=
_get_highlights_for_week
(
sections_with_highlights
,
week_num
,
course_key
,
)
return
highlights
def
_get_course_with_highlights
(
course_key
):
# pylint: disable=missing-docstring
if
not
COURSE_UPDATE_WAFFLE_FLAG
.
is_enabled
(
course_key
):
raise
CourseUpdateDoesNotExist
(
"
%
s
does not have Course Updates en
abled."
,
course_key
"
%
s
Course Update Messages waffle flag is dis
abled."
,
course_key
,
)
course_descriptor
=
_get_course_descriptor
(
course_key
)
course_module
=
_get_course_module
(
course_descriptor
,
user
)
sections_with_highlights
=
_get_sections_with_highlights
(
course_module
)
highlights
=
_get_highlights_for_week
(
sections_with_highlights
,
week_num
,
course_key
)
return
highlights
if
not
course_descriptor
.
highlights_enabled_for_messaging
:
raise
CourseUpdateDoesNotExist
(
"
%
s Course Update Messages are disabled."
,
course_key
,
)
return
course_descriptor
def
_get_course_descriptor
(
course_key
):
...
...
openedx/core/djangoapps/schedules/tests/test_content_highlights.py
View file @
c21895a8
...
...
@@ -21,7 +21,9 @@ class TestContentHighlights(ModuleStoreTestCase):
self
.
_setup_user
()
def
_setup_course
(
self
):
self
.
course
=
CourseFactory
.
create
()
self
.
course
=
CourseFactory
.
create
(
highlights_enabled_for_messaging
=
True
)
self
.
course_key
=
self
.
course
.
id
def
_setup_user
(
self
):
...
...
@@ -67,6 +69,23 @@ class TestContentHighlights(ModuleStoreTestCase):
)
@override_waffle_flag
(
COURSE_UPDATE_WAFFLE_FLAG
,
True
)
def
test_highlights_disabled_for_messaging
(
self
):
highlights
=
[
u'A test highlight.'
]
with
self
.
store
.
bulk_operations
(
self
.
course_key
):
self
.
_create_chapter
(
highlights
=
highlights
)
self
.
course
.
highlights_enabled_for_messaging
=
False
self
.
store
.
update_item
(
self
.
course
,
self
.
user
.
id
)
self
.
assertFalse
(
course_has_highlights
(
self
.
course_key
))
with
self
.
assertRaises
(
CourseUpdateDoesNotExist
):
get_week_highlights
(
self
.
user
,
self
.
course_key
,
week_num
=
1
,
)
@override_waffle_flag
(
COURSE_UPDATE_WAFFLE_FLAG
,
True
)
def
test_course_with_no_highlights
(
self
):
with
self
.
store
.
bulk_operations
(
self
.
course_key
):
self
.
_create_chapter
(
display_name
=
u"Week 1"
)
...
...
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