MDL-48947 course: Section button cleanup

Creates a new method of handling all the section related icons.
Including a new method that places these actions in a menu for topic and
weeks course formats. (This version replaces "Edit" with "Topic/Week/or
Section menu")
This commit is contained in:
Syxton 2015-09-17 10:40:31 -04:00
parent cd3a6a78b6
commit 60cf074239
29 changed files with 512 additions and 126 deletions

View File

@ -86,6 +86,46 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
return $title;
}
/**
* Generate the edit control action menu
*
* @param array $controls The edit control items from section_edit_control_items
* @param stdClass $course The course entry from DB
* @param stdClass $section The course_section entry from DB
* @return string HTML to output.
*/
protected function section_edit_control_menu($controls, $course, $section) {
$o = "";
if (!empty($controls)) {
$menu = new action_menu();
if ($section->section && get_string_manager()->string_exists('sectionmenu', 'format_'.$course->format)) {
$menu->set_menu_trigger(get_string('sectionmenu', 'format_'.$course->format));
} else {
$menu->set_menu_trigger(get_string('sectionmenu'));
}
$menu->attributes['class'] .= ' section-actions';
foreach ($controls as $value) {
$url = empty($value['url']) ? '' : $value['url'];
$icon = empty($value['icon']) ? '' : $value['icon'];
$name = empty($value['name']) ? '' : $value['name'];
$attr = empty($value['attr']) ? '' : $value['attr'];
$class = empty($item['pixattr']['class']) ? '' : $item['pixattr']['class'];
$alt = empty($item['pixattr']['alt']) ? '' : $item['pixattr']['alt'];
$al = new action_menu_link_secondary(
new moodle_url($url),
new pix_icon($icon, $name, null, array('class' => "smallicon " . $class, 'alt' => $alt)),
$name,
$attr
);
$menu->add($al);
}
$o .= html_writer::div($this->render($menu), 'section_action_menu');
}
return $o;
}
/**
* Generate the content to displayed on the right part of a section
* before course modules are included
@ -98,12 +138,8 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
protected function section_right_content($section, $course, $onsectionpage) {
$o = $this->output->spacer();
if ($section->section != 0) {
$controls = $this->section_edit_controls($course, $section, $onsectionpage);
if (!empty($controls)) {
$o = implode('<br />', $controls);
}
}
$controls = $this->section_edit_control_items($course, $section, $onsectionpage);
$o .= $this->section_edit_control_menu($controls, $course, $section);
return $o;
}
@ -160,6 +196,9 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
'class' => 'section main clearfix'.$sectionstyle, 'role'=>'region',
'aria-label'=> get_section_name($course, $section)));
// Create a span that contains the section title to be used to create the keyboard section move menu.
$o .= html_writer::tag('span', $this->section_title($section, $course), array('class' => 'hidden sectionname'));
$leftcontent = $this->section_left_content($section, $course, $onsectionpage);
$o.= html_writer::tag('div', $leftcontent, array('class' => 'left side'));
@ -181,17 +220,9 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
$o.= html_writer::start_tag('div', array('class' => 'summary'));
$o.= $this->format_summary_text($section);
$context = context_course::instance($course->id);
if ($PAGE->user_is_editing() && has_capability('moodle/course:update', $context)) {
$url = new moodle_url('/course/editsection.php', array('id'=>$section->id, 'sr'=>$sectionreturn));
$o.= html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/settings'),
'class' => 'iconsmall edit', 'alt' => get_string('edit'))),
array('title' => get_string('editsummary')));
}
$o.= html_writer::end_tag('div');
$context = context_course::instance($course->id);
$o .= $this->section_availability_message($section,
has_capability('moodle/course:viewhiddensections', $context));
@ -217,6 +248,8 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
* @param stdClass $section The course_section entry from DB
* @param bool $onsectionpage true if being printed on a section page
* @return array of links with edit controls
* @deprecated since Moodle 3.0 MDL-48947 - please do not use this function any more.
* @see format_section_renderer_base::section_edit_control_items()
*/
protected function section_edit_controls($course, $section, $onsectionpage = false) {
global $PAGE;
@ -225,6 +258,45 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
return array();
}
$controls = array();
$items = $this->section_edit_control_items($course, $section, $onsectionpage);
foreach ($items as $key => $item) {
$url = empty($item['url']) ? '' : $item['url'];
$icon = empty($item['icon']) ? '' : $item['icon'];
$name = empty($item['name']) ? '' : $item['name'];
$attr = empty($item['attr']) ? '' : $item['attr'];
$class = empty($item['pixattr']['class']) ? '' : $item['pixattr']['class'];
$alt = empty($item['pixattr']['alt']) ? '' : $item['pixattr']['alt'];
$controls[$key] = html_writer::link(
new moodle_url($url),
html_writer::empty_tag('img', array(
'src' => $this->output->pix_url($icon),
'class' => "icon " . $class,
'alt' => $alt
)),
$attr);
}
debugging('section_edit_controls() is deprecated, please use section_edit_control_items() instead.', DEBUG_DEVELOPER);
return $controls;
}
/**
* Generate the edit control items of a section
*
* @param stdClass $course The course entry from DB
* @param stdClass $section The course_section entry from DB
* @param bool $onsectionpage true if being printed on a section page
* @return array of edit control items
*/
protected function section_edit_control_items($course, $section, $onsectionpage = false) {
global $PAGE;
if (!$PAGE->user_is_editing()) {
return array();
}
$coursecontext = context_course::instance($course->id);
$isstealth = isset($course->numsections) && ($section->section > $course->numsections);
@ -237,62 +309,94 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
$controls = array();
$url = clone($baseurl);
if (!$isstealth && has_capability('moodle/course:sectionvisibility', $coursecontext)) {
if ($section->visible) { // Show the hide/show eye.
$strhidefromothers = get_string('hidefromothers', 'format_'.$course->format);
$url->param('hide', $section->section);
$controls[] = html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/hide'),
'class' => 'icon hide', 'alt' => $strhidefromothers)),
array('title' => $strhidefromothers, 'class' => 'editing_showhide'));
if (!$isstealth && has_capability('moodle/course:update', $coursecontext)) {
if ($section->section > 0
&& get_string_manager()->string_exists('editsection', 'format_'.$course->format)) {
$streditsection = get_string('editsection', 'format_'.$course->format);
} else {
$strshowfromothers = get_string('showfromothers', 'format_'.$course->format);
$url->param('show', $section->section);
$controls[] = html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/show'),
'class' => 'icon hide', 'alt' => $strshowfromothers)),
array('title' => $strshowfromothers, 'class' => 'editing_showhide'));
$streditsection = get_string('editsection');
}
$controls['edit'] = array(
'url' => new moodle_url('/course/editsection.php', array('id' => $section->id, 'sr' => $onsectionpage)),
'icon' => 'i/settings',
'name' => $streditsection,
'pixattr' => array('class' => '', 'alt' => $streditsection),
'attr' => array('class' => 'icon edit', 'title' => $streditsection));
}
if (course_can_delete_section($course, $section)) {
if (get_string_manager()->string_exists('deletesection', 'format_'.$course->format)) {
$strdelete = get_string('deletesection', 'format_'.$course->format);
} else {
$strdelete = get_string('deletesection');
}
$url = new moodle_url('/course/editsection.php', array('id' => $section->id,
'sr' => $onsectionpage ? $section->section : 0, 'delete' => 1));
$controls[] = html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('t/delete'),
'class' => 'icon delete', 'alt' => $strdelete)),
array('title' => $strdelete));
}
if (!$isstealth && !$onsectionpage && has_capability('moodle/course:movesections', $coursecontext)) {
if ($section->section) {
$url = clone($baseurl);
if ($section->section > 1) { // Add a arrow to move section up.
$url->param('section', $section->section);
$url->param('move', -1);
$strmoveup = get_string('moveup');
if (!$isstealth) {
if (has_capability('moodle/course:sectionvisibility', $coursecontext)) {
if ($section->visible) { // Show the hide/show eye.
$strhidefromothers = get_string('hidefromothers', 'format_'.$course->format);
$url->param('hide', $section->section);
$controls['visiblity'] = array(
'url' => $url,
'icon' => 'i/hide',
'name' => $strhidefromothers,
'pixattr' => array('class' => '', 'alt' => $strhidefromothers),
'attr' => array('class' => 'icon editing_showhide', 'title' => $strhidefromothers));
} else {
$strshowfromothers = get_string('showfromothers', 'format_'.$course->format);
$url->param('show', $section->section);
$controls['visiblity'] = array(
'url' => $url,
'icon' => 'i/show',
'name' => $strshowfromothers,
'pixattr' => array('class' => '', 'alt' => $strshowfromothers),
'attr' => array('class' => 'icon editing_showhide', 'title' => $strshowfromothers));
}
}
$controls[] = html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/up'),
'class' => 'icon up', 'alt' => $strmoveup)),
array('title' => $strmoveup, 'class' => 'moveup'));
if (!$onsectionpage) {
if (has_capability('moodle/course:movesections', $coursecontext)) {
$url = clone($baseurl);
if ($section->section > 1) { // Add a arrow to move section up.
$url->param('section', $section->section);
$url->param('move', -1);
$strmoveup = get_string('moveup');
$controls['moveup'] = array(
'url' => $url,
'icon' => 'i/up',
'name' => $strmoveup,
'pixattr' => array('class' => '', 'alt' => $strmoveup),
'attr' => array('class' => 'icon moveup', 'title' => $strmoveup));
}
$url = clone($baseurl);
if ($section->section < $course->numsections) { // Add a arrow to move section down.
$url->param('section', $section->section);
$url->param('move', 1);
$strmovedown = get_string('movedown');
$controls['movedown'] = array(
'url' => $url,
'icon' => 'i/down',
'name' => $strmovedown,
'pixattr' => array('class' => '', 'alt' => $strmovedown),
'attr' => array('class' => 'icon movedown', 'title' => $strmovedown));
}
}
}
}
$url = clone($baseurl);
if ($section->section < $course->numsections) { // Add a arrow to move section down.
$url->param('section', $section->section);
$url->param('move', 1);
$strmovedown = get_string('movedown');
$controls[] = html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/down'),
'class' => 'icon down', 'alt' => $strmovedown)),
array('title' => $strmovedown, 'class' => 'movedown'));
if (course_can_delete_section($course, $section)) {
if (get_string_manager()->string_exists('deletesection', 'format_'.$course->format)) {
$strdelete = get_string('deletesection', 'format_'.$course->format);
} else {
$strdelete = get_string('deletesection');
}
$url = new moodle_url('/course/editsection.php', array(
'id' => $section->id,
'sr' => $onsectionpage ? $section->section : 0,
'delete' => 1));
$controls['delete'] = array(
'url' => $url,
'icon' => 'i/delete',
'name' => $strdelete,
'pixattr' => array('class' => '', 'alt' => $strdelete),
'attr' => array('class' => 'icon delete', 'title' => $strdelete));
}
}

View File

@ -74,7 +74,7 @@ M.course.format.process_sections = function(Y, sectionlist, response, sectionfro
for (var i = sectionfrom; i <= sectionto; i++) {
// Update section title.
sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
sectionlist.item(i).all('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
// Update move icon.
ele = sectionlist.item(i).one(SELECTORS.SECTIONLEFTSIDE);
str = ele.getAttribute('alt');

View File

@ -24,9 +24,11 @@
*/
$string['currentsection'] = 'This topic';
$string['editsection'] = 'Edit topic';
$string['deletesection'] = 'Delete topic';
$string['sectionname'] = 'Topic';
$string['pluginname'] = 'Topics format';
$string['sectionmenu'] = 'Topic menu';
$string['section0name'] = 'General';
$string['page-course-view-topics'] = 'Any course main page in topics format';
$string['page-course-view-topics-x'] = 'Any course page in topics format';

View File

@ -74,14 +74,14 @@ class format_topics_renderer extends format_section_renderer_base {
}
/**
* Generate the edit controls of a section
* Generate the edit control items of a section
*
* @param stdClass $course The course entry from DB
* @param stdClass $section The course_section entry from DB
* @param bool $onsectionpage true if being printed on a section page
* @return array of links with edit controls
* @return array of edit control items
*/
protected function section_edit_controls($course, $section, $onsectionpage = false) {
protected function section_edit_control_items($course, $section, $onsectionpage = false) {
global $PAGE;
if (!$PAGE->user_is_editing()) {
@ -99,22 +99,26 @@ class format_topics_renderer extends format_section_renderer_base {
$isstealth = $section->section > $course->numsections;
$controls = array();
if (!$isstealth && has_capability('moodle/course:setcurrentsection', $coursecontext)) {
if (!$isstealth && $section->section && has_capability('moodle/course:setcurrentsection', $coursecontext)) {
if ($course->marker == $section->section) { // Show the "light globe" on/off.
$url->param('marker', 0);
$controls[] = html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/marked'),
'class' => 'icon ', 'alt' => get_string('markedthistopic'))),
array('title' => get_string('markedthistopic'), 'class' => 'editing_highlight'));
$markedthistopic = get_string('markedthistopic');
$highlightoff = get_string('highlightoff');
$controls[] = array("url" => $url, "icon" => 'i/marked',
"name" => $highlightoff,
'pixattr' => array('class' => '', 'alt' => $markedthistopic),
"attr" => array('class' => 'editing_highlight', 'title' => $markedthistopic));
} else {
$url->param('marker', $section->section);
$controls[] = html_writer::link($url,
html_writer::empty_tag('img', array('src' => $this->output->pix_url('i/marker'),
'class' => 'icon', 'alt' => get_string('markthistopic'))),
array('title' => get_string('markthistopic'), 'class' => 'editing_highlight'));
$markthistopic = get_string('markthistopic');
$highlight = get_string('highlight');
$controls[] = array("url" => $url, "icon" => 'i/marker',
"name" => $highlight,
'pixattr' => array('class' => '', 'alt' => $markthistopic),
"attr" => array('class' => 'editing_highlight', 'title' => $markthistopic));
}
}
return array_merge($controls, parent::section_edit_controls($course, $section, $onsectionpage));
return array_merge($controls, parent::section_edit_control_items($course, $section, $onsectionpage));
}
}

View File

@ -1,9 +1,12 @@
.course-content ul.topics {margin:0;}
.course-content ul.topics li.section {list-style: none;margin:0 0 5px 0;padding:0;}
.course-content ul.topics li.section .content {margin:0 40px;}
.course-content ul.topics li.section .left {float:left;}
.course-content ul.topics li.section .right {float:right;}
.course-content ul.topics li.section .left,
.course-content ul.topics li.section .right {width:40px;text-align:center;padding: 6px 0;}
.course-content ul.topics li.section .right {width:40px;padding: 0 6px;}
.course-content ul.topics li.section .right img.icon { padding: 0 0 4px 0;}
.course-content ul.topics li.section .left {padding-top:22px;text-align: right;}
.jsenabled .course-content ul.topics li.section .left,
.jsenabled .course-content ul.topics li.section .right {width:auto;}
.course-content ul.topics li.section .left .section-handle img.icon { padding:0; vertical-align: baseline; }
.course-content ul.topics li.section .section_action_menu .textmenu,
.course-content ul.topics li.section .section_action_menu .menu-action-text { white-space: nowrap; }

View File

@ -25,14 +25,14 @@ Feature: Sections can be edited and deleted in topics format
And I turn editing mode on
Scenario: Edit section summary in topics format
When I click on "Edit summary" "link" in the "li#section-2" "css_element"
When I edit the section "2"
And I set the following fields to these values:
| Summary | Welcome to section 2 |
And I press "Save changes"
Then I should see "Welcome to section 2" in the "li#section-2" "css_element"
Scenario: Edit section default name in topics format
When I click on "Edit summary" "link" in the "li#section-2" "css_element"
When I edit the section "2"
And I set the following fields to these values:
| Use default section name | 0 |
| name | This is the second topic |
@ -41,7 +41,7 @@ Feature: Sections can be edited and deleted in topics format
And I should not see "Topic 2" in the "li#section-2" "css_element"
Scenario: Deleting the last section in topics format
When I click on "Delete topic" "link" in the "li#section-5" "css_element"
When I delete section "5"
Then I should see "Are you absolutely sure you want to completely delete \"Topic 5\" and all the activities it contains?"
And I press "Continue"
And I should not see "Topic 5"
@ -50,7 +50,7 @@ Feature: Sections can be edited and deleted in topics format
And the field "Number of sections" matches value "4"
Scenario: Deleting the middle section in topics format
When I click on "Delete topic" "link" in the "li#section-4" "css_element"
When I delete section "4"
And I press "Continue"
Then I should not see "Topic 5"
And I should not see "Test chat name"
@ -62,7 +62,7 @@ Feature: Sections can be edited and deleted in topics format
Scenario: Deleting the orphaned section in topics format
When I follow "Reduce the number of sections"
Then I should see "Orphaned activities (section 5)" in the "li#section-5" "css_element"
And I click on "Delete topic" "link" in the "li#section-5" "css_element"
And I delete section "5"
And I press "Continue"
And I should not see "Topic 5"
And I should not see "Orphaned activities"
@ -76,7 +76,7 @@ Feature: Sections can be edited and deleted in topics format
Then I should see "Orphaned activities (section 5)" in the "li#section-5" "css_element"
And "li#section-5.orphaned" "css_element" should exist
And "li#section-4.orphaned" "css_element" should not exist
And I click on "Delete topic" "link" in the "li#section-1" "css_element"
And I delete section "1"
And I press "Continue"
And I should not see "Test book name"
And I should see "Orphaned activities (section 4)" in the "li#section-4" "css_element"

View File

@ -2,6 +2,10 @@ This files describes API changes for course formats
Overview of this plugin type at http://docs.moodle.org/dev/Course_formats
=== 3.0 ===
* Course formats should now use section_edit_control_items and use the returned array of controls items and their attributes to create a
renderable menu or array of links. Plugin calls to section_edit_controls will now include the section edit control in the returned array.
=== 2.9 ===
* Course formats may support deleting sections, see MDL-10405 for more details.
format_section_renderer_base::section_edit_controls() is now also called for

View File

@ -74,7 +74,7 @@ M.course.format.process_sections = function(Y, sectionlist, response, sectionfro
for (var i = sectionfrom; i <= sectionto; i++) {
// Update section title.
sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
sectionlist.item(i).all('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]);
// Update move icon.
ele = sectionlist.item(i).one(SELECTORS.SECTIONLEFTSIDE);

View File

@ -24,9 +24,11 @@
*/
$string['currentsection'] = 'This week';
$string['editsection'] = 'Edit week';
$string['deletesection'] = 'Delete week';
$string['sectionname'] = 'Week';
$string['pluginname'] = 'Weekly format';
$string['sectionmenu'] = 'Week menu';
$string['section0name'] = 'General';
$string['page-course-view-weeks'] = 'Any course main page in weeks format';
$string['page-course-view-weeks-x'] = 'Any course page in weeks format';

View File

@ -1,9 +1,12 @@
.course-content ul.weeks {margin:0;}
.course-content ul.weeks li.section {list-style: none;margin:0 0 5px 0;padding:0;}
.course-content ul.weeks li.section .content {margin:0 40px;}
.course-content ul.weeks li.section .left {float:left;}
.course-content ul.weeks li.section .right {float:right;}
.course-content ul.weeks li.section .left,
.course-content ul.weeks li.section .right {width:40px;text-align:center;padding: 6px 0;}
.course-content ul.weeks li.section .right {width:40px;padding: 0 6px;}
.course-content ul.weeks li.section .right img.icon { padding: 0 0 4px 0;}
.course-content ul.weeks li.section .left {padding-top:22px;text-align: right;}
.jsenabled .course-content ul.weeks li.section .left,
.jsenabled .course-content ul.weeks li.section .right {width:auto;}
.course-content ul.weeks li.section .left .section-handle img.icon { padding:0; vertical-align: baseline; }
.course-content ul.weeks li.section .section_action_menu .textmenu,
.course-content ul.weeks li.section .section_action_menu .menu-action-text { white-space: nowrap; }

View File

@ -25,7 +25,7 @@ Feature: Sections can be edited and deleted in weeks format
And I turn editing mode on
Scenario: Edit section summary in weeks format
When I click on "Edit summary" "link" in the "li#section-2" "css_element"
When I click on "Edit week" "link" in the "li#section-2" "css_element"
And I set the following fields to these values:
| Summary | Welcome to section 2 |
And I press "Save changes"
@ -33,7 +33,7 @@ Feature: Sections can be edited and deleted in weeks format
Scenario: Edit section default name in weeks format
Given I should see "8 May - 14 May" in the "li#section-2" "css_element"
When I click on "Edit summary" "link" in the "li#section-2" "css_element"
When I click on "Edit week" "link" in the "li#section-2" "css_element"
And I set the following fields to these values:
| Use default section name | 0 |
| name | This is the second week |
@ -43,7 +43,7 @@ Feature: Sections can be edited and deleted in weeks format
Scenario: Deleting the last section in weeks format
Given I should see "29 May - 4 June" in the "li#section-5" "css_element"
When I click on "Delete week" "link" in the "li#section-5" "css_element"
When I delete section "5"
Then I should see "Are you absolutely sure you want to completely delete \"29 May - 4 June\" and all the activities it contains?"
And I press "Continue"
And I should not see "29 May - 4 June"
@ -53,7 +53,7 @@ Feature: Sections can be edited and deleted in weeks format
Scenario: Deleting the middle section in weeks format
Given I should see "29 May - 4 June" in the "li#section-5" "css_element"
When I click on "Delete week" "link" in the "li#section-4" "css_element"
When I delete section "4"
And I press "Continue"
Then I should not see "29 May - 4 June"
And I should not see "Test chat name"
@ -65,7 +65,7 @@ Feature: Sections can be edited and deleted in weeks format
Scenario: Deleting the orphaned section in weeks format
When I follow "Reduce the number of sections"
Then I should see "Orphaned activities (section 5)" in the "li#section-5" "css_element"
And I click on "Delete week" "link" in the "li#section-5" "css_element"
And I delete section "5"
And I press "Continue"
And I should not see "29 May - 4 June"
And I should not see "Orphaned activities"
@ -79,7 +79,7 @@ Feature: Sections can be edited and deleted in weeks format
Then I should see "Orphaned activities (section 5)" in the "li#section-5" "css_element"
And "li#section-5.orphaned" "css_element" should exist
And "li#section-4.orphaned" "css_element" should not exist
And I click on "Delete week" "link" in the "li#section-1" "css_element"
And I delete section "1"
And I press "Continue"
And I should not see "Test book name"
And I should see "Orphaned activities (section 4)" in the "li#section-4" "css_element"

View File

@ -3322,6 +3322,8 @@ function include_course_ajax($course, $usedmodules = array(), $enabledmodules =
'edittitleinstructions',
'show',
'hide',
'highlight',
'highlightoff',
'groupsnone',
'groupsvisible',
'groupsseparate',

View File

@ -202,6 +202,56 @@ class behat_course extends behat_base {
}
/**
* Opens a section edit menu if it is not already opened.
*
* @Given /^I open section "(?P<section_number>\d+)" edit menu$/
* @throws DriverException The step is not available when Javascript is disabled
* @param string $sectionnumber
*/
public function i_open_section_edit_menu($sectionnumber) {
if (!$this->running_javascript()) {
throw new DriverException('Section edit menu not available when Javascript is disabled');
}
// If it is already opened we do nothing.
$xpath = $this->section_exists($sectionnumber);
$xpath .= "/descendant::div[contains(@class, 'section-actions')]/descendant::a[contains(@class, 'textmenu')]";
$exception = new ExpectationException('Section "' . $sectionnumber . '" was not found', $this->getSession());
$menu = $this->find('xpath', $xpath, $exception);
$menu->click();
$this->i_wait_until_section_is_available($sectionnumber);
}
/**
* Deletes course section.
*
* @Given /^I delete section "(?P<section_number>\d+)"$/
* @param int $sectionnumber The section number
* @return Given[]
*/
public function i_delete_section($sectionnumber) {
// Ensures the section exists.
$xpath = $this->section_exists($sectionnumber);
// We need to know the course format as the text strings depends on them.
$courseformat = $this->get_course_format();
if (get_string_manager()->string_exists('deletesection', $courseformat)) {
$strdelete = get_string('deletesection', $courseformat);
} else {
$strdelete = get_string('deletesection');
}
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
return new Given('I click on "' . $strdelete . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"');
}
/**
* Turns course section highlighting on.
*
@ -214,6 +264,11 @@ class behat_course extends behat_base {
// Ensures the section exists.
$xpath = $this->section_exists($sectionnumber);
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
return new Given('I click on "' . get_string('markthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"');
}
@ -229,6 +284,11 @@ class behat_course extends behat_base {
// Ensures the section exists.
$xpath = $this->section_exists($sectionnumber);
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
return new Given('I click on "' . get_string('markedthistopic') . '" "link" in the "' . $this->escape($xpath) . '" "xpath_element"');
}
@ -271,7 +331,20 @@ class behat_course extends behat_base {
* @param int $sectionnumber
*/
public function i_edit_the_section($sectionnumber) {
return new Given('I click on "' . get_string('editsummary') . '" "link" in the "#section-' . $sectionnumber . '" "css_element"');
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
// We need to know the course format as the text strings depends on them.
$courseformat = $this->get_course_format();
if (get_string_manager()->string_exists('editsection', $courseformat)) {
$stredit = get_string('editsection', $courseformat);
} else {
$stredit = get_string('editsection');
}
return new Given('I click on "' . $stredit . '" "link" in the "#section-' . $sectionnumber . '" "css_element"');
}
/**
@ -304,7 +377,7 @@ class behat_course extends behat_base {
$xpath = $this->section_exists($sectionnumber);
// The important checking, we can not check the img.
$xpath = $xpath . "/descendant::img[@alt='" . get_string('markedthistopic') . "'][contains(@src, 'marked')]";
$xpath = $xpath . "/descendant::img[contains(@src, 'marked')]";
$exception = new ExpectationException('The "' . $sectionnumber . '" section is not highlighted', $this->getSession());
$this->find('xpath', $xpath, $exception);
}
@ -409,9 +482,14 @@ class behat_course extends behat_base {
throw new ExpectationException('The section is hidden', $this->getSession());
}
// Hide section button should be visible.
// Edit menu should be visible.
if ($this->is_course_editor()) {
$this->hide_section_icon_exists($sectionnumber);
$xpath = $sectionxpath .
"/descendant::div[contains(@class, 'section-actions')]" .
"/descendant::a[contains(@class, 'textmenu')]";
if (!$this->getSession()->getPage()->find('xpath', $xpath)) {
throw new ExpectationException('The section edit menu is not available', $this->getSession());
}
}
}
@ -431,6 +509,11 @@ class behat_course extends behat_base {
// Ensures the section exists.
$sectionxpath = $this->section_exists($sectionnumber);
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
// Follows the link
$moveuplink = $this->get_node_in_container('link', get_string('moveup'), 'xpath_element', $sectionxpath);
$moveuplink->click();
@ -452,6 +535,11 @@ class behat_course extends behat_base {
// Ensures the section exists.
$sectionxpath = $this->section_exists($sectionnumber);
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
// Follows the link
$movedownlink = $this->get_node_in_container('link', get_string('movedown'), 'xpath_element', $sectionxpath);
$movedownlink->click();
@ -876,10 +964,15 @@ class behat_course extends behat_base {
// We need to know the course format as the text strings depends on them.
$courseformat = $this->get_course_format();
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
// Checking the show button alt text and show icon.
$showtext = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('showfromothers', $courseformat));
$linkxpath = $xpath . "/descendant::a[@title=$showtext]";
$imgxpath = $linkxpath . "/descendant::img[@alt=$showtext][contains(@src, 'show')]";
$imgxpath = $linkxpath . "/descendant::img[contains(@src, 'show')]";
$exception = new ElementNotFoundException($this->getSession(), 'Show section icon ');
$this->find('xpath', $imgxpath, $exception);
@ -903,10 +996,15 @@ class behat_course extends behat_base {
// We need to know the course format as the text strings depends on them.
$courseformat = $this->get_course_format();
// If javascript is on, link is inside a menu.
if ($this->running_javascript()) {
$this->i_open_section_edit_menu($sectionnumber);
}
// Checking the hide button alt text and hide icon.
$hidetext = $this->getSession()->getSelectorsHandler()->xpathLiteral(get_string('hidefromothers', $courseformat));
$linkxpath = $xpath . "/descendant::a[@title=$hidetext]";
$imgxpath = $linkxpath . "/descendant::img[@alt=$hidetext][contains(@src, 'hide')]";
$imgxpath = $linkxpath . "/descendant::img[contains(@src, 'hide')]";
$exception = new ElementNotFoundException($this->getSession(), 'Hide section icon ');
$this->find('xpath', $imgxpath, $exception);

View File

@ -106,10 +106,30 @@ Y.extend(DRAGSECTION, M.core.dragdrop, {
cssleft.appendChild(this.get_drag_handle(title, CSS.SECTIONHANDLE, 'icon', true));
if (moveup) {
moveup.remove();
if (moveup.previous('br')) {
moveup.previous('br').remove();
} else if (moveup.next('br')) {
moveup.next('br').remove();
}
if (moveup.ancestor('.section_action_menu')) {
moveup.ancestor('li').remove();
} else {
moveup.remove();
}
}
if (movedown) {
movedown.remove();
if (movedown.previous('br')) {
movedown.previous('br').remove();
} else if (movedown.next('br')) {
movedown.next('br').remove();
}
if (movedown.ancestor('.section_action_menu')) {
movedown.ancestor('li').remove();
} else {
movedown.remove();
}
}
// This section can be moved - add the class to indicate this to Y.DD.

File diff suppressed because one or more lines are too long

View File

@ -106,10 +106,30 @@ Y.extend(DRAGSECTION, M.core.dragdrop, {
cssleft.appendChild(this.get_drag_handle(title, CSS.SECTIONHANDLE, 'icon', true));
if (moveup) {
moveup.remove();
if (moveup.previous('br')) {
moveup.previous('br').remove();
} else if (moveup.next('br')) {
moveup.next('br').remove();
}
if (moveup.ancestor('.section_action_menu')) {
moveup.ancestor('li').remove();
} else {
moveup.remove();
}
}
if (movedown) {
movedown.remove();
if (movedown.previous('br')) {
movedown.previous('br').remove();
} else if (movedown.next('br')) {
movedown.next('br').remove();
}
if (movedown.ancestor('.section_action_menu')) {
movedown.ancestor('li').remove();
} else {
movedown.remove();
}
}
// This section can be moved - add the class to indicate this to Y.DD.

View File

@ -981,6 +981,7 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var section = e.target.ancestor(M.course.format.get_section_selector(Y)),
button = e.target.ancestor('a', true),
hideicon = button.one('img'),
buttontext = button.one('span'),
// The value to submit
value,
@ -1007,8 +1008,11 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
'src' : M.util.image_url('i/' + nextaction)
});
button.set('title', newstring);
if (buttontext) {
buttontext.set('text', newstring);
}
// Change the highlight status
// Change the show/hide status
var data = {
'class' : 'section',
'field' : 'visible',
@ -1053,6 +1057,7 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var section = e.target.ancestor(M.course.format.get_section_selector(Y));
var button = e.target.ancestor('a', true);
var buttonicon = button.one('img');
var buttontext = button.one('span');
// Determine whether the marker is currently set.
var togglestatus = section.hasClass('current');
@ -1060,16 +1065,21 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
// Set the current highlighted item text.
var old_string = M.util.get_string('markthistopic', 'moodle');
Y.one(SELECTOR.PAGECONTENT)
var selectedpage = Y.one(SELECTOR.PAGECONTENT);
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT)
.set('title', old_string);
Y.one(SELECTOR.PAGECONTENT)
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' span')
.set('text', M.util.get_string('highlight', 'moodle'));
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' img')
.set('alt', old_string)
.set('src', M.util.image_url('i/marker'));
// Remove the highlighting from all sections.
Y.one(SELECTOR.PAGECONTENT).all(M.course.format.get_section_selector(Y))
selectedpage.all(M.course.format.get_section_selector(Y))
.removeClass('current');
// Then add it if required to the selected section.
@ -1082,6 +1092,10 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
buttonicon
.set('alt', new_string)
.set('src', M.util.image_url('i/marked'));
if (buttontext) {
buttontext
.set('text', M.util.get_string('highlightoff', 'moodle'));
}
}
// Change the highlight status.

File diff suppressed because one or more lines are too long

View File

@ -981,6 +981,7 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var section = e.target.ancestor(M.course.format.get_section_selector(Y)),
button = e.target.ancestor('a', true),
hideicon = button.one('img'),
buttontext = button.one('span'),
// The value to submit
value,
@ -1007,8 +1008,11 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
'src' : M.util.image_url('i/' + nextaction)
});
button.set('title', newstring);
if (buttontext) {
buttontext.set('text', newstring);
}
// Change the highlight status
// Change the show/hide status
var data = {
'class' : 'section',
'field' : 'visible',
@ -1053,6 +1057,7 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var section = e.target.ancestor(M.course.format.get_section_selector(Y));
var button = e.target.ancestor('a', true);
var buttonicon = button.one('img');
var buttontext = button.one('span');
// Determine whether the marker is currently set.
var togglestatus = section.hasClass('current');
@ -1060,16 +1065,21 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
// Set the current highlighted item text.
var old_string = M.util.get_string('markthistopic', 'moodle');
Y.one(SELECTOR.PAGECONTENT)
var selectedpage = Y.one(SELECTOR.PAGECONTENT);
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT)
.set('title', old_string);
Y.one(SELECTOR.PAGECONTENT)
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' span')
.set('text', M.util.get_string('highlight', 'moodle'));
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' img')
.set('alt', old_string)
.set('src', M.util.image_url('i/marker'));
// Remove the highlighting from all sections.
Y.one(SELECTOR.PAGECONTENT).all(M.course.format.get_section_selector(Y))
selectedpage.all(M.course.format.get_section_selector(Y))
.removeClass('current');
// Then add it if required to the selected section.
@ -1082,6 +1092,10 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
buttonicon
.set('alt', new_string)
.set('src', M.util.image_url('i/marked'));
if (buttontext) {
buttontext
.set('text', M.util.get_string('highlightoff', 'moodle'));
}
}
// Change the highlight status.

View File

@ -75,10 +75,30 @@ Y.extend(DRAGSECTION, M.core.dragdrop, {
cssleft.appendChild(this.get_drag_handle(title, CSS.SECTIONHANDLE, 'icon', true));
if (moveup) {
moveup.remove();
if (moveup.previous('br')) {
moveup.previous('br').remove();
} else if (moveup.next('br')) {
moveup.next('br').remove();
}
if (moveup.ancestor('.section_action_menu')) {
moveup.ancestor('li').remove();
} else {
moveup.remove();
}
}
if (movedown) {
movedown.remove();
if (movedown.previous('br')) {
movedown.previous('br').remove();
} else if (movedown.next('br')) {
movedown.next('br').remove();
}
if (movedown.ancestor('.section_action_menu')) {
movedown.ancestor('li').remove();
} else {
movedown.remove();
}
}
// This section can be moved - add the class to indicate this to Y.DD.

View File

@ -49,6 +49,7 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var section = e.target.ancestor(M.course.format.get_section_selector(Y)),
button = e.target.ancestor('a', true),
hideicon = button.one('img'),
buttontext = button.one('span'),
// The value to submit
value,
@ -75,8 +76,11 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
'src' : M.util.image_url('i/' + nextaction)
});
button.set('title', newstring);
if (buttontext) {
buttontext.set('text', newstring);
}
// Change the highlight status
// Change the show/hide status
var data = {
'class' : 'section',
'field' : 'visible',
@ -121,6 +125,7 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
var section = e.target.ancestor(M.course.format.get_section_selector(Y));
var button = e.target.ancestor('a', true);
var buttonicon = button.one('img');
var buttontext = button.one('span');
// Determine whether the marker is currently set.
var togglestatus = section.hasClass('current');
@ -128,16 +133,21 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
// Set the current highlighted item text.
var old_string = M.util.get_string('markthistopic', 'moodle');
Y.one(SELECTOR.PAGECONTENT)
var selectedpage = Y.one(SELECTOR.PAGECONTENT);
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT)
.set('title', old_string);
Y.one(SELECTOR.PAGECONTENT)
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' span')
.set('text', M.util.get_string('highlight', 'moodle'));
selectedpage
.all(M.course.format.get_section_selector(Y) + '.current ' + SELECTOR.HIGHLIGHT + ' img')
.set('alt', old_string)
.set('src', M.util.image_url('i/marker'));
// Remove the highlighting from all sections.
Y.one(SELECTOR.PAGECONTENT).all(M.course.format.get_section_selector(Y))
selectedpage.all(M.course.format.get_section_selector(Y))
.removeClass('current');
// Then add it if required to the selected section.
@ -150,6 +160,10 @@ Y.extend(SECTIONTOOLBOX, TOOLBOX, {
buttonicon
.set('alt', new_string)
.set('src', M.util.image_url('i/marked'));
if (buttontext) {
buttontext
.set('text', M.util.get_string('highlightoff', 'moodle'));
}
}
// Change the highlight status.

View File

@ -557,7 +557,7 @@ $string['editorpreferences'] = 'Editor preferences';
$string['editorresettodefaults'] = 'Reset to default values';
$string['editorsettings'] = 'Editor settings';
$string['editorshortcutkeys'] = 'Editor shortcut keys';
$string['editsettings'] = 'Edit settings';
$string['editsection'] = 'Edit section';
$string['editsummary'] = 'Edit summary';
$string['edittitle'] = 'Edit title';
$string['edittitleinstructions'] = 'Escape to cancel, Enter when finished';
@ -924,6 +924,8 @@ $string['hidepicture'] = 'Hide picture';
$string['hidesection'] = 'Hide section {$a}';
$string['hidesettings'] = 'Hide settings';
$string['hideshowblocks'] = 'Hide or show blocks';
$string['highlight'] = 'Highlight';
$string['highlightoff'] = 'Remove highlight';
$string['hits'] = 'Hits';
$string['hitsoncourse'] = 'Hits on {$a->coursename} by {$a->username}';
$string['hitsoncoursetoday'] = 'Today\'s hits on {$a->coursename} by {$a->username}';
@ -1632,6 +1634,7 @@ $string['secondstotime86400'] = '1 day';
$string['secretalreadyused'] = 'Change password confirmation link was already used, password was not changed.';
$string['secs'] = 'secs';
$string['section'] = 'Section';
$string['sectionmenu'] = 'Section menu';
$string['sectionname'] = 'Section name';
$string['sections'] = 'Sections';
$string['sectionusedefaultname'] = 'Use default section name';

BIN
pix/i/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

11
pix/i/delete.svg Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-295 293 16 16" style="enable-background:new -295 293 16 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#999999;}
</style>
<path class="st0" d="M-284.4,300.6l4.3-4.3c0.5-0.5,0.5-1.4,0-1.9l-0.9-0.9c-0.5-0.5-1.4-0.5-1.9,0l-4.5,4.3l-4.3-4.3
c-0.5-0.5-1.4-0.5-1.9,0l-0.9,0.9c-0.5,0.5-0.5,1.4,0,1.9l4.3,4.3l-4.3,4.5c-0.5,0.5-0.5,1.4,0,1.9l0.9,0.9c0.5,0.5,1.4,0.5,1.9,0
l4.3-4.3l4.5,4.3c0.5,0.5,1.4,0.5,1.9,0l0.9-0.9c0.5-0.5,0.5-1.4,0-1.9L-284.4,300.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 745 B

View File

@ -1979,6 +1979,8 @@ img#persona_signin { cursor: pointer; }
.moodle-actionmenu > ul,
.moodle-actionmenu > ul > li {display: inline-block;}
.moodle-actionmenu ul {padding: 0;margin: 0;list-style-type: none;}
.section_action_menu .moodle-actionmenu ul.menubar {margin: 0;}
.section_action_menu .moodle-actionmenu ul.menu {margin: 0 10px 10px 0;}
#page .moodle-actionmenu a.hidden {display: none;}
.moodle-actionmenu .toggle-display,
.moodle-actionmenu .menu-action-text {display: none;}

View File

@ -29,6 +29,19 @@
display: inline-block;
}
.section .side.left {
float: left;
}
.dir-rtl .section .side.left {
float: right;
}
.section .side.right {
float: right;
}
.dir-rtl .section .side.right {
float: left;
}
.section .activity .editing_move {
position: absolute;
left: 0;

View File

@ -2193,6 +2193,14 @@ img#persona_signin {
list-style-type: none;
}
.section_action_menu .moodle-actionmenu ul.menubar {
margin: 0;
}
.section_action_menu .moodle-actionmenu ul.menu {
margin: 0 10px 10px 0;
}
.moodle-actionmenu .toggle-display,
.moodle-actionmenu .menu-action-text {
display: none; /** Hidden by default, display none so that we don't take up space. **/

View File

@ -2,9 +2,14 @@
/* COURSE CONTENT */
.section_add_menus {
text-align: right;
clear: both;
}
.section-modchooser {
clear: both;
}
.dir-rtl .section_add_menus {
text-align: left;
clear: both;
}
.section_add_menus .horizontal div,
.section_add_menus .horizontal form {
@ -41,6 +46,16 @@
margin: 1em;
}
.section {
.side {
&.left {
float: left;
}
&.right {
float: right;
}
position: relative;
z-index: 10;
}
.spinner {
height: 16px;
width: 16px;
@ -130,6 +145,16 @@
}
.dir-rtl .section {
.side {
&.left {
float: right;
}
&.right {
float: left;
}
position: relative;
z-index: 10;
}
.activity {
.spinner {
left: auto;

File diff suppressed because one or more lines are too long