MDL-44070 Conditional availability enhancements (8): display

Includes theme and renderer changes required for the new feature.
There are two parts: style required for the display as part of the
course page (when showing the list of conditions for an activity),
and style required for the settings form.

This change supports both the bootstrapbase theme (which was the
main theme used during development) and the old base theme.
This commit is contained in:
sam marshall 2014-03-26 13:24:58 +00:00
parent 400c0fd229
commit 00c832d7a1
5 changed files with 343 additions and 39 deletions

View file

@ -428,20 +428,18 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
global $CFG; global $CFG;
$o = ''; $o = '';
if (!$section->uservisible) { if (!$section->uservisible) {
$o .= html_writer::start_tag('div', array('class' => 'availabilityinfo'));
// Note: We only get to this function if availableinfo is non-empty, // Note: We only get to this function if availableinfo is non-empty,
// so there is definitely something to print. // so there is definitely something to print.
$o .= $section->availableinfo; $formattedinfo = \core_availability\info::format_info(
$o .= html_writer::end_tag('div'); $section->availableinfo, $section->course);
$o .= html_writer::div($formattedinfo, 'availabilityinfo');
} else if ($canviewhidden && !empty($CFG->enableavailability) && $section->visible) { } else if ($canviewhidden && !empty($CFG->enableavailability) && $section->visible) {
$ci = new condition_info_section($section); $ci = new \core_availability\info_section($section);
$fullinfo = $ci->get_full_information(); $fullinfo = $ci->get_full_information();
if ($fullinfo) { if ($fullinfo) {
$o .= html_writer::start_tag('div', array('class' => 'availabilityinfo')); $formattedinfo = \core_availability\info::format_info(
$o .= get_string( $fullinfo, $section->course);
($section->showavailability ? 'userrestriction_visible' : 'userrestriction_hidden'), $o .= html_writer::div($formattedinfo, 'availabilityinfo');
'condition', $fullinfo);
$o .= html_writer::end_tag('div');
} }
} }
return $o; return $o;
@ -737,13 +735,14 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
continue; continue;
} }
// Show the section if the user is permitted to access it, OR if it's not available // Show the section if the user is permitted to access it, OR if it's not available
// but showavailability is turned on (and there is some available info text). // but there is some available info text which explains the reason & should display.
$showsection = $thissection->uservisible || $showsection = $thissection->uservisible ||
($thissection->visible && !$thissection->available && $thissection->showavailability ($thissection->visible && !$thissection->available &&
&& !empty($thissection->availableinfo)); !empty($thissection->availableinfo));
if (!$showsection) { if (!$showsection) {
// Hidden section message is overridden by 'unavailable' control // If the hiddensections option is set to 'show hidden sections in collapsed
// (showavailability option). // form', then display the hidden section message - UNLESS the section is
// hidden by the availability system, which is set to hide the reason.
if (!$course->hiddensections && $thissection->available) { if (!$course->hiddensections && $thissection->available) {
echo $this->section_hidden($section); echo $this->section_hidden($section);
} }

View file

@ -665,7 +665,7 @@ class core_course_renderer extends plugin_renderer_base {
// off the JS. // off the JS.
$extraclass = ''; $extraclass = '';
if (!empty($CFG->enableavailability) && if (!empty($CFG->enableavailability) &&
condition_info::completion_value_used_as_condition($course, $mod)) { core_availability\info::completion_value_used($course, $mod->id)) {
$extraclass = ' preventjs'; $extraclass = ' preventjs';
} }
$output .= html_writer::start_tag('form', array('method' => 'post', $output .= html_writer::start_tag('form', array('method' => 'post',
@ -711,11 +711,8 @@ class core_course_renderer extends plugin_renderer_base {
global $CFG; global $CFG;
$conditionalhidden = false; $conditionalhidden = false;
if (!empty($CFG->enableavailability)) { if (!empty($CFG->enableavailability)) {
$conditionalhidden = $mod->availablefrom > time() || $info = new \core_availability\info_module($mod);
($mod->availableuntil && $mod->availableuntil < time()) || $conditionalhidden = !$info->is_available_for_all();
count($mod->conditionsgrade) > 0 ||
count($mod->conditionscompletion) > 0 ||
count($mod->conditionsfield);
} }
return $conditionalhidden; return $conditionalhidden;
} }
@ -736,8 +733,7 @@ class core_course_renderer extends plugin_renderer_base {
public function course_section_cm_name(cm_info $mod, $displayoptions = array()) { public function course_section_cm_name(cm_info $mod, $displayoptions = array()) {
global $CFG; global $CFG;
$output = ''; $output = '';
if (!$mod->uservisible && if (!$mod->uservisible && empty($mod->availableinfo)) {
(empty($mod->showavailability) || empty($mod->availableinfo))) {
// nothing to be displayed to the user // nothing to be displayed to the user
return $output; return $output;
} }
@ -825,8 +821,7 @@ class core_course_renderer extends plugin_renderer_base {
*/ */
public function course_section_cm_text(cm_info $mod, $displayoptions = array()) { public function course_section_cm_text(cm_info $mod, $displayoptions = array()) {
$output = ''; $output = '';
if (!$mod->uservisible && if (!$mod->uservisible && empty($mod->availableinfo)) {
(empty($mod->showavailability) || empty($mod->availableinfo))) {
// nothing to be displayed to the user // nothing to be displayed to the user
return $output; return $output;
} }
@ -876,8 +871,10 @@ class core_course_renderer extends plugin_renderer_base {
if (!$mod->uservisible) { if (!$mod->uservisible) {
// this is a student who is not allowed to see the module but might be allowed // this is a student who is not allowed to see the module but might be allowed
// to see availability info (i.e. "Available from ...") // to see availability info (i.e. "Available from ...")
if (!empty($mod->showavailability) && !empty($mod->availableinfo)) { if (!empty($mod->availableinfo)) {
$output = html_writer::tag('div', $mod->availableinfo, array('class' => 'availabilityinfo')); $formattedinfo = \core_availability\info::format_info(
$mod->availableinfo, $mod->get_course());
$output = html_writer::tag('div', $formattedinfo, array('class' => 'availabilityinfo'));
} }
return $output; return $output;
} }
@ -892,13 +889,12 @@ class core_course_renderer extends plugin_renderer_base {
if (!$mod->visible) { if (!$mod->visible) {
$hidinfoclass = 'hide'; $hidinfoclass = 'hide';
} }
$ci = new condition_info($mod); $ci = new \core_availability\info_module($mod);
$fullinfo = $ci->get_full_information(); $fullinfo = $ci->get_full_information();
if($fullinfo) { if ($fullinfo) {
return '<div class="availabilityinfo '.$hidinfoclass.'">'.get_string($mod->showavailability $formattedinfo = \core_availability\info::format_info(
? 'userrestriction_visible' $fullinfo, $mod->get_course());
: 'userrestriction_hidden','condition', return html_writer::div($formattedinfo, 'availabilityinfo ' . $hidinfoclass);
$fullinfo).'</div>';
} }
} }
} }
@ -954,15 +950,10 @@ class core_course_renderer extends plugin_renderer_base {
// if: // if:
// 1) The activity is not visible to users // 1) The activity is not visible to users
// and // and
// 2a) The 'showavailability' option is not set (if that is set, // 2) The 'availableinfo' is empty, i.e. the activity was
// we need to display the activity so we can show
// availability info)
// or
// 2b) The 'availableinfo' is empty, i.e. the activity was
// hidden in a way that leaves no info, such as using the // hidden in a way that leaves no info, such as using the
// eye icon. // eye icon.
if (!$mod->uservisible && if (!$mod->uservisible && empty($mod->availableinfo)) {
(empty($mod->showavailability) || empty($mod->availableinfo))) {
return $output; return $output;
} }

View file

@ -638,6 +638,163 @@ body.tag .managelink {padding: 5px;}
.path-backup .backup_log h2 { font-size: 1em; } .path-backup .backup_log h2 { font-size: 1em; }
.path-backup .backup_log_contents { border: 1px solid #ddd; padding: 10px; height: 300px; overflow-y: scroll; } .path-backup .backup_log_contents { border: 1px solid #ddd; padding: 10px; height: 300px; overflow-y: scroll; }
/*
* CSS for availability options on module and section. This is taken from the
* Bootstrap version and tweaked so it works on base.
*/
#fitem_id_availabilityconditionsjson .label {
background: #999;
padding: 2px 4px;
border-radius: 4px;
font-size: 0.8em;
font-weight: bold;
color: #fff;
}
#fitem_id_availabilityconditionsjson .label-warning {
background: #f89406;
position:relative;
top: -1px;
}
#fitem_id_availabilityconditionsjson .label:empty {
display: none;
}
#fitem_id_availabilityconditionsjson *[aria-hidden=true] {
display: none;
}
x#fitem_id_availabilityconditionsjson select,
x#fitem_id_availabilityconditionsjson input[type=text] {
position:relative;
top: 4px;
}
#fitem_id_availabilityconditionsjson label {
display: inline;
}
#fitem_id_availabilityconditionsjson .availability-group {
margin-right: 8px;
}
.dir-rtl #fitem_id_availabilityconditionsjson .availability-group {
margin-right: 0;
margin-left: 8px;
}
#fitem_id_availabilityconditionsjson .availability-item,
#fitem_id_availabilityconditionsjson .availability-header {
margin-bottom: 6px;
}
#fitem_id_availabilityconditionsjson .availability-none {
margin-left: 20px;
margin-bottom: 4px;
}
.dir-rtl #fitem_id_availabilityconditionsjson .availability-none {
margin-right: 20px;
margin-left: 0;
}
#fitem_id_availabilityconditionsjson .availability-plugincontrols {
padding: 4px 0px 4px 4px;
background: none repeat scroll 0% 0% #eee;
border: 1px solid #ddd;
border-radius: 4px;
display: inline-block;
margin-right: 8px;
}
.dir-rtl #fitem_id_availabilityconditionsjson .availability-plugincontrols {
padding-right: 4px;
padding-left: 0px;
margin-right: 0;
margin-left: 8px;
}
#fitem_id_availabilityconditionsjson .availability-eye,
#fitem_id_availabilityconditionsjson .availability-delete {
margin-right: 8px;
}
.dir-rtl #fitem_id_availabilityconditionsjson .availability-eye,
.dir-rtl #fitem_id_availabilityconditionsjson .availability-delete {
margin-left: 8px;
margin-right: 0;
}
#fitem_id_availabilityconditionsjson .availability-eye[aria-hidden=true] {
display: inline;
visibility: hidden;
}
#fitem_id_availabilityconditionsjson .availability-list > .availability-eye img {
vertical-align: top;
margin-top: 12px;
}
#fitem_id_availabilityconditionsjson .availability-button {
margin-left: 15px;
}
.dir-rtl #fitem_id_availabilityconditionsjson .availability-button {
margin-right: 15px;
margin-left: 0;
}
#fitem_id_availabilityconditionsjson .availability-childlist > .availability-inner {
display: inline-block;
background: #eee;
border: 1px solid #ddd;
border-radius: 4px;
padding: 6px;
margin-bottom: 6px;
}
#fitem_id_availabilityconditionsjson .availability-childlist .availability-childlist > .availability-inner {
background: white;
}
#fitem_id_availabilityconditionsjson .availability-connector {
margin-left: 20px;
margin-bottom: 6px;
}
.dir-rtl #fitem_id_availabilityconditionsjson .availability-connector {
margin-right: 20px;
margin-left: 0;
}
.mform .error .availability-field {
color: black;
}
.availability-dialogue.moodle-dialogue-base .moodle-dialogue .moodle-dialogue-bd {
padding-left: 0;
padding-right: 0;
padding-bottom: 2px;
}
.availability-dialogue ul {
display: block;
margin: 0;
}
.availability-dialogue li {
display: block;
list-style-type: none;
padding: 0 0 4px;
clear: both;
border-bottom: 1px solid #eee;
margin-bottom: 4px;
}
.availability-dialogue ul button {
float: left;
margin-left: 1em;
min-width: 140px;
margin-top: 4px;
}
.dir-rtl .availability-dialogue ul button {
float: right;
margin-right: 1em;
margin-left: 0;
}
.availability-dialogue label {
margin-left: 170px;
margin-right: 1em;
margin-bottom: 0;
display: block;
line-height: 1.5;
}
.dir-rtl .availability-dialogue label {
margin-right: 170px;
margin-left: 1em;
}
.availability-dialogue .availability-buttons button {
margin-left: 1em;
margin-right: 1em;
margin-top: 4px;
}
/** /**
* Web Service * Web Service
*/ */

View file

@ -171,6 +171,9 @@
.dir-rtl .sitetopic .section .activity .contentafterlink, .dir-rtl .sitetopic .section .activity .contentafterlink,
.dir-rtl .course-content .section .activity .availabilityinfo, .dir-rtl .course-content .section .activity .availabilityinfo,
.dir-rtl .course-content .section .activity .contentafterlink { margin-left: 0; margin-right: 30px;} .dir-rtl .course-content .section .activity .contentafterlink { margin-left: 0; margin-right: 30px;}
.availabilityinfo > ul {
margin-top: 0;
}
.section .activity .contentafterlink p { margin:.5em 0; } .section .activity .contentafterlink p { margin:.5em 0; }
.sitetopic .section .activity:hover, .sitetopic .section .activity:hover,
.course-content .section .activity:hover { background-color: #EEE; } .course-content .section .activity:hover { background-color: #EEE; }

View file

@ -455,3 +455,157 @@ fieldset.coursesearchbox label {
} }
} }
} }
/* Section and module editing forms contain special JS components for the
availability system (if enabled). */
#fitem_id_availabilityconditionsjson {
*[aria-hidden=true] {
display: none;
}
select,
input[type=text] {
position:relative;
top: 4px;
}
label {
display: inline;
}
.availability-group {
margin-right: 8px;
}
.availability-item {
margin-bottom: 6px;
}
.availability-none {
margin-left: 20px;
margin-bottom: 4px;
}
.availability-plugincontrols {
padding: 2px 0px 0px 4px;
background: none repeat scroll 0% 0% @wellBackground;
border: 1px solid @grayLighter;
border-radius: 4px;
display: inline-block;
margin-right: 8px;
}
/* Eye icon in front of an item and delete icon after it. */
.availability-eye,
.availability-delete {
margin-right: 8px;
}
/* Hidden eye icon still takes up space. */
.availability-eye[aria-hidden=true] {
display: inline;
visibility: hidden;
}
/* Eye icons in front of child lists are aligned specially. */
.availability-list > .availability-eye img {
vertical-align: top;
margin-top: 12px;
}
/* Add button lines up with child elements. */
.availability-button {
margin-left: 15px;
}
/* Nested section is grey. */
.availability-childlist > .availability-inner {
display: inline-block;
background: @wellBackground;
border: 1px solid @grayLighter;
border-radius: 4px;
padding: 6px;
margin-bottom: 6px;
}
/* Second (and more) levels of nested sections are white. */
.availability-childlist .availability-childlist > .availability-inner {
background: white;
}
/* Connecting text needs to be indented. */
.availability-connector {
margin-left: 20px;
margin-bottom: 6px;
}
}
.dir-rtl #fitem_id_availabilityconditionsjson {
.availability-group {
margin-right: 0;
margin-left: 8px;
}
.availability-none {
margin-right: 20px;
margin-left: 0;
}
.availability-plugincontrols {
padding-right: 4px;
padding-left: 0px;
margin-right: 0;
margin-left: 8px;
}
.availability-eye,
.availability-delete {
margin-left: 8px;
margin-right: 0;
}
.availability-button {
margin-right: 15px;
margin-left: 0;
}
.availability-connector {
margin-right: 20px;
margin-left: 0;
}
}
/* Default form styling colours all text red. With availability conditions
this looks excessive as we show 'Invalid' markers in specific places. */
.mform .error .availability-field {
color: @textColor;
}
/* This dialogue is used to add an availability condition. */
.availability-dialogue {
.moodle-dialogue .moodle-dialogue-bd {
padding-left: 0;
padding-right: 0;
padding-bottom: 2px;
}
ul {
display: block;
margin: 0;
}
li {
display: block;
list-style-type: none;
padding: 0 0 4px;
clear: both;
border-bottom: 1px solid @grayLighter;
margin-bottom: 4px;
}
ul button {
float: left;
margin-left: 1em;
min-width: 140px;
margin-top: 4px;
}
label {
margin-left: 170px;
margin-right: 1em;
margin-bottom: 0;
}
.availability-buttons button {
margin-left: 1em;
margin-right: 1em;
margin-top: 4px;
}
}
.dir-rtl .availability-dialogue {
ul button {
float: right;
margin-right: 1em;
margin-left: 0;
}
label {
margin-right: 170px;
margin-left: 1em;
}
}