Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mjg/configurable hide from toc #301

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@ class XblockSerializer(StrictSerializer):
target_index = serializers.IntegerField(required=False, allow_null=True)
boilerplate = serializers.JSONField(required=False, allow_null=True)
staged_content = serializers.CharField(required=False, allow_null=True)
hide_from_toc = serializers.BooleanField(required=False, allow_null=True)
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ def create_xblock_info( # lint-amnesty, pylint: disable=too-many-statements
"group_access": xblock.group_access,
"user_partitions": user_partitions,
"show_correctness": xblock.show_correctness,
"hide_from_toc": xblock.hide_from_toc,
}
)

Expand Down Expand Up @@ -1217,6 +1218,15 @@ def create_xblock_info( # lint-amnesty, pylint: disable=too-many-statements
else:
xblock_info["staff_only_message"] = False

if xblock_info["hide_from_toc"]:
xblock_info["hide_from_toc_message"] = True
elif child_info and child_info["children"]:
xblock_info["hide_from_toc_message"] = all(
child["hide_from_toc_message"] for child in child_info["children"]
)
else:
xblock_info["hide_from_toc_message"] = False

# If the ENABLE_TAGGING_TAXONOMY_LIST_PAGE feature flag is enabled, we show the "Manage Tags" options
if use_tagging_taxonomy_list_page():
xblock_info["use_tagging_taxonomy_list_page"] = True
Expand Down Expand Up @@ -1345,6 +1355,7 @@ class VisibilityState:
needs_attention = "needs_attention"
staff_only = "staff_only"
gated = "gated"
hide_from_toc = "hide_from_toc"


def _compute_visibility_state(
Expand All @@ -1355,6 +1366,8 @@ def _compute_visibility_state(
"""
if xblock.visible_to_staff_only:
return VisibilityState.staff_only
elif xblock.hide_from_toc:
return VisibilityState.hide_from_toc
elif is_unit_with_changes:
# Note that a unit that has never been published will fall into this category,
# as well as previously published units with draft content.
Expand All @@ -1366,18 +1379,23 @@ def _compute_visibility_state(
all_staff_only = True
all_unscheduled = True
all_live = True
all_hide_from_toc = True
for child in child_info["children"]:
child_state = child["visibility_state"]
if child_state == VisibilityState.needs_attention:
return child_state
elif not child_state == VisibilityState.staff_only:
all_staff_only = False
if not child_state == VisibilityState.unscheduled:
all_unscheduled = False
if not child_state == VisibilityState.live:
all_live = False
if not child_state == VisibilityState.hide_from_toc:
all_hide_from_toc = False
if not child_state == VisibilityState.unscheduled:
all_unscheduled = False
if not child_state == VisibilityState.live:
all_live = False
if all_staff_only:
return VisibilityState.staff_only
elif all_hide_from_toc:
return VisibilityState.hide_from_toc
elif all_unscheduled:
return (
VisibilityState.unscheduled
Expand Down
8 changes: 8 additions & 0 deletions cms/static/js/models/xblock_info.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ define(
* List of tags of the unit. This list is managed by the content_tagging module.
*/
tags: null,
/**
* True if the xblock is not visible to students only via links.
*/
hide_from_toc: null,
/**
* True iff this xblock should display a "Contains staff only content" message.
*/
hide_from_toc_message: null,
},

initialize: function() {
Expand Down
28 changes: 25 additions & 3 deletions cms/static/js/views/modals/course_outline_modals.js
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,10 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
return this.model.get('ancestor_has_staff_lock');
},

isModelHiddenFromTOC: function() {
return this.model.get('hide_from_toc');
},

getContext: function() {
return {
hasExplicitStaffLock: this.isModelLocked(),
Expand All @@ -812,6 +816,7 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
afterRender: function() {
AbstractVisibilityEditor.prototype.afterRender.call(this);
this.setLock(this.isModelLocked());
this.setHideFromTOC(this.isModelHiddenFromTOC());
},

setLock: function(value) {
Expand All @@ -822,16 +827,25 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
return this.$('#staff_lock').is(':checked');
},

setHideFromTOC: function(value) {
this.$('#hide_from_toc').prop('checked', value);
},

isHiddenFromTOC: function() {
return this.$('#hide_from_toc').is(':checked');
},

hasChanges: function() {
return this.isModelLocked() !== this.isLocked();
return this.isModelLocked() !== this.isLocked() || this.isModelHiddenFromTOC() !== this.isHiddenFromTOC();
},

getRequestData: function() {
if (this.hasChanges()) {
return {
publish: 'republish',
metadata: {
visible_to_staff_only: this.isLocked() ? true : null
visible_to_staff_only: this.isLocked() ? true : null,
hide_from_toc: this.isHiddenFromTOC() ? true : null
}
};
} else {
Expand Down Expand Up @@ -1050,12 +1064,20 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
if (this.currentVisibility() === 'staff_only') {
metadata.visible_to_staff_only = true;
metadata.hide_after_due = null;
metadata.hide_from_toc = null;
} else if (this.currentVisibility() === 'hide_after_due') {
metadata.visible_to_staff_only = null;
metadata.hide_after_due = true;
} else {
metadata.hide_from_toc = null;
} else if (this.currentVisibility() === 'hide_from_toc'){
metadata.visible_to_staff_only = null;
metadata.hide_after_due = null;
metadata.hide_from_toc = true;
}
else {
metadata.visible_to_staff_only = null;
metadata.hide_after_due = null;
metadata.hide_from_toc = null;
}

return {
Expand Down
1 change: 1 addition & 0 deletions cms/static/js/views/pages/container_subviews.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ function($, _, gettext, BaseView, ViewUtils, XBlockViewUtils, MoveXBlockUtils, H
releaseDate: this.model.get('release_date'),
releaseDateFrom: this.model.get('release_date_from'),
hasExplicitStaffLock: this.model.get('has_explicit_staff_lock'),
hideFromTOC: this.model.get('hide_from_toc'),
staffLockFrom: this.model.get('staff_lock_from'),
enableCopyUnit: this.model.get('enable_copy_paste_units'),
course: window.course,
Expand Down
8 changes: 7 additions & 1 deletion cms/static/js/views/utils/xblock_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ function($, _, gettext, ViewUtils, ModuleUtils, XBlockInfo, StringUtils) {
*
* 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.
*
* hideFromTOC - all of the block's content is to be hidden from the table of contents.
*/
VisibilityState = {
live: 'live',
ready: 'ready',
unscheduled: 'unscheduled',
needsAttention: 'needs_attention',
staffOnly: 'staff_only',
gated: 'gated'
gated: 'gated',
hideFromTOC: 'hide_from_toc'
};

/**
Expand Down Expand Up @@ -310,6 +313,9 @@ function($, _, gettext, ViewUtils, ModuleUtils, XBlockInfo, StringUtils) {
if (visibilityState === VisibilityState.staffOnly) {
return 'is-staff-only';
}
if (visibilityState === VisibilityState.hideFromTOC) {
return 'is-hidden-from-toc';
}
if (visibilityState === VisibilityState.gated) {
return 'is-gated';
}
Expand Down
1 change: 1 addition & 0 deletions cms/static/js/views/xblock_outline.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ function($, _, gettext, BaseView, ViewUtils, XBlockViewUtils, XBlockStringFieldE
includesChildren: this.shouldRenderChildren(),
hasExplicitStaffLock: this.model.get('has_explicit_staff_lock'),
staffOnlyMessage: this.model.get('staff_only_message'),
hideFromTOCMessage: this.model.get('hide_from_toc_message'),
course: course,
enableCopyPasteUnits: this.model.get("enable_copy_paste_units"), // ENABLE_COPY_PASTE_UNITS waffle flag
useTaggingTaxonomyListPage: this.model.get("use_tagging_taxonomy_list_page"), // ENABLE_TAGGING_TAXONOMY_LIST_PAGE waffle flag
Expand Down
22 changes: 22 additions & 0 deletions cms/static/sass/elements/_modules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,18 @@ $outline-indent-width: $baseline;
}
}

// CASE: is hidden from TOC
&.is-hidden-from-toc {
// needed to make sure direct children only
> .section-status,
> .subsection-status,
> .unit-status {
.status-message .icon {
color: $color-hide-from-toc;
}
}
}

// CASE: has gated content
&.is-gated {

Expand Down Expand Up @@ -603,6 +615,11 @@ $outline-indent-width: $baseline;
border-left-color: $color-staff-only;
}

// CASE: is hidden from TOC
&.is-hidden-from-toc {
border-left-color: $color-hide-from-toc;
}

// CASE: has gated content
&.is-gated {
border-left-color: $color-gated;
Expand Down Expand Up @@ -698,6 +715,11 @@ $outline-indent-width: $baseline;
border-left-color: $color-staff-only;
}

// CASE: is hidden from TOC
&.is-hidden-from-toc {
border-left-color: $color-hide-from-toc;
}

// CASE: is presented for gated
&.is-gated {
border-left-color: $color-gated;
Expand Down
1 change: 1 addition & 0 deletions cms/static/sass/partials/cms/theme/_variables-v1.scss
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ $color-ready: $green !default;
$color-warning: $orange-l2 !default;
$color-error: $red-l2 !default;
$color-staff-only: $black !default;
$color-hide-from-toc: $black !default;
$color-gated: $black !default;

$color-heading-base: $gray-d2 !default;
Expand Down
9 changes: 9 additions & 0 deletions cms/static/sass/views/_container.scss
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,15 @@
}
}

// CASE: is hidden from TOC
&.is-hidden-from-toc{
@extend %bar-module-black;

&.is-scheduled .wrapper-release .copy {
text-decoration: line-through;
}
}

// CASE: content is gated
&.is-gated {
@extend %bar-module-black;
Expand Down
13 changes: 12 additions & 1 deletion cms/templates/js/course-outline.underscore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ var addStatusMessage = function (statusType, message) {
statusIconClass = 'fa-warning';
} else if (statusType === 'staff-only' || statusType === 'gated') {
statusIconClass = 'fa-lock';
} else if (statusType === 'partition-groups') {
} else if(statusType === 'hide-from-toc') {
statusIconClass = 'fa-eye-slash';
}
else if (statusType === 'partition-groups') {
statusIconClass = 'fa-eye';
}

Expand All @@ -48,6 +51,14 @@ if (staffOnlyMessage) {
messageType = 'staff-only';
messageText = gettext('Contains staff only content');
addStatusMessage(messageType, messageText);
} else if (hideFromTOCMessage && !xblockInfo.isVertical()){
if (xblockInfo.isChapter()) {
messageText = gettext('Hidden in the course outline, but sections are accessible for your learners through their separate link.');
} else {
messageText = gettext('Subsections are not navigable between each other, they can only be accessed through their link.');
}
messageType = 'hide-from-toc';
addStatusMessage(messageType, messageText);
} else {
if (visibilityState === 'needs_attention' && xblockInfo.isVertical()) {
messageType = 'warning';
Expand Down
11 changes: 11 additions & 0 deletions cms/templates/js/staff-lock-editor.underscore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,15 @@
</p>
<% } %>
</div>
<div class="modal-section-content hide-from-toc">
<% if (!xblockInfo.isVertical()) { %>
<label class="label">
<input type="checkbox" id="hide_from_toc" name="hide_from_toc" class="input input-checkbox" />
<%- gettext('Hide in Course Outline, accessible via Link') %>
<p class="tip tip-inline">
<%- gettext('It is intentionally hidden from standard navigation, ensuring that only individuals witht he link can view its contents.') %>
</p>
</label>
<% } %>
</div>
</form>
7 changes: 7 additions & 0 deletions xmodule/modulestore/inheritance.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,13 @@ class InheritanceMixin(XBlockMixin):
scope=Scope.settings
)

hide_from_toc = Boolean(
display_name=_("Hide from Table of Contents"),
help=_("Enter true or false. If true, this block will be hidden from the Table of Contents."),
default=False,
scope=Scope.settings
)

@property
def close_date(self):
"""
Expand Down
Loading