MDL-80828 core_courseformat: Modify availability subpanel visibility

In the activity action menu, show only the subpanel when the options are different
than show or hide. In those cases the show/hide option will be directly displayed
in the menu instead of a subpanel.

Co-authored-by: ferran@moodle.com
This commit is contained in:
Mikel Martín 2024-02-28 17:15:51 +01:00
parent 342319339f
commit cd8a089d7a
12 changed files with 132 additions and 23 deletions

View File

@ -134,7 +134,7 @@ class controlmenu implements named_templatable, renderable {
// Prioritise the menu ahead of all other actions.
$menu->prioritise = true;
$ownerselector = $displayoptions['ownerselector'] ?? '#module-' . $mod->id;
$ownerselector = $this->displayoptions['ownerselector'] ?? '#module-' . $mod->id;
$menu->set_owner_selector($ownerselector);
foreach ($controls as $control) {

View File

@ -24,6 +24,8 @@
namespace core_courseformat\output\local\content\cm;
use action_menu_link_secondary;
use core\output\local\action_menu\subpanel as action_menu_subpanel;
use cm_info;
use core_courseformat\base as course_format;
use core_courseformat\output\local\courseformat_named_templatable;
@ -162,6 +164,43 @@ class visibility implements named_templatable, renderable {
return $choice;
}
/**
* Return the cm availability menu item.
*
* By default, the cm availability is displayed as a menu item subpanel.
* However, it can be simplified when there is only one option and
* it is not stealth (stealth require a subpanel to inform the user).
*
* @return action_menu_link_secondary|action_menu_subpanel|null
*/
public function get_menu_item(): action_menu_link_secondary|action_menu_subpanel|null {
$choice = $this->get_choice_list();
$selectableoptions = $choice->get_selectable_options();
if (count($selectableoptions) === 0) {
return null;
}
// Visible activities in hidden sections are always considered stealth.
if ($this->section->visible && count($selectableoptions) === 1) {
$option = reset($selectableoptions);
$actionlabel = $option->value === 'show' ? 'modshow' : 'modhide';
return new action_menu_link_secondary(
$option->url,
$option->icon,
get_string($actionlabel, 'moodle'),
$choice->get_option_extras($option->value)
);
}
return new action_menu_subpanel(
get_string('availability', 'moodle'),
$choice,
['class' => 'editing_availability'],
new pix_icon('t/hide', '', 'moodle', ['class' => 'iconsmall'])
);
}
/**
* Get the selected choice value depending on the course, section and stealth settings.
* @return string

View File

@ -27,14 +27,14 @@ Feature: Verify activity visibility interface.
Scenario: Teacher can hide an activity using the actions menu.
Given I should not see "Hidden from students" in the "Activity sample 1" "activity"
When I open "Activity sample 1" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
Then I should see "Hidden from students" in the "Activity sample 1" "core_courseformat > Activity visibility"
@javascript
Scenario: Teacher can show an activity using the actions menu.
Given I should see "Hidden from students" in the "Activity sample 2" "core_courseformat > Activity visibility"
When I open "Activity sample 2" actions menu
And I choose "Availability > Show on course page" in the open action menu
And I choose "Show" in the open action menu
Then I should not see "Hidden from students" in the "Activity sample 2" "activity"
@javascript

View File

@ -77,7 +77,7 @@ Feature: Course index depending on role
And I am on "Course 1" course homepage with editing mode on
And I hide section "2"
And I open "Activity sample 3" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
And I log out
And I log in as "teacher1"
When I am on "Course 1" course homepage
@ -94,7 +94,7 @@ Feature: Course index depending on role
And I am on "Course 1" course homepage with editing mode on
And I hide section "2"
And I open "Activity sample 3" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
And I log out
And I log in as "student1"
When I am on "Course 1" course homepage

View File

@ -43,7 +43,7 @@ Feature: Varify section visibility interface
@javascript
Scenario: Hiden activities in hidden sections stay hidden when the section is shown.
Given I open "Activity sample 1" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
And I should see "Hidden from students" in the "Activity sample 1" "activity"
And I hide section "1"
And I should see "Hidden from students" in the "Activity sample 1" "activity"

View File

@ -1443,7 +1443,7 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
$str = get_strings(
[
'delete', 'move', 'moveright', 'moveleft', 'editsettings',
'duplicate', 'availability'
'duplicate', 'availability',
],
'moodle'
);
@ -1543,14 +1543,9 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
$availabilityclass = $courseformat->get_output_classname('content\\cm\\visibility');
/** @var core_courseformat\output\local\content\cm\visibility */
$availability = new $availabilityclass($courseformat, $sectioninfo, $mod);
$availabilitychoice = $availability->get_choice_list();
if ($availabilitychoice->count_options() > 1) {
$actions['availability'] = new action_menu_subpanel(
$str->availability,
$availabilitychoice,
['class' => 'editing_availability'],
new pix_icon('t/hide', '', 'moodle', array('class' => 'iconsmall'))
);
$availabilityitem = $availability->get_menu_item();
if ($availabilityitem) {
$actions['availability'] = $availabilityitem;
}
}

View File

@ -34,13 +34,13 @@ Feature: Toggle activities visibility from the course page
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
When I open "Test forum name" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
Then "Test forum name" activity should be hidden
And I open "Test forum name" actions menu
And I choose "Availability > Show on course page" in the open action menu
And I choose "Show" in the open action menu
And "Test forum name" activity should be visible
And I open "Test forum name" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
And "Test forum name" activity should be hidden
And I reload the page
And "Test forum name" activity should be hidden

View File

@ -55,7 +55,7 @@ Feature: Course activity controls works as expected
And I click on "Cancel" "button"
And <belowpage> "section" should not exist
And I open "Test forum name 1" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
And <belowpage> "section" should not exist
And I delete "Test forum name 1" activity
And I should not see "Test forum name 1" in the "region-main" "region"
@ -125,7 +125,7 @@ Feature: Course activity controls works as expected
And I should see "Display description on course page"
And I press "Save and return to course"
And <belowpage> "section" should not exist
And I click on "Hide on course page" "link" in the "Test forum name 1" activity
And I click on "Hide" "link" in the "Test forum name 1" activity
And <belowpage> "section" should not exist
And I delete "Test forum name 1" activity
And <belowpage> "section" should not exist

View File

@ -40,7 +40,7 @@ Feature: We can change what we are viewing on the grader report
Scenario: View and minimise the grader report containing hidden activities
When I am on "Course 1" course homepage with editing mode on
And I open "Test assignment name 2" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
And I am on "Course 1" course homepage with editing mode off
And I navigate to "View > Grader report" in the course gradebook
And I should see "Test assignment name 1" in the "user-grades" "table"
@ -73,7 +73,7 @@ Feature: We can change what we are viewing on the grader report
Scenario: Minimise the grader report containing hidden activities without the 'moodle/grade:viewhidden' capability
Given I am on "Course 1" course homepage with editing mode on
And I open "Test assignment name 2" actions menu
And I choose "Availability > Hide on course page" in the open action menu
And I choose "Hide" in the open action menu
And the following "role capability" exists:
| role | editingteacher |
| moodle/grade:viewhidden | prevent |

View File

@ -94,6 +94,23 @@ class choicelist implements renderable, named_templatable {
return count($this->options);
}
/**
* Get the selectable options.
*
* This method returns an array of options that are selectable, excluding the selected option and any disabled options.
*
* @return \stdClass[]
*/
public function get_selectable_options(): array {
$selectableOptions = [];
foreach ($this->options as $option) {
if ($option['value'] !== $this->selected && !$option['disabled']) {
$selectableOptions[] = (object) $option;
}
}
return $selectableOptions;
}
/**
* Set the selected option.
*
@ -206,6 +223,23 @@ class choicelist implements renderable, named_templatable {
}
}
/**
* Retrieves the HTML attributes for a given value from the options array.
* @param string $value The value for which to retrieve the extras.
* @return array an array of HTML attributes of the option (attribute => value).
*/
public function get_option_extras(string $value): array {
if (!isset($this->options[$value]) || !isset($this->options[$value]['extras'])) {
return [];
}
$result = [];
foreach ($this->options[$value]['extras'] as $extra) {
$result[$extra['attribute']] = $extra['value'];
}
return $result;
}
/**
* Get the selected option HTML.
*

View File

@ -232,4 +232,45 @@ class choicelist_test extends advanced_testcase {
$this->assertTrue($choice->get_allow_empty());
$this->assertEquals('option2', $choice->get_selected_value());
}
/**
* Test for a choice with option selected.
*
* @covers ::get_selectable_options
*/
public function test_get_selectable_options(): void {
$choice = new choicelist('Choose an option');
$choice->add_option('option1', 'Option 1');
$choice->add_option('option2', 'Option 2');
$choice->add_option('option3', 'Option 3', ['disabled' => true]);
$choice->add_option('option4', 'Option 4', ['disabled' => true]);
$choice->add_option('option5', 'Option 5');
$selectable = $choice->get_selectable_options();
$this->assertCount(3, $selectable);
$this->assertEquals('option1', $selectable[0]->value);
$this->assertEquals('option2', $selectable[1]->value);
$this->assertEquals('option5', $selectable[2]->value);
$choice->set_selected_value('option2');
$selectable = $choice->get_selectable_options();
$this->assertCount(2, $selectable);
$this->assertEquals('option1', $selectable[0]->value);
$this->assertEquals('option5', $selectable[1]->value);
}
/**
* Test for a choice with option selected.
*
* @covers ::get_option_extras
*/
public function test_get_option_extras(): void {
$choice = new choicelist('Choose an option');
$choice->add_option('option1', 'Option 1');
$choice->add_option('option2', 'Option 2', ['extras' => ['data-attribute' => 'value2']]);
$this->assertEquals([], $choice->get_option_extras('option1'));
$this->assertEquals(['data-attribute' => 'value2'], $choice->get_option_extras('option2'));
$this->assertEquals([], $choice->get_option_extras('inexistent'));
}
}

View File

@ -86,7 +86,7 @@ Feature: Add H5P activity context locking
Scenario: Access participant report in a hidden activity
Given I log in as "admin"
And I am on "Course 1" course homepage with editing mode on
And I click on "Hide on course page" "link" in the "H5P package" activity
And I click on "Hide" "link" in the "H5P package" activity
When I am on the "H5P package" "h5pactivity activity" page
And I navigate to "Attempts report" in current page administration
Then I should see "Student 1"