mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 05:58:34 +01:00
MDL-76993 core_course: Recover move right/left functionality
This is a backport of MDL-76990
This commit is contained in:
parent
f8e2445513
commit
3a38791d62
2
course/amd/build/actions.min.js
vendored
2
course/amd/build/actions.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -60,7 +60,7 @@ define(
|
||||
// Meanwhile, we filter the migrated actions.
|
||||
const componentActions = [
|
||||
'moveSection', 'moveCm', 'addSection', 'deleteSection', 'sectionHide', 'sectionShow',
|
||||
'cmHide', 'cmShow', 'cmStealth',
|
||||
'cmHide', 'cmShow', 'cmStealth', 'cmMoveRight', 'cmMoveLeft',
|
||||
];
|
||||
|
||||
// The course reactive instance.
|
||||
|
2
course/format/amd/build/local/content.min.js
vendored
2
course/format/amd/build/local/content.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -221,6 +221,7 @@ export default class Component extends BaseComponent {
|
||||
// State changes that require to reload some course modules.
|
||||
{watch: `cm.visible:updated`, handler: this._reloadCm},
|
||||
{watch: `cm.stealth:updated`, handler: this._reloadCm},
|
||||
{watch: `cm.indent:updated`, handler: this._reloadCm},
|
||||
// Update section number and title.
|
||||
{watch: `section.number:updated`, handler: this._refreshSectionNumber},
|
||||
// Collapse and expand sections.
|
||||
|
@ -50,6 +50,8 @@ const directMutations = {
|
||||
cmHide: 'cmHide',
|
||||
cmShow: 'cmShow',
|
||||
cmStealth: 'cmStealth',
|
||||
cmMoveRight: 'cmMoveRight',
|
||||
cmMoveLeft: 'cmMoveLeft',
|
||||
};
|
||||
|
||||
export default class extends BaseComponent {
|
||||
|
@ -282,6 +282,24 @@ export default class {
|
||||
this._setElementsValue(stateManager, 'cm', cmIds, 'completionstate', newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move cms to the right: indent = 1.
|
||||
* @param {StateManager} stateManager the current state manager
|
||||
* @param {array} cmIds the list of cm ids
|
||||
*/
|
||||
async cmMoveRight(stateManager, cmIds) {
|
||||
await this._cmBasicAction(stateManager, 'cm_moveright', cmIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move cms to the left: indent = 0.
|
||||
* @param {StateManager} stateManager the current state manager
|
||||
* @param {array} cmIds the list of cm ids
|
||||
*/
|
||||
async cmMoveLeft(stateManager, cmIds) {
|
||||
await this._cmBasicAction(stateManager, 'cm_moveleft', cmIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock or unlock course modules.
|
||||
*
|
||||
|
@ -456,14 +456,6 @@ abstract class base {
|
||||
/**
|
||||
* Returns true if this course format uses activity indentation.
|
||||
*
|
||||
* Indentation is not supported by core formats anymore and may be deprecated in the future.
|
||||
* This method will keep a default return "true" for legacy reasons but new formats should override
|
||||
* it with a return false to prevent future deprecations.
|
||||
*
|
||||
* A message in a bottle: if indentation is finally deprecated, both behat steps i_indent_right_activity
|
||||
* and i_indent_left_activity should be removed as well. Right now no core behat uses them but indentation
|
||||
* is not officially deprecated so they are still available for the contrib formats.
|
||||
*
|
||||
* @return bool if the course format uses indentation.
|
||||
*/
|
||||
public function uses_indentation(): bool {
|
||||
|
@ -106,6 +106,7 @@ class cmitem implements named_templatable, renderable {
|
||||
'extraclasses' => $mod->extraclasses,
|
||||
'cmformat' => $item->export_for_template($output),
|
||||
'hasinfo' => $hasinfo,
|
||||
'indent' => $mod->indent,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ class cm implements renderable {
|
||||
'sectionnumber' => $section->section,
|
||||
'uservisible' => $cm->uservisible,
|
||||
'hascmrestrictions' => $this->get_has_restrictions(),
|
||||
'indent' => $cm->indent,
|
||||
];
|
||||
|
||||
// Check the user access type to this cm.
|
||||
|
@ -422,6 +422,79 @@ class stateactions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move course cms to the right. Indent = 1.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids cm ids
|
||||
* @param int $targetsectionid not used
|
||||
* @param int $targetcmid not used
|
||||
*/
|
||||
public function cm_moveright(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null
|
||||
): void {
|
||||
$this->set_cm_indentation($updates, $course, $ids, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move course cms to the left. Indent = 0.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids cm ids
|
||||
* @param int $targetsectionid not used
|
||||
* @param int $targetcmid not used
|
||||
*/
|
||||
public function cm_moveleft(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids = [],
|
||||
?int $targetsectionid = null,
|
||||
?int $targetcmid = null
|
||||
): void {
|
||||
$this->set_cm_indentation($updates, $course, $ids, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to define the cm indentation level.
|
||||
*
|
||||
* @param stateupdates $updates the affected course elements track
|
||||
* @param stdClass $course the course object
|
||||
* @param int[] $ids cm ids
|
||||
* @param int $indent new value for indentation
|
||||
*/
|
||||
protected function set_cm_indentation(
|
||||
stateupdates $updates,
|
||||
stdClass $course,
|
||||
array $ids,
|
||||
int $indent
|
||||
): void {
|
||||
global $DB;
|
||||
|
||||
$this->validate_cms($course, $ids, __FUNCTION__);
|
||||
|
||||
// Check capabilities on every activity context.
|
||||
foreach ($ids as $cmid) {
|
||||
$modcontext = context_module::instance($cmid);
|
||||
require_capability('moodle/course:manageactivities', $modcontext);
|
||||
}
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
$cms = $this->get_cm_info($modinfo, $ids);
|
||||
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($cms), SQL_PARAMS_NAMED);
|
||||
$DB->set_field_select('course_modules', 'indent', $indent, "id $insql", $inparams);
|
||||
rebuild_course_cache($course->id, false, true);
|
||||
foreach ($cms as $cm) {
|
||||
$modcontext = context_module::instance($cm->id);
|
||||
course_module_updated::create_from_cm($cm, $modcontext)->trigger();
|
||||
$updates->add_cm_put($cm->id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract several cm_info from the course_modinfo.
|
||||
*
|
||||
|
@ -53,7 +53,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"modstealth": true
|
||||
"modstealth": true,
|
||||
"indent": 1
|
||||
}
|
||||
}}
|
||||
<div class="activity-item {{#modstealth}}hiddenactivity{{/modstealth}}{{!
|
||||
|
@ -34,11 +34,12 @@
|
||||
"id": 3,
|
||||
"anchor": "module-3",
|
||||
"module": "forum",
|
||||
"extraclasses": "newmessages"
|
||||
"extraclasses": "newmessages",
|
||||
"indent": 0
|
||||
}
|
||||
}}
|
||||
<li
|
||||
class="activity activity-wrapper {{module}} modtype_{{module}} {{extraclasses}} {{#hasinfo}}hasinfo{{/hasinfo}}"
|
||||
class="activity activity-wrapper {{module}} modtype_{{module}} {{extraclasses}} {{#hasinfo}}hasinfo{{/hasinfo}} {{#indent}}indented{{/indent}}"
|
||||
id="{{anchor}}"
|
||||
data-for="cmitem"
|
||||
data-id="{{id}}"
|
||||
|
@ -870,4 +870,58 @@ class stateactions_test extends \advanced_testcase {
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for cm_moveright
|
||||
*
|
||||
* @covers ::cm_moveright
|
||||
* @dataProvider basic_role_provider
|
||||
* @param string $role the user role
|
||||
* @param bool $expectedexception if it will expect an exception.
|
||||
*/
|
||||
public function test_cm_moveright(
|
||||
string $role = 'editingteacher',
|
||||
bool $expectedexception = false
|
||||
): void {
|
||||
$this->basic_state_text(
|
||||
'cm_moveright',
|
||||
$role,
|
||||
['cm0', 'cm1', 'cm2', 'cm3'],
|
||||
$expectedexception,
|
||||
4,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'indent',
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for cm_moveleft
|
||||
*
|
||||
* @covers ::cm_moveleft
|
||||
* @dataProvider basic_role_provider
|
||||
* @param string $role the user role
|
||||
* @param bool $expectedexception if it will expect an exception.
|
||||
*/
|
||||
public function test_cm_moveleft(
|
||||
string $role = 'editingteacher',
|
||||
bool $expectedexception = false
|
||||
): void {
|
||||
$this->basic_state_text(
|
||||
'cm_moveleft',
|
||||
$role,
|
||||
['cm0', 'cm1', 'cm2', 'cm3'],
|
||||
$expectedexception,
|
||||
4,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'indent',
|
||||
0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -50,10 +50,6 @@ class format_topics extends core_courseformat\base {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function uses_indentation(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name of the given section that the course prefers.
|
||||
*
|
||||
|
@ -49,10 +49,6 @@ class format_weeks extends core_courseformat\base {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function uses_indentation(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the title for this section page
|
||||
* @return string the page title
|
||||
|
@ -1702,7 +1702,9 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
if ($hasmanageactivities && $indent >= 0) {
|
||||
$indentlimits = new stdClass();
|
||||
$indentlimits->min = 0;
|
||||
$indentlimits->max = 16;
|
||||
// Legacy indentation could continue using a limit of 16,
|
||||
// but components based formats will be forced to use one level indentation only.
|
||||
$indentlimits->max = ($usecomponents) ? 1 : 16;
|
||||
if (right_to_left()) { // Exchange arrows on RTL
|
||||
$rightarrow = 't/left';
|
||||
$leftarrow = 't/right';
|
||||
@ -1717,11 +1719,16 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
$enabledclass = '';
|
||||
}
|
||||
$actions['moveright'] = new action_menu_link_secondary(
|
||||
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '1')),
|
||||
new pix_icon($rightarrow, '', 'moodle', array('class' => 'iconsmall')),
|
||||
new moodle_url($baseurl, ['id' => $mod->id, 'indent' => '1']),
|
||||
new pix_icon($rightarrow, '', 'moodle', ['class' => 'iconsmall']),
|
||||
$str->moveright,
|
||||
array('class' => 'editing_moveright ' . $enabledclass, 'data-action' => 'moveright',
|
||||
'data-keepopen' => true, 'data-sectionreturn' => $sr)
|
||||
[
|
||||
'class' => 'editing_moveright ' . $enabledclass,
|
||||
'data-action' => ($usecomponents) ? 'cmMoveRight' : 'moveright',
|
||||
'data-keepopen' => true,
|
||||
'data-sectionreturn' => $sr,
|
||||
'data-id' => $mod->id,
|
||||
]
|
||||
);
|
||||
|
||||
if ($indent <= $indentlimits->min) {
|
||||
@ -1730,11 +1737,16 @@ function course_get_cm_edit_actions(cm_info $mod, $indent = -1, $sr = null) {
|
||||
$enabledclass = '';
|
||||
}
|
||||
$actions['moveleft'] = new action_menu_link_secondary(
|
||||
new moodle_url($baseurl, array('id' => $mod->id, 'indent' => '-1')),
|
||||
new pix_icon($leftarrow, '', 'moodle', array('class' => 'iconsmall')),
|
||||
new moodle_url($baseurl, ['id' => $mod->id, 'indent' => '0']),
|
||||
new pix_icon($leftarrow, '', 'moodle', ['class' => 'iconsmall']),
|
||||
$str->moveleft,
|
||||
array('class' => 'editing_moveleft ' . $enabledclass, 'data-action' => 'moveleft',
|
||||
'data-keepopen' => true, 'data-sectionreturn' => $sr)
|
||||
[
|
||||
'class' => 'editing_moveleft ' . $enabledclass,
|
||||
'data-action' => ($usecomponents) ? 'cmMoveLeft' : 'moveleft',
|
||||
'data-keepopen' => true,
|
||||
'data-sectionreturn' => $sr,
|
||||
'data-id' => $mod->id,
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -145,3 +145,36 @@ Feature: Course activity controls works as expected
|
||||
| weeks | 0 | "General" | should | should | "8 January - 14 January" |
|
||||
| weeks | 1 | "1 January - 7 January" | should not | should not | "8 January - 14 January" |
|
||||
| weeks | 1 | "General" | should | should not | "8 January - 14 January" |
|
||||
|
||||
@javascript
|
||||
Scenario Outline: Indentation should allow one level only
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format | coursedisplay | numsections | startdate |
|
||||
| Course 1 | C1 | <courseformat> | <coursedisplay> | 5 | 0 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| forum | Test forum name | Test forum description | C1 | forum1 |
|
||||
When I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I open "Test forum name" actions menu
|
||||
Then "Move right" "link" should be visible
|
||||
And "Move left" "link" should not be visible
|
||||
And I click on "Move right" "link" in the "Test forum name" activity
|
||||
And I open "Test forum name" actions menu
|
||||
And "Move right" "link" should not be visible
|
||||
And "Move left" "link" should be visible
|
||||
And I click on "Move left" "link" in the "Test forum name" activity
|
||||
And I open "Test forum name" actions menu
|
||||
And "Move right" "link" should be visible
|
||||
And "Move left" "link" should not be visible
|
||||
|
||||
Examples:
|
||||
| courseformat |
|
||||
| topics |
|
||||
| weeks |
|
||||
|
@ -16,6 +16,8 @@ information provided here is intended especially for developers.
|
||||
parameter. This information can be used by the plugins when enclosing the icons in `.activityiconcontainer .icon` or
|
||||
`.activityiconcontainer .activityicon` containers to determine whether CSS filtering should be applied to the icon. If the icon
|
||||
needs to be rendered as is and not whitened out, the `.nofilter` CSS class needs to be applied to the icon.
|
||||
* Course module indentation has been recovered for course format using components via Move right/left feature.
|
||||
Course formats using components will be allowed to use one level indentation only.
|
||||
|
||||
=== 4.1.2 ===
|
||||
|
||||
|
@ -109,6 +109,19 @@ body:not(.editing) .sitetopic ul.section {
|
||||
a.stealth:hover {
|
||||
color: lighten($link-color, 25%) !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
||||
|
||||
&.indented {
|
||||
.activity-item {
|
||||
border: 0;
|
||||
margin-left: map-get($spacers, 3);
|
||||
}
|
||||
}
|
||||
&.indented + .indented {
|
||||
.activity-item {
|
||||
border-top: $border-width solid $border-color;
|
||||
border-radius: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
|
@ -13994,6 +13994,12 @@ body:not(.editing) .sitetopic ul.section {
|
||||
.section .activity a.stealth:hover {
|
||||
color: #5babf2 !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
.section .activity.indented .activity-item {
|
||||
border: 0;
|
||||
margin-left: 1rem; }
|
||||
.section .activity.indented + .indented .activity-item {
|
||||
border-top: 1px solid #dee2e6;
|
||||
border-radius: unset; }
|
||||
|
||||
.section .label .contentwithoutlink,
|
||||
.section .label .activityinstance {
|
||||
|
@ -13994,6 +13994,12 @@ body:not(.editing) .sitetopic ul.section {
|
||||
.section .activity a.stealth:hover {
|
||||
color: #5babf2 !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
.section .activity.indented .activity-item {
|
||||
border: 0;
|
||||
margin-left: 1rem; }
|
||||
.section .activity.indented + .indented .activity-item {
|
||||
border-top: 1px solid #dee2e6;
|
||||
border-radius: unset; }
|
||||
|
||||
.section .label .contentwithoutlink,
|
||||
.section .label .activityinstance {
|
||||
|
Loading…
x
Reference in New Issue
Block a user