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
2211ae33
Commit
2211ae33
authored
Oct 23, 2017
by
Nimisha Asthagiri
Committed by
GitHub
Oct 23, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #16304 from edx/pacing/studio-updates
Dynamic pacing: Studio support of Section Highlights
parents
59490244
ee1a003c
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
359 additions
and
13 deletions
+359
-13
cms/djangoapps/contentstore/views/item.py
+5
-0
cms/djangoapps/contentstore/views/tests/test_item.py
+3
-1
cms/envs/common.py
+4
-1
cms/envs/test.py
+2
-0
cms/static/js/models/xblock_info.js
+6
-1
cms/static/js/spec/views/pages/course_outline_spec.js
+172
-6
cms/static/js/views/course_outline.js
+17
-0
cms/static/js/views/modals/base_modal.js
+1
-1
cms/static/js/views/modals/course_outline_modals.js
+88
-2
cms/static/sass/views/_outline.scss
+17
-0
cms/templates/course_outline.html
+1
-1
cms/templates/js/course-outline.underscore
+16
-0
cms/templates/js/highlights-editor.underscore
+27
-0
No files found.
cms/djangoapps/contentstore/views/item.py
View file @
2211ae33
...
@@ -1182,6 +1182,11 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
...
@@ -1182,6 +1182,11 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F
xblock_info
.
update
({
xblock_info
.
update
({
'hide_after_due'
:
xblock
.
hide_after_due
,
'hide_after_due'
:
xblock
.
hide_after_due
,
})
})
elif
xblock
.
category
==
'chapter'
:
xblock_info
.
update
({
'highlights'
:
xblock
.
highlights
,
'highlights_enabled'
:
settings
.
FEATURES
.
get
(
'ENABLE_SECTION_HIGHLIGHTS'
,
False
),
})
# update xblock_info with special exam information if the feature flag is enabled
# update xblock_info with special exam information if the feature flag is enabled
if
settings
.
FEATURES
.
get
(
'ENABLE_SPECIAL_EXAMS'
):
if
settings
.
FEATURES
.
get
(
'ENABLE_SPECIAL_EXAMS'
):
...
...
cms/djangoapps/contentstore/views/tests/test_item.py
View file @
2211ae33
...
@@ -2389,7 +2389,8 @@ class TestXBlockInfo(ItemTest):
...
@@ -2389,7 +2389,8 @@ class TestXBlockInfo(ItemTest):
super
(
TestXBlockInfo
,
self
)
.
setUp
()
super
(
TestXBlockInfo
,
self
)
.
setUp
()
user_id
=
self
.
user
.
id
user_id
=
self
.
user
.
id
self
.
chapter
=
ItemFactory
.
create
(
self
.
chapter
=
ItemFactory
.
create
(
parent_location
=
self
.
course
.
location
,
category
=
'chapter'
,
display_name
=
"Week 1"
,
user_id
=
user_id
parent_location
=
self
.
course
.
location
,
category
=
'chapter'
,
display_name
=
"Week 1"
,
user_id
=
user_id
,
highlights
=
[
'highlight'
],
)
)
self
.
sequential
=
ItemFactory
.
create
(
self
.
sequential
=
ItemFactory
.
create
(
parent_location
=
self
.
chapter
.
location
,
category
=
'sequential'
,
display_name
=
"Lesson 1"
,
user_id
=
user_id
parent_location
=
self
.
chapter
.
location
,
category
=
'sequential'
,
display_name
=
"Lesson 1"
,
user_id
=
user_id
...
@@ -2596,6 +2597,7 @@ class TestXBlockInfo(ItemTest):
...
@@ -2596,6 +2597,7 @@ class TestXBlockInfo(ItemTest):
self
.
assertEqual
(
xblock_info
[
'graded'
],
False
)
self
.
assertEqual
(
xblock_info
[
'graded'
],
False
)
self
.
assertEqual
(
xblock_info
[
'due'
],
None
)
self
.
assertEqual
(
xblock_info
[
'due'
],
None
)
self
.
assertEqual
(
xblock_info
[
'format'
],
None
)
self
.
assertEqual
(
xblock_info
[
'format'
],
None
)
self
.
assertEqual
(
xblock_info
[
'highlights'
],
self
.
chapter
.
highlights
)
# Finally, validate the entire response for consistency
# Finally, validate the entire response for consistency
self
.
validate_xblock_info_consistency
(
xblock_info
,
has_child_info
=
has_child_info
)
self
.
validate_xblock_info_consistency
(
xblock_info
,
has_child_info
=
has_child_info
)
...
...
cms/envs/common.py
View file @
2211ae33
...
@@ -264,7 +264,10 @@ FEATURES = {
...
@@ -264,7 +264,10 @@ FEATURES = {
# Whether archived courses (courses with end dates in the past) should be
# Whether archived courses (courses with end dates in the past) should be
# shown in Studio in a separate list.
# shown in Studio in a separate list.
'ENABLE_SEPARATE_ARCHIVED_COURSES'
:
True
'ENABLE_SEPARATE_ARCHIVED_COURSES'
:
True
,
# Whether section-level highlights are enabled on the platform.
'ENABLE_SECTION_HIGHLIGHTS'
:
False
,
}
}
ENABLE_JASMINE
=
False
ENABLE_JASMINE
=
False
...
...
cms/envs/test.py
View file @
2211ae33
...
@@ -326,6 +326,8 @@ SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine"
...
@@ -326,6 +326,8 @@ SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine"
FEATURES
[
'ENABLE_ENROLLMENT_TRACK_USER_PARTITION'
]
=
True
FEATURES
[
'ENABLE_ENROLLMENT_TRACK_USER_PARTITION'
]
=
True
FEATURES
[
'ENABLE_SECTION_HIGHLIGHTS'
]
=
True
########################## AUTHOR PERMISSION #######################
########################## AUTHOR PERMISSION #######################
FEATURES
[
'ENABLE_CREATOR_GROUP'
]
=
False
FEATURES
[
'ENABLE_CREATOR_GROUP'
]
=
False
...
...
cms/static/js/models/xblock_info.js
View file @
2211ae33
...
@@ -159,7 +159,12 @@ function(Backbone, _, str, ModuleUtils) {
...
@@ -159,7 +159,12 @@ function(Backbone, _, str, ModuleUtils) {
* some additional fields that are not stored in the course descriptor
* some additional fields that are not stored in the course descriptor
* (for example, which groups are selected for this particular XBlock).
* (for example, which groups are selected for this particular XBlock).
*/
*/
user_partitions
:
null
user_partitions
:
null
,
/**
* This xBlock's Highlights to message to learners.
*/
highlights
:
null
,
highlights_enabled
:
null
},
},
initialize
:
function
()
{
initialize
:
function
()
{
...
...
cms/static/js/spec/views/pages/course_outline_spec.js
View file @
2211ae33
...
@@ -7,7 +7,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
...
@@ -7,7 +7,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
var
createCourseOutlinePage
,
displayNameInput
,
model
,
outlinePage
,
requests
,
getItemsOfType
,
getItemHeaders
,
var
createCourseOutlinePage
,
displayNameInput
,
model
,
outlinePage
,
requests
,
getItemsOfType
,
getItemHeaders
,
verifyItemsExpanded
,
expandItemsAndVerifyState
,
collapseItemsAndVerifyState
,
selectBasicSettings
,
verifyItemsExpanded
,
expandItemsAndVerifyState
,
collapseItemsAndVerifyState
,
selectBasicSettings
,
selectVisibilitySettings
,
selectAdvancedSettings
,
createMockCourseJSON
,
createMockSectionJSON
,
selectVisibilitySettings
,
selectAdvancedSettings
,
createMockCourseJSON
,
createMockSectionJSON
,
createMockSubsectionJSON
,
verifyTypePublishable
,
mockCourseJSON
,
mockEmptyCourseJSON
,
createMockSubsectionJSON
,
verifyTypePublishable
,
mockCourseJSON
,
mockEmptyCourseJSON
,
setSelfPaced
,
mockSingleSectionCourseJSON
,
createMockVerticalJSON
,
createMockIndexJSON
,
mockCourseEntranceExamJSON
,
mockSingleSectionCourseJSON
,
createMockVerticalJSON
,
createMockIndexJSON
,
mockCourseEntranceExamJSON
,
mockOutlinePage
=
readFixtures
(
'mock/mock-course-outline-page.underscore'
),
mockOutlinePage
=
readFixtures
(
'mock/mock-course-outline-page.underscore'
),
mockRerunNotification
=
readFixtures
(
'mock/mock-course-rerun-notification.underscore'
);
mockRerunNotification
=
readFixtures
(
'mock/mock-course-rerun-notification.underscore'
);
...
@@ -55,7 +55,9 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
...
@@ -55,7 +55,9 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
},
},
user_partitions
:
[],
user_partitions
:
[],
group_access
:
{},
group_access
:
{},
user_partition_info
:
{}
user_partition_info
:
{},
highlights
:
[],
highlights_enabled
:
true
},
options
,
{
child_info
:
{
children
:
children
}});
},
options
,
{
child_info
:
{
children
:
children
}});
};
};
...
@@ -160,6 +162,11 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
...
@@ -160,6 +162,11 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
this
.
$
(
".modal-section .settings-tab-button[data-tab='advanced']"
).
click
();
this
.
$
(
".modal-section .settings-tab-button[data-tab='advanced']"
).
click
();
};
};
setSelfPaced
=
function
()
{
/* global course */
course
.
set
(
'self_paced'
,
true
);
};
createCourseOutlinePage
=
function
(
test
,
courseJSON
,
createOnly
)
{
createCourseOutlinePage
=
function
(
test
,
courseJSON
,
createOnly
)
{
requests
=
AjaxHelpers
.
requests
(
test
);
requests
=
AjaxHelpers
.
requests
(
test
);
model
=
new
XBlockOutlineInfo
(
courseJSON
,
{
parse
:
true
});
model
=
new
XBlockOutlineInfo
(
courseJSON
,
{
parse
:
true
});
...
@@ -255,7 +262,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
...
@@ -255,7 +262,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
'due-date-editor'
,
'grading-editor'
,
'publish-editor'
,
'due-date-editor'
,
'grading-editor'
,
'publish-editor'
,
'staff-lock-editor'
,
'unit-access-editor'
,
'content-visibility-editor'
,
'staff-lock-editor'
,
'unit-access-editor'
,
'content-visibility-editor'
,
'settings-modal-tabs'
,
'timed-examination-preference-editor'
,
'access-editor'
,
'settings-modal-tabs'
,
'timed-examination-preference-editor'
,
'access-editor'
,
'show-correctness-editor'
'show-correctness-editor'
,
'highlights-editor'
]);
]);
appendSetFixtures
(
mockOutlinePage
);
appendSetFixtures
(
mockOutlinePage
);
mockCourseJSON
=
createMockCourseJSON
({},
[
mockCourseJSON
=
createMockCourseJSON
({},
[
...
@@ -522,6 +529,166 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
...
@@ -522,6 +529,166 @@ 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
,
expectHighlightLinkTextToBe
,
expectHighlightsToBe
,
expectServerHandshakeWithHighlights
,
expectHighlightsToUpdate
,
maxNumHighlights
=
5
;
beforeEach
(
function
()
{
setSelfPaced
();
});
createCourse
=
function
(
sectionOptions
)
{
createCourseOutlinePage
(
this
,
createMockCourseJSON
({},
[
createMockSectionJSON
(
sectionOptions
)
])
);
};
createCourseWithHighlights
=
function
(
highlights
)
{
createCourse
({
highlights
:
highlights
});
};
createCourseWithHighlightsDisabled
=
function
()
{
createCourse
({
highlights_enabled
:
false
});
};
mockHighlightValues
=
function
(
numberOfHighlights
)
{
var
highlights
=
[],
i
;
for
(
i
=
0
;
i
<
numberOfHighlights
;
i
++
)
{
highlights
.
push
(
'Highlight'
+
(
i
+
1
));
}
return
highlights
;
};
highlightsLink
=
function
()
{
return
outlinePage
.
$
(
'.section-status >> .highlights-button'
);
};
highlightInputs
=
function
()
{
return
$
(
'.highlight-input-text'
);
};
openHighlights
=
function
()
{
highlightsLink
().
click
();
};
saveHighlights
=
function
()
{
$
(
'.wrapper-modal-window .action-save'
).
click
();
};
setHighlights
=
function
(
highlights
)
{
var
i
;
for
(
i
=
0
;
i
<
highlights
.
length
;
i
++
)
{
$
(
highlightInputs
()[
i
]).
val
(
highlights
[
i
]);
}
for
(
i
=
highlights
.
length
;
i
<
maxNumHighlights
;
i
++
)
{
$
(
highlightInputs
()[
i
]).
val
(
''
);
}
};
expectHighlightLinkTextToBe
=
function
(
expectedValue
)
{
expect
(
highlightsLink
()).
toContainText
(
expectedValue
);
};
expectHighlightsToBe
=
function
(
expectedHighlights
)
{
var
highlights
=
highlightInputs
(),
i
;
expect
(
highlights
).
toHaveLength
(
maxNumHighlights
);
for
(
i
=
0
;
i
<
expectedHighlights
.
length
;
i
++
)
{
expect
(
highlights
[
i
]).
toHaveValue
(
expectedHighlights
[
i
]);
}
for
(
i
=
expectedHighlights
.
length
;
i
<
maxNumHighlights
;
i
++
)
{
expect
(
highlights
[
i
]).
toHaveValue
(
''
);
expect
(
highlights
[
i
]).
toHaveAttr
(
'placeholder'
,
'A highlight to look forward to this week.'
);
}
};
expectServerHandshakeWithHighlights
=
function
(
highlights
)
{
// POST to update section
AjaxHelpers
.
expectJsonRequest
(
requests
,
'POST'
,
'/xblock/mock-section'
,
{
publish
:
'republish'
,
metadata
:
{
highlights
:
highlights
}
});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
// GET updated section
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/outline/mock-section'
);
AjaxHelpers
.
respondWithJson
(
requests
,
createMockSectionJSON
({
highlights
:
highlights
}));
};
expectHighlightsToUpdate
=
function
(
originalHighlights
,
updatedHighlights
)
{
createCourseWithHighlights
(
originalHighlights
);
openHighlights
();
setHighlights
(
updatedHighlights
);
saveHighlights
();
expectServerHandshakeWithHighlights
(
updatedHighlights
);
openHighlights
();
expectHighlightsToBe
(
updatedHighlights
);
};
it
(
'does not display a link when highlights is disabled'
,
function
()
{
createCourseWithHighlightsDisabled
();
expect
(
highlightsLink
()).
toHaveLength
(
0
);
});
it
(
'displays link when no highlights exist'
,
function
()
{
createCourseWithHighlights
([]);
expectHighlightLinkTextToBe
(
'Enter Section Highlights'
);
});
it
(
'displays link when highlights exist'
,
function
()
{
var
highlights
=
mockHighlightValues
(
2
);
createCourseWithHighlights
(
highlights
);
expectHighlightLinkTextToBe
(
'Section Highlights: 2 entered'
);
});
it
(
'can view when no highlights exist'
,
function
()
{
createCourseWithHighlights
([]);
openHighlights
();
expectHighlightsToBe
([]);
});
it
(
'can view existing highlights'
,
function
()
{
var
highlights
=
mockHighlightValues
(
2
);
createCourseWithHighlights
(
highlights
);
openHighlights
();
expectHighlightsToBe
(
highlights
);
});
it
(
'can add highlights'
,
function
()
{
expectHighlightsToUpdate
(
mockHighlightValues
(
0
),
mockHighlightValues
(
1
)
);
});
it
(
'can remove highlights'
,
function
()
{
expectHighlightsToUpdate
(
mockHighlightValues
(
5
),
mockHighlightValues
(
3
)
);
});
it
(
'can edit highlights'
,
function
()
{
var
originalHighlights
=
mockHighlightValues
(
3
),
editedHighlights
=
originalHighlights
;
editedHighlights
[
2
]
=
'A New Value'
;
expectHighlightsToUpdate
(
originalHighlights
,
editedHighlights
);
});
});
describe
(
'Section'
,
function
()
{
describe
(
'Section'
,
function
()
{
var
getDisplayNameWrapper
;
var
getDisplayNameWrapper
;
...
@@ -530,7 +697,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
...
@@ -530,7 +697,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
};
};
it
(
'can be deleted'
,
function
()
{
it
(
'can be deleted'
,
function
()
{
var
promptSpy
=
EditHelpers
.
createPromptSpy
()
,
requestCount
;
var
promptSpy
=
EditHelpers
.
createPromptSpy
();
createCourseOutlinePage
(
this
,
createMockCourseJSON
({},
[
createCourseOutlinePage
(
this
,
createMockCourseJSON
({},
[
createMockSectionJSON
(),
createMockSectionJSON
(),
createMockSectionJSON
({
id
:
'mock-section-2'
,
display_name
:
'Mock Section 2'
})
createMockSectionJSON
({
id
:
'mock-section-2'
,
display_name
:
'Mock Section 2'
})
...
@@ -922,8 +1089,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
...
@@ -922,8 +1089,7 @@ define(['jquery', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers', 'common/j
])
])
]);
]);
createCourseOutlinePage
(
this
,
mockCourseJSON
,
false
);
createCourseOutlinePage
(
this
,
mockCourseJSON
,
false
);
/* global course */
setSelfPaced
();
course
.
set
(
'self_paced'
,
true
);
outlinePage
.
$
(
'.outline-subsection .configure-button'
).
click
();
outlinePage
.
$
(
'.outline-subsection .configure-button'
).
click
();
expect
(
$
(
'.edit-settings-release'
).
length
).
toBe
(
0
);
expect
(
$
(
'.edit-settings-release'
).
length
).
toBe
(
0
);
expect
(
$
(
'.grading-due-date'
).
length
).
toBe
(
0
);
expect
(
$
(
'.grading-due-date'
).
length
).
toBe
(
0
);
...
...
cms/static/js/views/course_outline.js
View file @
2211ae33
...
@@ -197,6 +197,19 @@ define(['jquery', 'underscore', 'js/views/xblock_outline', 'common/js/components
...
@@ -197,6 +197,19 @@ define(['jquery', 'underscore', 'js/views/xblock_outline', 'common/js/components
}
}
},
},
highlightsXBlock
:
function
()
{
var
modal
=
CourseOutlineModalsFactory
.
getModal
(
'highlights'
,
this
.
model
,
{
onSave
:
this
.
refresh
.
bind
(
this
),
xblockType
:
XBlockViewUtils
.
getXBlockType
(
this
.
model
.
get
(
'category'
),
this
.
parentView
.
model
,
true
)
});
if
(
modal
)
{
modal
.
show
();
}
},
addButtonActions
:
function
(
element
)
{
addButtonActions
:
function
(
element
)
{
XBlockOutlineView
.
prototype
.
addButtonActions
.
apply
(
this
,
arguments
);
XBlockOutlineView
.
prototype
.
addButtonActions
.
apply
(
this
,
arguments
);
element
.
find
(
'.configure-button'
).
click
(
function
(
event
)
{
element
.
find
(
'.configure-button'
).
click
(
function
(
event
)
{
...
@@ -207,6 +220,10 @@ define(['jquery', 'underscore', 'js/views/xblock_outline', 'common/js/components
...
@@ -207,6 +220,10 @@ define(['jquery', 'underscore', 'js/views/xblock_outline', 'common/js/components
event
.
preventDefault
();
event
.
preventDefault
();
this
.
publishXBlock
();
this
.
publishXBlock
();
}.
bind
(
this
));
}.
bind
(
this
));
element
.
find
(
'.highlights-button'
).
click
(
function
(
event
)
{
event
.
preventDefault
();
this
.
highlightsXBlock
();
}.
bind
(
this
));
},
},
makeContentDraggable
:
function
(
element
)
{
makeContentDraggable
:
function
(
element
)
{
...
...
cms/static/js/views/modals/base_modal.js
View file @
2211ae33
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
*
*
* getTitle():
* getTitle():
* returns the title for the modal.
* returns the title for the modal.
* get
HTMLContent
():
* get
ContentHtml
():
* returns the HTML content to be shown inside the modal.
* returns the HTML content to be shown inside the modal.
*
*
* A modal implementation should also provide the following options:
* A modal implementation should also provide the following options:
...
...
cms/static/js/views/modals/course_outline_modals.js
View file @
2211ae33
...
@@ -13,10 +13,11 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
...
@@ -13,10 +13,11 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
$
,
Backbone
,
_
,
gettext
,
BaseView
,
BaseModal
,
date
,
XBlockViewUtils
,
DateUtils
,
HtmlUtils
,
StringUtils
$
,
Backbone
,
_
,
gettext
,
BaseView
,
BaseModal
,
date
,
XBlockViewUtils
,
DateUtils
,
HtmlUtils
,
StringUtils
)
{
)
{
'use strict'
;
'use strict'
;
var
CourseOutlineXBlockModal
,
SettingsXBlockModal
,
PublishXBlockModal
,
AbstractEditor
,
BaseDateEditor
,
var
CourseOutlineXBlockModal
,
SettingsXBlockModal
,
PublishXBlockModal
,
HighlightsXBlockModal
,
AbstractEditor
,
BaseDateEditor
,
ReleaseDateEditor
,
DueDateEditor
,
GradingEditor
,
PublishEditor
,
AbstractVisibilityEditor
,
ReleaseDateEditor
,
DueDateEditor
,
GradingEditor
,
PublishEditor
,
AbstractVisibilityEditor
,
StaffLockEditor
,
UnitAccessEditor
,
ContentVisibilityEditor
,
TimedExaminationPreferenceEditor
,
StaffLockEditor
,
UnitAccessEditor
,
ContentVisibilityEditor
,
TimedExaminationPreferenceEditor
,
AccessEditor
,
ShowCorrectnessEditor
;
AccessEditor
,
ShowCorrectnessEditor
,
HighlightsEditor
;
CourseOutlineXBlockModal
=
BaseModal
.
extend
({
CourseOutlineXBlockModal
=
BaseModal
.
extend
({
events
:
_
.
extend
({},
BaseModal
.
prototype
.
events
,
{
events
:
_
.
extend
({},
BaseModal
.
prototype
.
events
,
{
...
@@ -206,6 +207,38 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
...
@@ -206,6 +207,38 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
}
}
});
});
HighlightsXBlockModal
=
CourseOutlineXBlockModal
.
extend
({
initialize
:
function
()
{
CourseOutlineXBlockModal
.
prototype
.
initialize
.
call
(
this
);
if
(
this
.
options
.
xblockType
)
{
this
.
options
.
modalName
=
'highlights-'
+
this
.
options
.
xblockType
;
}
},
getTitle
:
function
()
{
return
StringUtils
.
interpolate
(
gettext
(
'Highlights for {display_name}'
),
{
display_name
:
this
.
model
.
get
(
'display_name'
)}
);
},
getIntroductionMessage
:
function
()
{
return
StringUtils
.
interpolate
(
gettext
(
'The highlights you provide here are messaged (i.e., emailed) to learners. Each {item}
\'
s '
+
'highlights are emailed at the time that we expect the learner to start working on that {item}. '
+
'At this time, we assume that each {item} will take 1 week to complete.'
),
{
item
:
this
.
options
.
xblockType
}
);
},
addActionButtons
:
function
()
{
this
.
addActionButton
(
'save'
,
gettext
(
'Save'
),
true
);
this
.
addActionButton
(
'cancel'
,
gettext
(
'Cancel'
));
}
});
AbstractEditor
=
BaseView
.
extend
({
AbstractEditor
=
BaseView
.
extend
({
tagName
:
'section'
,
tagName
:
'section'
,
templateName
:
null
,
templateName
:
null
,
...
@@ -844,12 +877,58 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
...
@@ -844,12 +877,58 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
}
}
});
});
HighlightsEditor
=
AbstractEditor
.
extend
({
templateName
:
'highlights-editor'
,
className
:
'edit-show-highlights'
,
currentValue
:
function
()
{
var
highlights
=
[];
$
(
'.highlight-input-text'
).
each
(
function
()
{
var
value
=
$
(
this
).
val
();
if
(
value
!==
''
&&
value
!==
null
)
{
highlights
.
push
(
value
);
}
});
return
highlights
;
},
hasChanges
:
function
()
{
return
this
.
model
.
get
(
'highlights'
)
!==
this
.
currentValue
();
},
getRequestData
:
function
()
{
if
(
this
.
hasChanges
())
{
return
{
publish
:
'republish'
,
metadata
:
{
highlights
:
this
.
currentValue
()
}
};
}
else
{
return
{};
}
},
getContext
:
function
()
{
return
$
.
extend
(
{},
AbstractEditor
.
prototype
.
getContext
.
call
(
this
),
{
highlights
:
this
.
model
.
get
(
'highlights'
)
||
[]
}
);
}
});
return
{
return
{
getModal
:
function
(
type
,
xblockInfo
,
options
)
{
getModal
:
function
(
type
,
xblockInfo
,
options
)
{
if
(
type
===
'edit'
)
{
if
(
type
===
'edit'
)
{
return
this
.
getEditModal
(
xblockInfo
,
options
);
return
this
.
getEditModal
(
xblockInfo
,
options
);
}
else
if
(
type
===
'publish'
)
{
}
else
if
(
type
===
'publish'
)
{
return
this
.
getPublishModal
(
xblockInfo
,
options
);
return
this
.
getPublishModal
(
xblockInfo
,
options
);
}
else
if
(
type
===
'highlights'
)
{
return
this
.
getHighlightsModal
(
xblockInfo
,
options
);
}
else
{
return
null
;
}
}
},
},
...
@@ -918,6 +997,13 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
...
@@ -918,6 +997,13 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
editors
:
[
PublishEditor
],
editors
:
[
PublishEditor
],
model
:
xblockInfo
model
:
xblockInfo
},
options
));
},
options
));
},
getHighlightsModal
:
function
(
xblockInfo
,
options
)
{
return
new
HighlightsXBlockModal
(
$
.
extend
({
editors
:
[
HighlightsEditor
],
model
:
xblockInfo
},
options
));
}
}
};
};
});
});
cms/static/sass/views/_outline.scss
View file @
2211ae33
...
@@ -634,6 +634,23 @@
...
@@ -634,6 +634,23 @@
}
}
}
}
// outline: highlight settings
.highlights-button
{
cursor
:
pointer
;
color
:
$uxpl-blue-base
;
}
.highlight-input-text
{
width
:
100%
;
margin-bottom
:
5px
;
margin-top
:
5px
;
}
.highlights-description
{
font-size
:
80%
;
font-weight
:
bolder
;
}
// outline: edit item settings
// outline: edit item settings
.wrapper-modal-window-bulkpublish-section
,
.wrapper-modal-window-bulkpublish-section
,
.wrapper-modal-window-bulkpublish-subsection
,
.wrapper-modal-window-bulkpublish-subsection
,
...
...
cms/templates/course_outline.html
View file @
2211ae33
...
@@ -26,7 +26,7 @@ from openedx.core.djangolib.markup import HTML, Text
...
@@ -26,7 +26,7 @@ from openedx.core.djangolib.markup import HTML, Text
<
%
block
name=
"header_extras"
>
<
%
block
name=
"header_extras"
>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"${static.url('js/vendor/timepicker/jquery.timepicker.css')}"
/>
<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']:
% 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'
]:
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<%
static
:
include
path
=
"js/${template_name}.underscore"
/>
<%
static
:
include
path
=
"js/${template_name}.underscore"
/>
</script>
</script>
...
...
cms/templates/js/course-outline.underscore
View file @
2211ae33
...
@@ -200,6 +200,22 @@ if (is_proctored_exam) {
...
@@ -200,6 +200,22 @@ if (is_proctored_exam) {
</p>
</p>
</div>
</div>
<% } %>
<% } %>
<% if (xblockInfo.get('highlights_enabled') && course.get('self_paced') && xblockInfo.isChapter()) { %>
<div class="block-highlights">
<span class="sr block-highlights-label"><%- gettext('Highlights:') %></span>
<% var number_of_highlights = (xblockInfo.get('highlights') || []).length; %>
<% if (number_of_highlights > 0) { %>
<span class="block-highlights-value highlights-button action-button">
<%- edx.StringUtils.interpolate(
gettext('Section Highlights: {number_of_highlights} entered'),
{number_of_highlights: number_of_highlights}
) %>
</span>
<% } else { %>
<span class="block-highlights-value highlights-button action-button"><%- gettext('Enter Section Highlights') %></span>
<% } %>
</div>
<% } %>
<% if (xblockInfo.get('is_time_limited')) { %>
<% if (xblockInfo.get('is_time_limited')) { %>
<div class="status-timed-proctored-exam">
<div class="status-timed-proctored-exam">
<p>
<p>
...
...
cms/templates/js/highlights-editor.underscore
0 → 100644
View file @
2211ae33
<form>
<h3 class="modal-section-title" id="highlights_label"><%- gettext('Section Highlights') %></h3>
<div class="modal-section-content block-highlights">
<div role="group" class="list-fields" aria-labelledby="highlights_label">
<p class='field-message highlights-description' id='highlights_description'>
<%- gettext('Please enter 3-5 highlights to be sent as separate bullet points in the message.') %>
</p>
<%
var max_number_of_highlights = 5;
%>
<% _.each(highlights, function(highlight){ %>
<input
class="input input-text highlight-input-text"
type="text" maxlength="250" aria-describedby="highlights_description"
value="<%= _.escape(highlight) %>"
/>
<% }); %>
<% for (i = highlights.length; i < max_number_of_highlights; i++) { %>
<input
class="input input-text highlight-input-text"
type="text" maxlength="250" aria-describedby="highlights_description"
placeholder="<%- gettext('A highlight to look forward to this week.') %>"
/>
<% } %>
</div>
</div>
</form>
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