mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 06:18:28 +01:00
Merge branch 'MDL-81681-main' of https://github.com/sarjona/moodle
This commit is contained in:
commit
bb1cddb140
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -6,6 +6,6 @@ define("core_courseformat/local/content/section",["exports","core_courseformat/l
|
||||
* @class core_courseformat/local/content/section
|
||||
* @copyright 2021 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_header=_interopRequireDefault(_header),_dndsection=_interopRequireDefault(_dndsection),_templates=_interopRequireDefault(_templates),_pending=_interopRequireDefault(_pending);class _default extends _dndsection.default{create(){this.name="content_section",this.selectors={SECTION_ITEM:"[data-for='section_title']",CM:'[data-for="cmitem"]',SECTIONINFO:'[data-for="sectioninfo"]',SECTIONBADGES:'[data-region="sectionbadges"]',SHOWSECTION:'[data-action="sectionShow"]',HIDESECTION:'[data-action="sectionHide"]',ACTIONTEXT:".menu-action-text",ICON:".icon"},this.classes={LOCKED:"editinprogress",HASDESCRIPTION:"description",HIDE:"d-none",HIDDEN:"hidden",CURRENT:"current"},this.id=this.element.dataset.id}stateReady(state){if(this.configState(state),this.reactive.isEditing&&this.reactive.supportComponents){const sectionItem=this.getElement(this.selectors.SECTION_ITEM);if(sectionItem){const headerComponent=new _header.default({...this,element:sectionItem,fullregion:this.element});this.configDragDrop(headerComponent)}}this._openSectionIfNecessary()}async _openSectionIfNecessary(){const pageCmInfo=this.reactive.getPageAnchorCmInfo();if(!pageCmInfo||pageCmInfo.sectionid!==this.id)return;await this.reactive.dispatch("sectionContentCollapsed",[this.id],!1);const pendingOpen=new _pending.default("courseformat/section:openSectionIfNecessary");this.element.scrollIntoView({block:"center"}),setTimeout((()=>{this.reactive.dispatch("setPageItem","cm",pageCmInfo.id),pendingOpen.resolve()}),250)}getWatchers(){return[{watch:"section[".concat(this.id,"]:updated"),handler:this._refreshSection}]}validateDropData(dropdata){return("section"!==(null==dropdata?void 0:dropdata.type)||null===this.reactive.sectionReturn)&&super.validateDropData(dropdata)}getLastCm(){const cms=this.getElements(this.selectors.CM);return cms&&0!==cms.length?cms[cms.length-1]:null}_refreshSection(_ref){var _element$dragging,_element$locked,_element$visible,_element$current;let{element:element}=_ref;this.element.classList.toggle(this.classes.DRAGGING,null!==(_element$dragging=element.dragging)&&void 0!==_element$dragging&&_element$dragging),this.element.classList.toggle(this.classes.LOCKED,null!==(_element$locked=element.locked)&&void 0!==_element$locked&&_element$locked),this.element.classList.toggle(this.classes.HIDDEN,null!==(_element$visible=!element.visible)&&void 0!==_element$visible&&_element$visible),this.element.classList.toggle(this.classes.CURRENT,null!==(_element$current=element.current)&&void 0!==_element$current&&_element$current),this.locked=element.locked;const sectioninfo=this.getElement(this.selectors.SECTIONINFO);sectioninfo&§ioninfo.classList.toggle(this.classes.HASDESCRIPTION,element.hasrestrictions),this._updateBadges(element),this._updateActionsMenu(element)}_updateBadges(section){const current=this.getElement("".concat(this.selectors.SECTIONBADGES," [data-type='iscurrent']"));null==current||current.classList.toggle(this.classes.HIDE,!section.current);const hiddenFromStudents=this.getElement("".concat(this.selectors.SECTIONBADGES," [data-type='hiddenfromstudents']"));null==hiddenFromStudents||hiddenFromStudents.classList.toggle(this.classes.HIDE,section.visible)}async _updateActionsMenu(section){var _affectedAction$datas,_affectedAction$datas2;let selector,newAction;section.visible?(selector=this.selectors.SHOWSECTION,newAction="sectionHide"):(selector=this.selectors.HIDESECTION,newAction="sectionShow");const affectedAction=this.getElement(selector);if(!affectedAction)return;affectedAction.dataset.action=newAction;const actionText=affectedAction.querySelector(this.selectors.ACTIONTEXT);if(null!==(_affectedAction$datas=affectedAction.dataset)&&void 0!==_affectedAction$datas&&_affectedAction$datas.swapname&&actionText){const oldText=null==actionText?void 0:actionText.innerText;actionText.innerText=affectedAction.dataset.swapname,affectedAction.dataset.swapname=oldText}const icon=affectedAction.querySelector(this.selectors.ICON);if(null!==(_affectedAction$datas2=affectedAction.dataset)&&void 0!==_affectedAction$datas2&&_affectedAction$datas2.swapicon&&icon){const newIcon=affectedAction.dataset.swapicon;if(newIcon){const pixHtml=await _templates.default.renderPix(newIcon,"core");_templates.default.replaceNode(icon,pixHtml,"")}}}}return _exports.default=_default,_exports.default}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_header=_interopRequireDefault(_header),_dndsection=_interopRequireDefault(_dndsection),_templates=_interopRequireDefault(_templates),_pending=_interopRequireDefault(_pending);class _default extends _dndsection.default{create(){this.name="content_section",this.selectors={SECTION_ITEM:"[data-for='section_title']",CM:'[data-for="cmitem"]',SECTIONINFO:'[data-for="sectioninfo"]',SECTIONBADGES:'[data-region="sectionbadges"]',SHOWSECTION:'[data-action="sectionShow"]',HIDESECTION:'[data-action="sectionHide"]',ACTIONTEXT:".menu-action-text",ICON:".icon"},this.classes={LOCKED:"editinprogress",HASDESCRIPTION:"description",HIDE:"d-none",HIDDEN:"hidden",CURRENT:"current"},this.id=this.element.dataset.id}stateReady(state){if(this.configState(state),this.reactive.isEditing&&this.reactive.supportComponents){const sectionItem=this.getElement(this.selectors.SECTION_ITEM);if(sectionItem){const headerComponent=new _header.default({...this,element:sectionItem,fullregion:this.element});this.configDragDrop(headerComponent)}}this._openSectionIfNecessary()}async _openSectionIfNecessary(){const pageCmInfo=this.reactive.getPageAnchorCmInfo();if(!pageCmInfo||pageCmInfo.sectionid!==this.id)return;await this.reactive.dispatch("sectionContentCollapsed",[this.id],!1);const pendingOpen=new _pending.default("courseformat/section:openSectionIfNecessary");this.element.scrollIntoView({block:"center"}),setTimeout((()=>{this.reactive.dispatch("setPageItem","cm",pageCmInfo.id),pendingOpen.resolve()}),250)}getWatchers(){return[{watch:"section[".concat(this.id,"]:updated"),handler:this._refreshSection}]}validateDropData(dropdata){return("section"!==(null==dropdata?void 0:dropdata.type)||null===this.reactive.sectionReturn)&&super.validateDropData(dropdata)}getLastCm(){const cms=this.getElements(this.selectors.CM);return cms&&0!==cms.length?cms[cms.length-1]:null}_refreshSection(_ref){var _element$dragging,_element$locked,_element$visible,_element$current;let{element:element}=_ref;this.element.classList.toggle(this.classes.DRAGGING,null!==(_element$dragging=element.dragging)&&void 0!==_element$dragging&&_element$dragging),this.element.classList.toggle(this.classes.LOCKED,null!==(_element$locked=element.locked)&&void 0!==_element$locked&&_element$locked),this.element.classList.toggle(this.classes.HIDDEN,null!==(_element$visible=!element.visible)&&void 0!==_element$visible&&_element$visible),this.element.classList.toggle(this.classes.CURRENT,null!==(_element$current=element.current)&&void 0!==_element$current&&_element$current),this.locked=element.locked;const sectioninfo=this.getElement(this.selectors.SECTIONINFO);sectioninfo&§ioninfo.classList.toggle(this.classes.HASDESCRIPTION,element.hasrestrictions),this._updateBadges(element),this._updateActionsMenu(element)}_updateBadges(section){const current=this.getElement("".concat(this.selectors.SECTIONBADGES," [data-type='iscurrent']"));null==current||current.classList.toggle(this.classes.HIDE,!section.current);const hiddenFromStudents=this.getElement("".concat(this.selectors.SECTIONBADGES," [data-type='hiddenfromstudents']"));null==hiddenFromStudents||hiddenFromStudents.classList.toggle(this.classes.HIDE,section.visible)}async _updateActionsMenu(section){var _affectedAction$datas,_affectedAction$datas2;let selector,newAction;section.visible?(selector=this.selectors.SHOWSECTION,newAction="sectionHide"):(selector=this.selectors.HIDESECTION,newAction="sectionShow");const affectedAction=this._getActionMenu(selector);if(!affectedAction)return;affectedAction.dataset.action=newAction;const actionText=affectedAction.querySelector(this.selectors.ACTIONTEXT);if(null!==(_affectedAction$datas=affectedAction.dataset)&&void 0!==_affectedAction$datas&&_affectedAction$datas.swapname&&actionText){const oldText=null==actionText?void 0:actionText.innerText;actionText.innerText=affectedAction.dataset.swapname,affectedAction.dataset.swapname=oldText}const icon=affectedAction.querySelector(this.selectors.ICON);if(null!==(_affectedAction$datas2=affectedAction.dataset)&&void 0!==_affectedAction$datas2&&_affectedAction$datas2.swapicon&&icon){const newIcon=affectedAction.dataset.swapicon;if(newIcon){const pixHtml=await _templates.default.renderPix(newIcon,"core");_templates.default.replaceNode(icon,pixHtml,"")}}}_getActionMenu(selector){return this.getElement(".section_action_menu")?this.getElement(selector):document.querySelector(selector)}}return _exports.default=_default,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=section.min.js.map
|
File diff suppressed because one or more lines are too long
@ -429,7 +429,7 @@ export default class extends BaseComponent {
|
||||
return (cmList.length || sectionInfo.hassummary || sectionInfo.rawtitle);
|
||||
});
|
||||
if (!needsConfirmation) {
|
||||
this.reactive.dispatch('sectionDelete', sectionIds);
|
||||
this._dispatchSectionDelete(sectionIds, target);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -455,11 +455,25 @@ export default class extends BaseComponent {
|
||||
// Stop the default save button behaviour which is to close the modal.
|
||||
e.preventDefault();
|
||||
modal.destroy();
|
||||
this.reactive.dispatch('sectionDelete', sectionIds);
|
||||
this._dispatchSectionDelete(sectionIds, target);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the section delete action and handle the redirection if necessary.
|
||||
*
|
||||
* @param {Array} sectionIds the IDs of the sections to delete.
|
||||
* @param {Element} target the dispatch action element
|
||||
*/
|
||||
async _dispatchSectionDelete(sectionIds, target) {
|
||||
await this.reactive.dispatch('sectionDelete', sectionIds);
|
||||
if (target.baseURI.includes('section.php')) {
|
||||
// Redirect to the course main page if the section is the current page.
|
||||
window.location.href = this.reactive.get('course').baseurl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a toggle cm selection.
|
||||
*
|
||||
|
@ -191,7 +191,7 @@ export default class extends DndSection {
|
||||
newAction = 'sectionShow';
|
||||
}
|
||||
// Find the affected action.
|
||||
const affectedAction = this.getElement(selector);
|
||||
const affectedAction = this._getActionMenu(selector);
|
||||
if (!affectedAction) {
|
||||
return;
|
||||
}
|
||||
@ -214,4 +214,18 @@ export default class extends DndSection {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action menu element from the selector.
|
||||
*
|
||||
* @param {string} selector The selector to find the action menu.
|
||||
* @returns The action menu element.
|
||||
*/
|
||||
_getActionMenu(selector) {
|
||||
if (this.getElement('.section_action_menu')) {
|
||||
return this.getElement(selector);
|
||||
}
|
||||
|
||||
return document.querySelector(selector);
|
||||
}
|
||||
}
|
||||
|
@ -104,14 +104,7 @@ class visibility implements named_templatable, renderable {
|
||||
private function get_option_data(string $name, string $action): array {
|
||||
$baseurl = course_get_url($this->section->course, $this->section);
|
||||
$baseurl->param('sesskey', sesskey());
|
||||
$baseurl->param($name, $this->section->section);
|
||||
|
||||
// The section page is not yet fully reactive and it needs to use the old non-ajax links.
|
||||
$pagesectionid = $this->format->get_sectionid();
|
||||
if ($this->section->id == $pagesectionid) {
|
||||
$baseurl->param('sectionid', $pagesectionid);
|
||||
$action = '';
|
||||
}
|
||||
$baseurl->param($action, $this->section->section);
|
||||
|
||||
return [
|
||||
'description' => get_string("availability_{$name}_help", 'core_courseformat'),
|
||||
|
@ -217,6 +217,6 @@
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['core_courseformat/local/content'], function(component) {
|
||||
component.init('course-format-{{uniqid}}', {}, {{sectionreturn}});
|
||||
component.init('page', {}, {{sectionreturn}});
|
||||
});
|
||||
{{/js}}
|
||||
|
@ -110,3 +110,15 @@ Feature: Single section course page
|
||||
Then I should see "Online users"
|
||||
And I am on the "Course 1 > Section 1" "course > section" page
|
||||
And I should see "Online users"
|
||||
|
||||
@javascript
|
||||
Scenario: Delete a section from the section page redirects to the main course page
|
||||
Given I am on the "C1 > Section 1" "course > section" page
|
||||
And I turn editing mode on
|
||||
And I open the action menu in "page-header" "region"
|
||||
When I choose "Delete" in the open action menu
|
||||
And I click on "Delete" "button" in the "Delete section?" "dialogue"
|
||||
# Section 1 should be removed.
|
||||
Then I should not see "Section 1"
|
||||
# The user should be redirected to the course page.
|
||||
And I should see "General" in the "page" "region"
|
||||
|
@ -94,3 +94,15 @@ Feature: Varify section visibility interface
|
||||
And I open the action menu in "page-header" "region"
|
||||
And I choose "Hide" in the open action menu
|
||||
And I should see "Hidden from students" in the "[data-region='sectionbadges']" "css_element"
|
||||
|
||||
@javascript
|
||||
Scenario: The section action menu should be updated properly when a section is hidden/shown
|
||||
Given I open section "1" edit menu
|
||||
When I choose "Hide" in the open action menu
|
||||
Then I should see "Hidden from students" in the "Section 1" "section"
|
||||
And I open section "1" edit menu
|
||||
And I should see "Show" in the "Section 1" "section"
|
||||
And I press the escape key
|
||||
# Confirm the Section 2 menu hasn't been updated.
|
||||
And I open section "2" edit menu
|
||||
And I should see "Hide" in the "Section 2" "section"
|
||||
|
@ -5,6 +5,6 @@ define("format_topics/section",["exports","core/reactive","core_courseformat/cou
|
||||
* @module format_topics/section
|
||||
* @copyright 2022 Ferran Recio <ferran@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};class HighlightSection extends _reactive.BaseComponent{create(){this.name="format_topics_section",this.selectors={SECTION:"[data-for='section']",SETMARKER:'[data-action="sectionHighlight"]',REMOVEMARKER:'[data-action="sectionUnhighlight"]',ACTIONTEXT:".menu-action-text",ICON:".icon"},this.classes={HIDE:"d-none"},this.formatActions={HIGHLIGHT:"sectionHighlight",UNHIGHLIGHT:"sectionUnhighlight"}}getWatchers(){return[{watch:"section.current:updated",handler:this._refreshHighlight}]}async _refreshHighlight(_ref){var _affectedAction$datas,_affectedAction$datas2;let selector,newAction,{element:element}=_ref;element.current?(selector=this.selectors.SETMARKER,newAction=this.formatActions.UNHIGHLIGHT):(selector=this.selectors.REMOVEMARKER,newAction=this.formatActions.HIGHLIGHT);const affectedAction=this.getElement("".concat(this.selectors.SECTION," ").concat(selector),element.id);if(!affectedAction)return;affectedAction.dataset.action=newAction;const actionText=affectedAction.querySelector(this.selectors.ACTIONTEXT);if(null!==(_affectedAction$datas=affectedAction.dataset)&&void 0!==_affectedAction$datas&&_affectedAction$datas.swapname&&actionText){const oldText=null==actionText?void 0:actionText.innerText;actionText.innerText=affectedAction.dataset.swapname,affectedAction.dataset.swapname=oldText}const icon=affectedAction.querySelector(this.selectors.ICON);if(null!==(_affectedAction$datas2=affectedAction.dataset)&&void 0!==_affectedAction$datas2&&_affectedAction$datas2.swapicon&&icon){const newIcon=affectedAction.dataset.swapicon;if(newIcon){const pixHtml=await _templates.default.renderPix(newIcon,"core");_templates.default.replaceNode(icon,pixHtml,"")}}}}_exports.init=()=>{const courseEditor=(0,_courseeditor.getCurrentCourseEditor)();courseEditor.supportComponents&&courseEditor.isEditing&&new HighlightSection({element:document.getElementById("region-main"),reactive:courseEditor})}}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};class HighlightSection extends _reactive.BaseComponent{create(){this.name="format_topics_section",this.selectors={SETMARKER:'[data-action="sectionHighlight"]',REMOVEMARKER:'[data-action="sectionUnhighlight"]',ACTIONTEXT:".menu-action-text",ICON:".icon"},this.classes={HIDE:"d-none"},this.formatActions={HIGHLIGHT:"sectionHighlight",UNHIGHLIGHT:"sectionUnhighlight"}}getWatchers(){return[{watch:"section.current:updated",handler:this._refreshHighlight}]}async _refreshHighlight(_ref){var _affectedAction$datas,_affectedAction$datas2;let selector,newAction,{element:element}=_ref;element.current?(selector=this.selectors.SETMARKER,newAction=this.formatActions.UNHIGHLIGHT):(selector=this.selectors.REMOVEMARKER,newAction=this.formatActions.HIGHLIGHT);const affectedAction=this.getElement("".concat(selector),element.id);if(!affectedAction)return;affectedAction.dataset.action=newAction;const actionText=affectedAction.querySelector(this.selectors.ACTIONTEXT);if(null!==(_affectedAction$datas=affectedAction.dataset)&&void 0!==_affectedAction$datas&&_affectedAction$datas.swapname&&actionText){const oldText=null==actionText?void 0:actionText.innerText;actionText.innerText=affectedAction.dataset.swapname,affectedAction.dataset.swapname=oldText}const icon=affectedAction.querySelector(this.selectors.ICON);if(null!==(_affectedAction$datas2=affectedAction.dataset)&&void 0!==_affectedAction$datas2&&_affectedAction$datas2.swapicon&&icon){const newIcon=affectedAction.dataset.swapicon;if(newIcon){const pixHtml=await _templates.default.renderPix(newIcon,"core");_templates.default.replaceNode(icon,pixHtml,"")}}}}_exports.init=()=>{const courseEditor=(0,_courseeditor.getCurrentCourseEditor)();courseEditor.supportComponents&&courseEditor.isEditing&&new HighlightSection({element:document.getElementById("page"),reactive:courseEditor})}}));
|
||||
|
||||
//# sourceMappingURL=section.min.js.map
|
File diff suppressed because one or more lines are too long
@ -35,7 +35,6 @@ class HighlightSection extends BaseComponent {
|
||||
this.name = 'format_topics_section';
|
||||
// Default query selectors.
|
||||
this.selectors = {
|
||||
SECTION: `[data-for='section']`,
|
||||
SETMARKER: `[data-action="sectionHighlight"]`,
|
||||
REMOVEMARKER: `[data-action="sectionUnhighlight"]`,
|
||||
ACTIONTEXT: `.menu-action-text`,
|
||||
@ -80,7 +79,7 @@ class HighlightSection extends BaseComponent {
|
||||
newAction = this.formatActions.HIGHLIGHT;
|
||||
}
|
||||
// Find the affected action.
|
||||
const affectedAction = this.getElement(`${this.selectors.SECTION} ${selector}`, element.id);
|
||||
const affectedAction = this.getElement(`${selector}`, element.id);
|
||||
if (!affectedAction) {
|
||||
return;
|
||||
}
|
||||
@ -108,7 +107,7 @@ export const init = () => {
|
||||
const courseEditor = getCurrentCourseEditor();
|
||||
if (courseEditor.supportComponents && courseEditor.isEditing) {
|
||||
new HighlightSection({
|
||||
element: document.getElementById('region-main'),
|
||||
element: document.getElementById('page'),
|
||||
reactive: courseEditor,
|
||||
});
|
||||
}
|
||||
|
@ -1183,7 +1183,7 @@ class behat_course extends behat_base {
|
||||
"/descendant::div[contains(concat(' ', @class, ' '), ' lightbox ')][contains(@style, 'display: none')]";
|
||||
|
||||
// Component based courses do not use lightboxes anymore but js depending.
|
||||
$sectionreadyxpath = "//*[contains(@id,'page-content')]" .
|
||||
$sectionreadyxpath = "//*[contains(@id,'page')]" .
|
||||
"/descendant::*[contains(concat(' ', normalize-space(@class), ' '), ' stateready ')]";
|
||||
|
||||
$duplicationreadyxpath = "$hiddenlightboxxpath | $sectionreadyxpath";
|
||||
|
Loading…
x
Reference in New Issue
Block a user