mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-76713 core_availability: Fix date restriction conflict
* Use a unique ID the date nodes in the HTML tree to be able to find the current node. * Look for nodes in the same tree "leaf" and work on conflicts in this single leaf/branch.
This commit is contained in:
parent
6988b5b328
commit
4f620f537e
@ -0,0 +1,105 @@
|
|||||||
|
@availability @availability_date @javascript
|
||||||
|
Feature: As a teacher I can set availability dates restriction to an activity and see a warning when conflicting dates are set
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the following "courses" exist:
|
||||||
|
| fullname | shortname | format | enablecompletion |
|
||||||
|
| Course 1 | C1 | topics | 1 |
|
||||||
|
And the following "users" exist:
|
||||||
|
| username |
|
||||||
|
| teacher1 |
|
||||||
|
And the following "course enrolments" exist:
|
||||||
|
| user | course | role |
|
||||||
|
| teacher1 | C1 | editingteacher |
|
||||||
|
And the following "activities" exist:
|
||||||
|
| activity | name | intro | introformat | course | content | contentformat | idnumber |
|
||||||
|
| page | PageName1 | PageDesc1 | 1 | C1 | Page 1 | 1 | 1 |
|
||||||
|
|
||||||
|
Scenario: When I set dates to potential conflicting dates in the same subset, I should see a warning.
|
||||||
|
Given I am on the PageName1 "page activity editing" page logged in as teacher1
|
||||||
|
And I expand all fieldsets
|
||||||
|
And I click on "Add restriction..." "button" in the "root" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1" "availability_date > Date Restriction" to "4"
|
||||||
|
And I set the field "Direction" in the "1" "availability_date > Date Restriction" to "from"
|
||||||
|
And I click on "Add restriction..." "button" in the "root" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "2" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "2" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "2" "availability_date > Date Restriction" to "6"
|
||||||
|
And I set the field "Direction" in the "2" "availability_date > Date Restriction" to "until"
|
||||||
|
And I click on "Add restriction..." "button" in the "root" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "3" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "3" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "3" "availability_date > Date Restriction" to "6"
|
||||||
|
When I set the field "Direction" in the "3" "availability_date > Date Restriction" to "from"
|
||||||
|
Then I should see "Conflicts with other date restrictions"
|
||||||
|
|
||||||
|
Scenario: If there are conflicting dates in the same subset, I should not see a warning if condition are separated by "any".
|
||||||
|
Given I am on the PageName1 "page activity editing" page logged in as teacher1
|
||||||
|
And I expand all fieldsets
|
||||||
|
And I click on "Add restriction..." "button" in the "root" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Restriction set" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I click on "Add restriction..." "button" in the "1" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1.1" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1.1" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1.1" "availability_date > Date Restriction" to "4"
|
||||||
|
And I set the field "Direction" in the "1.1" "availability_date > Date Restriction" to "from"
|
||||||
|
And I click on "Add restriction..." "button" in the "1" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1.2" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1.2" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1.2" "availability_date > Date Restriction" to "6"
|
||||||
|
And I set the field "Direction" in the "1.2" "availability_date > Date Restriction" to "until"
|
||||||
|
And I click on "Add restriction..." "button" in the "1" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1.3" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1.3" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1.3" "availability_date > Date Restriction" to "6"
|
||||||
|
And I set the field "Direction" in the "1.3" "availability_date > Date Restriction" to "from"
|
||||||
|
When I set the field "Required restrictions" in the "1" "core_availability > Set Of Restrictions" to "any"
|
||||||
|
Then I should not see "Conflicts with other date restrictions"
|
||||||
|
|
||||||
|
Scenario: There should a conflicting availability dates are in the same subset separated by "all".
|
||||||
|
Given I am on the PageName1 "page activity editing" page logged in as teacher1
|
||||||
|
And I expand all fieldsets
|
||||||
|
# Root level: Student "must" match the following.
|
||||||
|
And I click on "Add restriction..." "button" in the "root" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Restriction set" "button" in the "Add restriction..." "dialogue"
|
||||||
|
# This is the second level: Student "must" match any of the following.
|
||||||
|
And I click on "Add restriction..." "button" in the "1" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Restriction set" "button" in the "Add restriction..." "dialogue"
|
||||||
|
# And now the third and final level.
|
||||||
|
And I click on "Add restriction..." "button" in the "1.1" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1.1.1" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1.1.1" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1.1.1" "availability_date > Date Restriction" to "2"
|
||||||
|
And I set the field "Direction" in the "1.1.1" "availability_date > Date Restriction" to "from"
|
||||||
|
And I click on "Add restriction..." "button" in the "1.1" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1.1.2" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1.1.2" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1.1.2" "availability_date > Date Restriction" to "3"
|
||||||
|
And I set the field "Direction" in the "1.1.2" "availability_date > Date Restriction" to "until"
|
||||||
|
# Then add a restriction to the second level.
|
||||||
|
And I click on "Add restriction..." "button" in the "1" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Restriction set" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I click on "Add restriction..." "button" in the "1.2" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1.2.1" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1.2.1" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1.2.1" "availability_date > Date Restriction" to "4"
|
||||||
|
And I set the field "Direction" in the "1.2.1" "availability_date > Date Restriction" to "from"
|
||||||
|
And I click on "Add restriction..." "button" in the "1.2" "core_availability > Availability Button Area"
|
||||||
|
And I click on "Date" "button" in the "Add restriction..." "dialogue"
|
||||||
|
And I set the field "year" in the "1.2.2" "availability_date > Date Restriction" to "2023"
|
||||||
|
And I set the field "Month" in the "1.2.2" "availability_date > Date Restriction" to "April"
|
||||||
|
And I set the field "day" in the "1.2.2" "availability_date > Date Restriction" to "3"
|
||||||
|
When I set the field "Direction" in the "1.2.2" "availability_date > Date Restriction" to "until"
|
||||||
|
# Same subset, we can detect conflicts.
|
||||||
|
Then I should see "Conflicts with other date restrictions"
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
// This file is part of Moodle - http://moodle.org/
|
||||||
|
//
|
||||||
|
// Moodle is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Moodle is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
use Behat\Mink\Element\NodeElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Behat availabilty-related steps definitions.
|
||||||
|
*
|
||||||
|
* @package availability_date
|
||||||
|
* @category test
|
||||||
|
* @copyright 2023 Laurent David <laurent.david@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
class behat_availability_date extends behat_base {
|
||||||
|
/**
|
||||||
|
* Return the list of partial named selectors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function get_partial_named_selectors(): array {
|
||||||
|
return [
|
||||||
|
new behat_component_named_selector(
|
||||||
|
'Date Restriction', ["//div[h3[@data-restriction-order=%locator% and contains(text(), 'Date restriction')]]"]
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -65,6 +65,11 @@ M.availability_date.form.getNode = function(json) {
|
|||||||
// Set default time that corresponds to the HTML selectors.
|
// Set default time that corresponds to the HTML selectors.
|
||||||
node.setData('time', this.defaultTime);
|
node.setData('time', this.defaultTime);
|
||||||
}
|
}
|
||||||
|
if (json.nodeUID === undefined) {
|
||||||
|
var miliTime = new Date();
|
||||||
|
json.nodeUID = miliTime.getTime();
|
||||||
|
}
|
||||||
|
node.setData('nodeUID', json.nodeUID);
|
||||||
if (json.d !== undefined) {
|
if (json.d !== undefined) {
|
||||||
node.one('select[name=direction]').set('value', json.d);
|
node.one('select[name=direction]').set('value', json.d);
|
||||||
}
|
}
|
||||||
@ -114,7 +119,7 @@ M.availability_date.form.getNode = function(json) {
|
|||||||
* gets an AJAX response.
|
* gets an AJAX response.
|
||||||
*
|
*
|
||||||
* @method updateTime
|
* @method updateTime
|
||||||
* @param {Y.Node} component Node for plugin controls
|
* @param {Y.Node} node Node for plugin controls
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.updateTime = function(node) {
|
M.availability_date.form.updateTime = function(node) {
|
||||||
// After a change to the date/time we need to recompute the
|
// After a change to the date/time we need to recompute the
|
||||||
@ -140,39 +145,53 @@ M.availability_date.form.updateTime = function(node) {
|
|||||||
M.availability_date.form.fillValue = function(value, node) {
|
M.availability_date.form.fillValue = function(value, node) {
|
||||||
value.d = node.one('select[name=direction]').get('value');
|
value.d = node.one('select[name=direction]').get('value');
|
||||||
value.t = parseInt(node.getData('time'), 10);
|
value.t = parseInt(node.getData('time'), 10);
|
||||||
|
value.nodeUID = node.getData('nodeUID');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List out Date node value in an array node.
|
* List out Date node value in the same branch.
|
||||||
*
|
*
|
||||||
* This will go through all array node and list from earlier date node to current date node.
|
* This will go through all array node and list nodes that are sibling of the current node.
|
||||||
*
|
*
|
||||||
* @method convertTreeDateValue
|
* @method findAllDateSiblings
|
||||||
* @param {array} tree Tree node to convert
|
* @param {Array} tree Tree items to convert
|
||||||
* @param {array} arrayDateNode
|
* @param {Number} nodeUIDToFind node UID to find.
|
||||||
* @param {array} currentNode current node.
|
* @return {Array|null} array of surrounding date avaiability values
|
||||||
*
|
|
||||||
* @return {array} arrayDateNode
|
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, currentNode) {
|
M.availability_date.form.findAllDateSiblings = function(tree, nodeUIDToFind) {
|
||||||
var shouldSkip = false;
|
var itemValue = null;
|
||||||
tree.forEach(function(node) {
|
var siblingsFinderRecursive = function(itemsTree) {
|
||||||
if (shouldSkip) {
|
var dateSiblings = [];
|
||||||
return;
|
var nodeFound = false;
|
||||||
}
|
var index;
|
||||||
if (node.type === 'date') {
|
var childDates;
|
||||||
// We go through all tree node, if we meet the current node then return.
|
var currentOp = itemsTree.op !== undefined ? itemsTree.op : null;
|
||||||
if (node.t === parseInt(currentNode.getData('time'), 10)
|
if (itemsTree.c !== undefined) {
|
||||||
&& currentNode.one('select[name=direction]').get('value') == node.d) {
|
var children = itemsTree.c;
|
||||||
shouldSkip = true;
|
for (index = 0; index < children.length; index++) {
|
||||||
return;
|
itemValue = children.at(index);
|
||||||
|
if (itemValue.type === undefined) {
|
||||||
|
childDates = siblingsFinderRecursive(itemValue);
|
||||||
|
if (childDates) {
|
||||||
|
return childDates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itemValue.type === 'date') {
|
||||||
|
// We go through all tree node, if we meet the current node then we add all nodes in the current branch.
|
||||||
|
if (nodeUIDToFind === itemValue.nodeUID) {
|
||||||
|
nodeFound = true;
|
||||||
|
} else if (currentOp === '&') {
|
||||||
|
dateSiblings.push(itemValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nodeFound) {
|
||||||
|
return dateSiblings;
|
||||||
}
|
}
|
||||||
arrayDateNode.push(node);
|
|
||||||
} else if (node.type === undefined) {
|
|
||||||
M.availability_date.form.convertTreeDateValue(node.c, arrayDateNode, currentNode);
|
|
||||||
}
|
}
|
||||||
});
|
return null;
|
||||||
return arrayDateNode;
|
};
|
||||||
|
return siblingsFinderRecursive(tree);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,37 +200,34 @@ M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, cu
|
|||||||
* This will check current date node with all date node in tree node.
|
* This will check current date node with all date node in tree node.
|
||||||
*
|
*
|
||||||
* @method checkConditionDate
|
* @method checkConditionDate
|
||||||
* @param {array} currentNode The curent node.
|
* @param {Y.Node} currentNode The curent node.
|
||||||
*
|
*
|
||||||
* @return {boolean} error Return true if the date is conflict.
|
* @return {boolean} error Return true if the date is conflict.
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.checkConditionDate = function(currentNode) {
|
M.availability_date.form.checkConditionDate = function(currentNode) {
|
||||||
var error = false;
|
var error = false;
|
||||||
if (M.core_availability.form.rootList.getValue().op === '&') {
|
var currentNodeUID = currentNode.getData('nodeUID');
|
||||||
var jsValue = M.core_availability.form.rootList.getValue().c;
|
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
||||||
var arrayDateNode = M.availability_date.form.convertTreeDateValue(jsValue, [], currentNode);
|
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
||||||
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
var dateSiblings = M.availability_date.form.findAllDateSiblings(
|
||||||
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
M.core_availability.form.rootList.getValue(),
|
||||||
arrayDateNode.forEach(function(checkNode) {
|
currentNodeUID);
|
||||||
|
if (dateSiblings) {
|
||||||
|
dateSiblings.forEach(function(dateSibling) {
|
||||||
// Validate if the date is conflict.
|
// Validate if the date is conflict.
|
||||||
if (checkNode.d === '<') {
|
if (dateSibling.d === '<') {
|
||||||
if (currentNodeDirection === '>=' && currentNodeTime >= checkNode.t) {
|
if (currentNodeDirection === '>=' && currentNodeTime >= dateSibling.t) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentNodeDirection === '<' && currentNodeTime <= checkNode.t) {
|
if (currentNodeDirection === '<' && currentNodeTime <= dateSibling.t) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
});
|
});
|
||||||
return error;
|
|
||||||
} else {
|
|
||||||
if (currentNode.one('div > .badge-warning')) {
|
|
||||||
currentNode.one('div > .badge-warning').remove();
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
return error;
|
||||||
};
|
};
|
||||||
|
|
||||||
M.availability_date.form.fillErrors = function(errors, node) {
|
M.availability_date.form.fillErrors = function(errors, node) {
|
||||||
|
@ -1 +1 @@
|
|||||||
YUI.add("moodle-availability_date-form",function(o,e){M.availability_date=M.availability_date||{},M.availability_date.form=o.Object(M.core_availability.plugin),M.availability_date.form.initInner=function(e,a){this.html=e,this.defaultTime=a},M.availability_date.form.getNode=function(e){var t,i,a='<span class="col-form-label pr-3">'+M.util.get_string("direction_before","availability_date")+'</span> <span class="availability-group"><label><span class="accesshide">'+M.util.get_string("direction_label","availability_date")+' </span><select name="direction" class="custom-select"><option value=">=">'+M.util.get_string("direction_from","availability_date")+'</option><option value="<">'+M.util.get_string("direction_until","availability_date")+"</option></select></label></span> "+this.html,n=o.Node.create("<span>"+a+"</span>");return e.t!==undefined?(n.setData("time",e.t),n.all("select:not([name=direction])").each(function(e){e.set("disabled",!0)}),a=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=fromtime&time="+e.t,o.io(a,{on:{success:function(e,a){var t,i,l=o.JSON.parse(a.responseText);for(t in l)(i=n.one("select[name=x\\["+t+"\\]]")).set("value",""+l[t]),i.set("disabled",!1)},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})):n.setData("time",this.defaultTime),e.d!==undefined&&n.one("select[name=direction]").set("value",e.d),M.availability_date.form.addedEvents||(M.availability_date.form.addedEvents=!0,(a=o.one(".availability-field")).delegate("change",function(){M.core_availability.form.update()},".availability_date select[name=direction]"),a.delegate("change",function(){M.availability_date.form.updateTime(this.ancestor("span.availability_date"))},".availability_date select:not([name=direction])")),n.one("a[href=#]")&&(M.form.dateselector.init_single_date_selector(n),t=n.one("select[name=x\\[year\\]]"),i=t.set,t.set=function(e,a){i.call(t,e,a),"selectedIndex"===e&&setTimeout(function(){M.availability_date.form.updateTime(n)},0)}),n},M.availability_date.form.updateTime=function(t){var e=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=totime&year="+t.one("select[name=x\\[year\\]]").get("value")+"&month="+t.one("select[name=x\\[month\\]]").get("value")+"&day="+t.one("select[name=x\\[day\\]]").get("value")+"&hour="+t.one("select[name=x\\[hour\\]]").get("value")+"&minute="+t.one("select[name=x\\[minute\\]]").get("value");o.io(e,{on:{success:function(e,a){t.setData("time",a.responseText),M.core_availability.form.update()},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})},M.availability_date.form.fillValue=function(e,a){e.d=a.one("select[name=direction]").get("value"),e.t=parseInt(a.getData("time"),10)},M.availability_date.form.convertTreeDateValue=function(e,a,t){var i=!1;return e.forEach(function(e){i||("date"===e.type?e.t!==parseInt(t.getData("time"),10)||t.one("select[name=direction]").get("value")!=e.d?a.push(e):i=!0:e.type===undefined&&M.availability_date.form.convertTreeDateValue(e.c,a,t))}),a},M.availability_date.form.checkConditionDate=function(e){var a,t,i,l=!1;return"&"===M.core_availability.form.rootList.getValue().op?(a=M.core_availability.form.rootList.getValue().c,a=M.availability_date.form.convertTreeDateValue(a,[],e),t=e.one("select[name=direction]").get("value"),i=parseInt(e.getData("time"),10),a.forEach(function(e){return"<"===e.d?">="===t&&i>=e.t&&(l=!0):"<"===t&&i<=e.t&&(l=!0),l})):e.one("div > .badge-warning")&&e.one("div > .badge-warning").remove(),l},M.availability_date.form.fillErrors=function(e,a){M.availability_date.form.checkConditionDate(a)&&e.push("availability_date:error_dateconflict")}},"@VERSION@",{requires:["base","node","event","io","moodle-core_availability-form"]});
|
YUI.add("moodle-availability_date-form",function(o,e){M.availability_date=M.availability_date||{},M.availability_date.form=o.Object(M.core_availability.plugin),M.availability_date.form.initInner=function(e,a){this.html=e,this.defaultTime=a},M.availability_date.form.getNode=function(e){var t,i,a='<span class="col-form-label pr-3">'+M.util.get_string("direction_before","availability_date")+'</span> <span class="availability-group"><label><span class="accesshide">'+M.util.get_string("direction_label","availability_date")+' </span><select name="direction" class="custom-select"><option value=">=">'+M.util.get_string("direction_from","availability_date")+'</option><option value="<">'+M.util.get_string("direction_until","availability_date")+"</option></select></label></span> "+this.html,l=o.Node.create("<span>"+a+"</span>");return e.t!==undefined?(l.setData("time",e.t),l.all("select:not([name=direction])").each(function(e){e.set("disabled",!0)}),a=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=fromtime&time="+e.t,o.io(a,{on:{success:function(e,a){var t,i,n=o.JSON.parse(a.responseText);for(t in n)(i=l.one("select[name=x\\["+t+"\\]]")).set("value",""+n[t]),i.set("disabled",!1)},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})):l.setData("time",this.defaultTime),e.nodeUID===undefined&&(a=new Date,e.nodeUID=a.getTime()),l.setData("nodeUID",e.nodeUID),e.d!==undefined&&l.one("select[name=direction]").set("value",e.d),M.availability_date.form.addedEvents||(M.availability_date.form.addedEvents=!0,(a=o.one(".availability-field")).delegate("change",function(){M.core_availability.form.update()},".availability_date select[name=direction]"),a.delegate("change",function(){M.availability_date.form.updateTime(this.ancestor("span.availability_date"))},".availability_date select:not([name=direction])")),l.one("a[href=#]")&&(M.form.dateselector.init_single_date_selector(l),t=l.one("select[name=x\\[year\\]]"),i=t.set,t.set=function(e,a){i.call(t,e,a),"selectedIndex"===e&&setTimeout(function(){M.availability_date.form.updateTime(l)},0)}),l},M.availability_date.form.updateTime=function(t){var e=M.cfg.wwwroot+"/availability/condition/date/ajax.php?action=totime&year="+t.one("select[name=x\\[year\\]]").get("value")+"&month="+t.one("select[name=x\\[month\\]]").get("value")+"&day="+t.one("select[name=x\\[day\\]]").get("value")+"&hour="+t.one("select[name=x\\[hour\\]]").get("value")+"&minute="+t.one("select[name=x\\[minute\\]]").get("value");o.io(e,{on:{success:function(e,a){t.setData("time",a.responseText),M.core_availability.form.update()},failure:function(){window.alert(M.util.get_string("ajaxerror","availability_date"))}}})},M.availability_date.form.fillValue=function(e,a){e.d=a.one("select[name=direction]").get("value"),e.t=parseInt(a.getData("time"),10),e.nodeUID=a.getData("nodeUID")},M.availability_date.form.findAllDateSiblings=function(e,d){var r,c=function(e){var a,t,i,n=[],l=!1,o=e.op!==undefined?e.op:null;if(e.c!==undefined){for(i=e.c,a=0;a<i.length;a++){if((r=i.at(a)).type===undefined&&(t=c(r)))return t;"date"===r.type&&(d===r.nodeUID?l=!0:"&"===o&&n.push(r))}if(l)return n}return null};return c(e)},M.availability_date.form.checkConditionDate=function(e){var a=!1,t=e.getData("nodeUID"),i=e.one("select[name=direction]").get("value"),n=parseInt(e.getData("time"),10),e=M.availability_date.form.findAllDateSiblings(M.core_availability.form.rootList.getValue(),t);return e&&e.forEach(function(e){return"<"===e.d?">="===i&&n>=e.t&&(a=!0):"<"===i&&n<=e.t&&(a=!0),a}),a},M.availability_date.form.fillErrors=function(e,a){M.availability_date.form.checkConditionDate(a)&&e.push("availability_date:error_dateconflict")}},"@VERSION@",{requires:["base","node","event","io","moodle-core_availability-form"]});
|
@ -65,6 +65,11 @@ M.availability_date.form.getNode = function(json) {
|
|||||||
// Set default time that corresponds to the HTML selectors.
|
// Set default time that corresponds to the HTML selectors.
|
||||||
node.setData('time', this.defaultTime);
|
node.setData('time', this.defaultTime);
|
||||||
}
|
}
|
||||||
|
if (json.nodeUID === undefined) {
|
||||||
|
var miliTime = new Date();
|
||||||
|
json.nodeUID = miliTime.getTime();
|
||||||
|
}
|
||||||
|
node.setData('nodeUID', json.nodeUID);
|
||||||
if (json.d !== undefined) {
|
if (json.d !== undefined) {
|
||||||
node.one('select[name=direction]').set('value', json.d);
|
node.one('select[name=direction]').set('value', json.d);
|
||||||
}
|
}
|
||||||
@ -114,7 +119,7 @@ M.availability_date.form.getNode = function(json) {
|
|||||||
* gets an AJAX response.
|
* gets an AJAX response.
|
||||||
*
|
*
|
||||||
* @method updateTime
|
* @method updateTime
|
||||||
* @param {Y.Node} component Node for plugin controls
|
* @param {Y.Node} node Node for plugin controls
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.updateTime = function(node) {
|
M.availability_date.form.updateTime = function(node) {
|
||||||
// After a change to the date/time we need to recompute the
|
// After a change to the date/time we need to recompute the
|
||||||
@ -140,39 +145,53 @@ M.availability_date.form.updateTime = function(node) {
|
|||||||
M.availability_date.form.fillValue = function(value, node) {
|
M.availability_date.form.fillValue = function(value, node) {
|
||||||
value.d = node.one('select[name=direction]').get('value');
|
value.d = node.one('select[name=direction]').get('value');
|
||||||
value.t = parseInt(node.getData('time'), 10);
|
value.t = parseInt(node.getData('time'), 10);
|
||||||
|
value.nodeUID = node.getData('nodeUID');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List out Date node value in an array node.
|
* List out Date node value in the same branch.
|
||||||
*
|
*
|
||||||
* This will go through all array node and list from earlier date node to current date node.
|
* This will go through all array node and list nodes that are sibling of the current node.
|
||||||
*
|
*
|
||||||
* @method convertTreeDateValue
|
* @method findAllDateSiblings
|
||||||
* @param {array} tree Tree node to convert
|
* @param {Array} tree Tree items to convert
|
||||||
* @param {array} arrayDateNode
|
* @param {Number} nodeUIDToFind node UID to find.
|
||||||
* @param {array} currentNode current node.
|
* @return {Array|null} array of surrounding date avaiability values
|
||||||
*
|
|
||||||
* @return {array} arrayDateNode
|
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, currentNode) {
|
M.availability_date.form.findAllDateSiblings = function(tree, nodeUIDToFind) {
|
||||||
var shouldSkip = false;
|
var itemValue = null;
|
||||||
tree.forEach(function(node) {
|
var siblingsFinderRecursive = function(itemsTree) {
|
||||||
if (shouldSkip) {
|
var dateSiblings = [];
|
||||||
return;
|
var nodeFound = false;
|
||||||
}
|
var index;
|
||||||
if (node.type === 'date') {
|
var childDates;
|
||||||
// We go through all tree node, if we meet the current node then return.
|
var currentOp = itemsTree.op !== undefined ? itemsTree.op : null;
|
||||||
if (node.t === parseInt(currentNode.getData('time'), 10)
|
if (itemsTree.c !== undefined) {
|
||||||
&& currentNode.one('select[name=direction]').get('value') == node.d) {
|
var children = itemsTree.c;
|
||||||
shouldSkip = true;
|
for (index = 0; index < children.length; index++) {
|
||||||
return;
|
itemValue = children.at(index);
|
||||||
|
if (itemValue.type === undefined) {
|
||||||
|
childDates = siblingsFinderRecursive(itemValue);
|
||||||
|
if (childDates) {
|
||||||
|
return childDates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itemValue.type === 'date') {
|
||||||
|
// We go through all tree node, if we meet the current node then we add all nodes in the current branch.
|
||||||
|
if (nodeUIDToFind === itemValue.nodeUID) {
|
||||||
|
nodeFound = true;
|
||||||
|
} else if (currentOp === '&') {
|
||||||
|
dateSiblings.push(itemValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nodeFound) {
|
||||||
|
return dateSiblings;
|
||||||
}
|
}
|
||||||
arrayDateNode.push(node);
|
|
||||||
} else if (node.type === undefined) {
|
|
||||||
M.availability_date.form.convertTreeDateValue(node.c, arrayDateNode, currentNode);
|
|
||||||
}
|
}
|
||||||
});
|
return null;
|
||||||
return arrayDateNode;
|
};
|
||||||
|
return siblingsFinderRecursive(tree);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -181,37 +200,34 @@ M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, cu
|
|||||||
* This will check current date node with all date node in tree node.
|
* This will check current date node with all date node in tree node.
|
||||||
*
|
*
|
||||||
* @method checkConditionDate
|
* @method checkConditionDate
|
||||||
* @param {array} currentNode The curent node.
|
* @param {Y.Node} currentNode The curent node.
|
||||||
*
|
*
|
||||||
* @return {boolean} error Return true if the date is conflict.
|
* @return {boolean} error Return true if the date is conflict.
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.checkConditionDate = function(currentNode) {
|
M.availability_date.form.checkConditionDate = function(currentNode) {
|
||||||
var error = false;
|
var error = false;
|
||||||
if (M.core_availability.form.rootList.getValue().op === '&') {
|
var currentNodeUID = currentNode.getData('nodeUID');
|
||||||
var jsValue = M.core_availability.form.rootList.getValue().c;
|
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
||||||
var arrayDateNode = M.availability_date.form.convertTreeDateValue(jsValue, [], currentNode);
|
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
||||||
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
var dateSiblings = M.availability_date.form.findAllDateSiblings(
|
||||||
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
M.core_availability.form.rootList.getValue(),
|
||||||
arrayDateNode.forEach(function(checkNode) {
|
currentNodeUID);
|
||||||
|
if (dateSiblings) {
|
||||||
|
dateSiblings.forEach(function(dateSibling) {
|
||||||
// Validate if the date is conflict.
|
// Validate if the date is conflict.
|
||||||
if (checkNode.d === '<') {
|
if (dateSibling.d === '<') {
|
||||||
if (currentNodeDirection === '>=' && currentNodeTime >= checkNode.t) {
|
if (currentNodeDirection === '>=' && currentNodeTime >= dateSibling.t) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentNodeDirection === '<' && currentNodeTime <= checkNode.t) {
|
if (currentNodeDirection === '<' && currentNodeTime <= dateSibling.t) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
});
|
});
|
||||||
return error;
|
|
||||||
} else {
|
|
||||||
if (currentNode.one('div > .badge-warning')) {
|
|
||||||
currentNode.one('div > .badge-warning').remove();
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
return error;
|
||||||
};
|
};
|
||||||
|
|
||||||
M.availability_date.form.fillErrors = function(errors, node) {
|
M.availability_date.form.fillErrors = function(errors, node) {
|
||||||
|
100
availability/condition/date/yui/src/form/js/form.js
vendored
100
availability/condition/date/yui/src/form/js/form.js
vendored
@ -63,6 +63,11 @@ M.availability_date.form.getNode = function(json) {
|
|||||||
// Set default time that corresponds to the HTML selectors.
|
// Set default time that corresponds to the HTML selectors.
|
||||||
node.setData('time', this.defaultTime);
|
node.setData('time', this.defaultTime);
|
||||||
}
|
}
|
||||||
|
if (json.nodeUID === undefined) {
|
||||||
|
var miliTime = new Date();
|
||||||
|
json.nodeUID = miliTime.getTime();
|
||||||
|
}
|
||||||
|
node.setData('nodeUID', json.nodeUID);
|
||||||
if (json.d !== undefined) {
|
if (json.d !== undefined) {
|
||||||
node.one('select[name=direction]').set('value', json.d);
|
node.one('select[name=direction]').set('value', json.d);
|
||||||
}
|
}
|
||||||
@ -112,7 +117,7 @@ M.availability_date.form.getNode = function(json) {
|
|||||||
* gets an AJAX response.
|
* gets an AJAX response.
|
||||||
*
|
*
|
||||||
* @method updateTime
|
* @method updateTime
|
||||||
* @param {Y.Node} component Node for plugin controls
|
* @param {Y.Node} node Node for plugin controls
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.updateTime = function(node) {
|
M.availability_date.form.updateTime = function(node) {
|
||||||
// After a change to the date/time we need to recompute the
|
// After a change to the date/time we need to recompute the
|
||||||
@ -138,39 +143,53 @@ M.availability_date.form.updateTime = function(node) {
|
|||||||
M.availability_date.form.fillValue = function(value, node) {
|
M.availability_date.form.fillValue = function(value, node) {
|
||||||
value.d = node.one('select[name=direction]').get('value');
|
value.d = node.one('select[name=direction]').get('value');
|
||||||
value.t = parseInt(node.getData('time'), 10);
|
value.t = parseInt(node.getData('time'), 10);
|
||||||
|
value.nodeUID = node.getData('nodeUID');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List out Date node value in an array node.
|
* List out Date node value in the same branch.
|
||||||
*
|
*
|
||||||
* This will go through all array node and list from earlier date node to current date node.
|
* This will go through all array node and list nodes that are sibling of the current node.
|
||||||
*
|
*
|
||||||
* @method convertTreeDateValue
|
* @method findAllDateSiblings
|
||||||
* @param {array} tree Tree node to convert
|
* @param {Array} tree Tree items to convert
|
||||||
* @param {array} arrayDateNode
|
* @param {Number} nodeUIDToFind node UID to find.
|
||||||
* @param {array} currentNode current node.
|
* @return {Array|null} array of surrounding date avaiability values
|
||||||
*
|
|
||||||
* @return {array} arrayDateNode
|
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, currentNode) {
|
M.availability_date.form.findAllDateSiblings = function(tree, nodeUIDToFind) {
|
||||||
var shouldSkip = false;
|
var itemValue = null;
|
||||||
tree.forEach(function(node) {
|
var siblingsFinderRecursive = function(itemsTree) {
|
||||||
if (shouldSkip) {
|
var dateSiblings = [];
|
||||||
return;
|
var nodeFound = false;
|
||||||
}
|
var index;
|
||||||
if (node.type === 'date') {
|
var childDates;
|
||||||
// We go through all tree node, if we meet the current node then return.
|
var currentOp = itemsTree.op !== undefined ? itemsTree.op : null;
|
||||||
if (node.t === parseInt(currentNode.getData('time'), 10)
|
if (itemsTree.c !== undefined) {
|
||||||
&& currentNode.one('select[name=direction]').get('value') == node.d) {
|
var children = itemsTree.c;
|
||||||
shouldSkip = true;
|
for (index = 0; index < children.length; index++) {
|
||||||
return;
|
itemValue = children.at(index);
|
||||||
|
if (itemValue.type === undefined) {
|
||||||
|
childDates = siblingsFinderRecursive(itemValue);
|
||||||
|
if (childDates) {
|
||||||
|
return childDates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (itemValue.type === 'date') {
|
||||||
|
// We go through all tree node, if we meet the current node then we add all nodes in the current branch.
|
||||||
|
if (nodeUIDToFind === itemValue.nodeUID) {
|
||||||
|
nodeFound = true;
|
||||||
|
} else if (currentOp === '&') {
|
||||||
|
dateSiblings.push(itemValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nodeFound) {
|
||||||
|
return dateSiblings;
|
||||||
}
|
}
|
||||||
arrayDateNode.push(node);
|
|
||||||
} else if (node.type === undefined) {
|
|
||||||
M.availability_date.form.convertTreeDateValue(node.c, arrayDateNode, currentNode);
|
|
||||||
}
|
}
|
||||||
});
|
return null;
|
||||||
return arrayDateNode;
|
};
|
||||||
|
return siblingsFinderRecursive(tree);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,37 +198,34 @@ M.availability_date.form.convertTreeDateValue = function(tree, arrayDateNode, cu
|
|||||||
* This will check current date node with all date node in tree node.
|
* This will check current date node with all date node in tree node.
|
||||||
*
|
*
|
||||||
* @method checkConditionDate
|
* @method checkConditionDate
|
||||||
* @param {array} currentNode The curent node.
|
* @param {Y.Node} currentNode The curent node.
|
||||||
*
|
*
|
||||||
* @return {boolean} error Return true if the date is conflict.
|
* @return {boolean} error Return true if the date is conflict.
|
||||||
*/
|
*/
|
||||||
M.availability_date.form.checkConditionDate = function(currentNode) {
|
M.availability_date.form.checkConditionDate = function(currentNode) {
|
||||||
var error = false;
|
var error = false;
|
||||||
if (M.core_availability.form.rootList.getValue().op === '&') {
|
var currentNodeUID = currentNode.getData('nodeUID');
|
||||||
var jsValue = M.core_availability.form.rootList.getValue().c;
|
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
||||||
var arrayDateNode = M.availability_date.form.convertTreeDateValue(jsValue, [], currentNode);
|
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
||||||
var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
|
var dateSiblings = M.availability_date.form.findAllDateSiblings(
|
||||||
var currentNodeTime = parseInt(currentNode.getData('time'), 10);
|
M.core_availability.form.rootList.getValue(),
|
||||||
arrayDateNode.forEach(function(checkNode) {
|
currentNodeUID);
|
||||||
|
if (dateSiblings) {
|
||||||
|
dateSiblings.forEach(function(dateSibling) {
|
||||||
// Validate if the date is conflict.
|
// Validate if the date is conflict.
|
||||||
if (checkNode.d === '<') {
|
if (dateSibling.d === '<') {
|
||||||
if (currentNodeDirection === '>=' && currentNodeTime >= checkNode.t) {
|
if (currentNodeDirection === '>=' && currentNodeTime >= dateSibling.t) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentNodeDirection === '<' && currentNodeTime <= checkNode.t) {
|
if (currentNodeDirection === '<' && currentNodeTime <= dateSibling.t) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
});
|
});
|
||||||
return error;
|
|
||||||
} else {
|
|
||||||
if (currentNode.one('div > .badge-warning')) {
|
|
||||||
currentNode.one('div > .badge-warning').remove();
|
|
||||||
}
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
return error;
|
||||||
};
|
};
|
||||||
|
|
||||||
M.availability_date.form.fillErrors = function(errors, node) {
|
M.availability_date.form.fillErrors = function(errors, node) {
|
||||||
|
67
availability/tests/behat/behat_availability.php
Normal file
67
availability/tests/behat/behat_availability.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
// This file is part of Moodle - http://moodle.org/
|
||||||
|
//
|
||||||
|
// Moodle is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Moodle is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
require_once(__DIR__ . '/../../../lib/behat/behat_base.php');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Availability related behat steps and selectors definitions.
|
||||||
|
*
|
||||||
|
* @package core_availability
|
||||||
|
* @category test
|
||||||
|
* @copyright 2023 Amaia Anabitarte <amaia@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
class behat_availability extends behat_base {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the list of partial named selectors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function get_partial_named_selectors(): array {
|
||||||
|
return [
|
||||||
|
new behat_component_named_selector(
|
||||||
|
'Activity availability', [
|
||||||
|
".//li[contains(concat(' ', normalize-space(@class), ' '), ' activity ')]"
|
||||||
|
. "[descendant::*[contains(normalize-space(.), %locator%)]]//div[@data-region='availabilityinfo']",
|
||||||
|
]
|
||||||
|
),
|
||||||
|
new behat_component_named_selector(
|
||||||
|
'Section availability', [".//li[@id = %locator%]//div[@data-region='availabilityinfo']"],
|
||||||
|
),
|
||||||
|
new behat_component_named_selector(
|
||||||
|
'Set Of Restrictions', ["//div[h3[@data-restriction-order=%locator% and contains(text(), 'Set of')]]"],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the list of exact named selectors
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function get_exact_named_selectors(): array {
|
||||||
|
return [
|
||||||
|
new behat_component_named_selector(
|
||||||
|
'Availability Button Area',
|
||||||
|
[
|
||||||
|
"//h3[@data-restriction-order=%locator%]/following-sibling::div[contains(@class,'availability-inner')]/"
|
||||||
|
. "div[contains(@class,'availability-button')]",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -560,7 +560,7 @@ M.core_availability.List.prototype.renumber = function(parentNumber) {
|
|||||||
}
|
}
|
||||||
var heading = M.util.get_string('setheading', 'availability', headingParams);
|
var heading = M.util.get_string('setheading', 'availability', headingParams);
|
||||||
this.node.one('> h3').set('innerHTML', heading);
|
this.node.one('> h3').set('innerHTML', heading);
|
||||||
|
this.node.one('> h3').getDOMNode().dataset.restrictionOrder = parentNumber ? parentNumber : 'root';
|
||||||
// Do children.
|
// Do children.
|
||||||
for (var i = 0; i < this.children.length; i++) {
|
for (var i = 0; i < this.children.length; i++) {
|
||||||
var child = this.children[i];
|
var child = this.children[i];
|
||||||
@ -1008,6 +1008,7 @@ M.core_availability.Item.prototype.renumber = function(number) {
|
|||||||
headingParams.number = number + ':';
|
headingParams.number = number + ':';
|
||||||
var heading = M.util.get_string('itemheading', 'availability', headingParams);
|
var heading = M.util.get_string('itemheading', 'availability', headingParams);
|
||||||
this.node.one('> h3').set('innerHTML', heading);
|
this.node.one('> h3').set('innerHTML', heading);
|
||||||
|
this.node.one('> h3').getDOMNode().dataset.restrictionOrder = number ? number : 'root';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
File diff suppressed because one or more lines are too long
@ -560,7 +560,7 @@ M.core_availability.List.prototype.renumber = function(parentNumber) {
|
|||||||
}
|
}
|
||||||
var heading = M.util.get_string('setheading', 'availability', headingParams);
|
var heading = M.util.get_string('setheading', 'availability', headingParams);
|
||||||
this.node.one('> h3').set('innerHTML', heading);
|
this.node.one('> h3').set('innerHTML', heading);
|
||||||
|
this.node.one('> h3').getDOMNode().dataset.restrictionOrder = parentNumber ? parentNumber : 'root';
|
||||||
// Do children.
|
// Do children.
|
||||||
for (var i = 0; i < this.children.length; i++) {
|
for (var i = 0; i < this.children.length; i++) {
|
||||||
var child = this.children[i];
|
var child = this.children[i];
|
||||||
@ -1008,6 +1008,7 @@ M.core_availability.Item.prototype.renumber = function(number) {
|
|||||||
headingParams.number = number + ':';
|
headingParams.number = number + ':';
|
||||||
var heading = M.util.get_string('itemheading', 'availability', headingParams);
|
var heading = M.util.get_string('itemheading', 'availability', headingParams);
|
||||||
this.node.one('> h3').set('innerHTML', heading);
|
this.node.one('> h3').set('innerHTML', heading);
|
||||||
|
this.node.one('> h3').getDOMNode().dataset.restrictionOrder = number ? number : 'root';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
3
availability/yui/src/form/js/form.js
vendored
3
availability/yui/src/form/js/form.js
vendored
@ -558,7 +558,7 @@ M.core_availability.List.prototype.renumber = function(parentNumber) {
|
|||||||
}
|
}
|
||||||
var heading = M.util.get_string('setheading', 'availability', headingParams);
|
var heading = M.util.get_string('setheading', 'availability', headingParams);
|
||||||
this.node.one('> h3').set('innerHTML', heading);
|
this.node.one('> h3').set('innerHTML', heading);
|
||||||
|
this.node.one('> h3').getDOMNode().dataset.restrictionOrder = parentNumber ? parentNumber : 'root';
|
||||||
// Do children.
|
// Do children.
|
||||||
for (var i = 0; i < this.children.length; i++) {
|
for (var i = 0; i < this.children.length; i++) {
|
||||||
var child = this.children[i];
|
var child = this.children[i];
|
||||||
@ -1006,6 +1006,7 @@ M.core_availability.Item.prototype.renumber = function(number) {
|
|||||||
headingParams.number = number + ':';
|
headingParams.number = number + ':';
|
||||||
var heading = M.util.get_string('itemheading', 'availability', headingParams);
|
var heading = M.util.get_string('itemheading', 'availability', headingParams);
|
||||||
this.node.one('> h3').set('innerHTML', heading);
|
this.node.one('> h3').set('innerHTML', heading);
|
||||||
|
this.node.one('> h3').getDOMNode().dataset.restrictionOrder = number ? number : 'root';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user