Merge branch 'MDL-78813-master' of https://github.com/mihailges/moodle

This commit is contained in:
Huong Nguyen
2023-09-28 12:01:25 +07:00
10 changed files with 75 additions and 15 deletions
+2 -2
View File
@@ -1,10 +1,10 @@
define("gradereport_grader/stickycolspan",["exports","jquery"],(function(_exports,_jquery){var obj;
define("gradereport_grader/stickycolspan",["exports","jquery","core/sticky-footer"],(function(_exports,_jquery,_stickyFooter){var obj;
/**
* Javascript module for fixing the position of sticky headers with multiple colspans
*
* @module gradereport_grader/stickycolspan
* @copyright 2022 Bas Brands <bas@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,_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj};const SELECTORS_GRADEPARENT=".gradeparent",SELECTORS_STUDENTHEADER="#studentheader",SELECTORS_TABLEHEADER="th.header",SELECTORS_BEHAT="body.behat-site",SELECTORS_USERDROPDOWN=".userrow th .dropdown",SELECTORS_AVERAGEROWHEADER=".lastrow th";_exports.init=()=>{(0,_jquery.default)(SELECTORS_USERDROPDOWN).on("show.bs.dropdown hide.bs.dropdown",(e=>{e.target.closest(SELECTORS_TABLEHEADER).classList.toggle("actions-menu-active")}));if(new IntersectionObserver((_ref=>{let[e]=_ref;return e.target.closest("tr").classList.toggle("pinned",e.intersectionRatio<1)}),{threshold:[1]}).observe(document.querySelector(SELECTORS_AVERAGEROWHEADER)),!document.querySelector(SELECTORS_BEHAT)){const grader=document.querySelector(SELECTORS_GRADEPARENT),tableHeaders=grader.querySelectorAll(SELECTORS_TABLEHEADER),studentHeader=grader.querySelector(SELECTORS_STUDENTHEADER),leftOffset=getComputedStyle(studentHeader).getPropertyValue("left"),rightOffset=getComputedStyle(studentHeader).getPropertyValue("right");tableHeaders.forEach((tableHeader=>{if(tableHeader.colSpan>1){const addOffset=tableHeader.offsetWidth-studentHeader.offsetWidth;window.right_to_left()?tableHeader.style.right="calc("+rightOffset+" - "+addOffset+"px )":tableHeader.style.left="calc("+leftOffset+" - "+addOffset+"px )"}}))}}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj};const SELECTORS_GRADEPARENT=".gradeparent",SELECTORS_STUDENTHEADER="#studentheader",SELECTORS_TABLEHEADER="th.header",SELECTORS_BEHAT="body.behat-site",SELECTORS_USERDROPDOWN=".userrow th .dropdown",SELECTORS_AVERAGEROWHEADER=".lastrow th";_exports.init=()=>{if((0,_jquery.default)(SELECTORS_USERDROPDOWN).on("show.bs.dropdown hide.bs.dropdown",(e=>{e.target.closest(SELECTORS_TABLEHEADER).classList.toggle("actions-menu-active")})),defineAverageRowIntersectionObserver(!0),document.addEventListener(_stickyFooter.eventTypes.stickyFooterStateChanged,(e=>{defineAverageRowIntersectionObserver(e.detail.enabled)})),!document.querySelector(SELECTORS_BEHAT)){const grader=document.querySelector(SELECTORS_GRADEPARENT),tableHeaders=grader.querySelectorAll(SELECTORS_TABLEHEADER),studentHeader=grader.querySelector(SELECTORS_STUDENTHEADER),leftOffset=getComputedStyle(studentHeader).getPropertyValue("left"),rightOffset=getComputedStyle(studentHeader).getPropertyValue("right");tableHeaders.forEach((tableHeader=>{if(tableHeader.colSpan>1){const addOffset=tableHeader.offsetWidth-studentHeader.offsetWidth;window.right_to_left()?tableHeader.style.right="calc("+rightOffset+" - "+addOffset+"px )":tableHeader.style.left="calc("+leftOffset+" - "+addOffset+"px )"}}))}};const defineAverageRowIntersectionObserver=stickyFooterEnabled=>{const stickyFooterHeight=stickyFooterEnabled?document.querySelector(_stickyFooter.SELECTORS.STICKYFOOTER).offsetHeight:null;new IntersectionObserver((_ref=>{let[e]=_ref;return e.target.closest("tr").classList.toggle("pinned",e.intersectionRatio<1)}),{rootMargin:stickyFooterHeight?"0px 0px -".concat(stickyFooterHeight,"px 0px"):"0px",threshold:[1]}).observe(document.querySelector(SELECTORS_AVERAGEROWHEADER))}}));
//# sourceMappingURL=stickycolspan.min.js.map
File diff suppressed because one or more lines are too long
+30 -8
View File
@@ -22,6 +22,7 @@
*/
import $ from 'jquery';
import {SELECTORS as stickyFooterSelectors, eventTypes as stickyFooterEvents} from 'core/sticky-footer';
const SELECTORS = {
GRADEPARENT: '.gradeparent',
@@ -43,14 +44,14 @@ export const init = () => {
// The closest heading element has sticky positioning which affects the stacking context in this case.
e.target.closest(SELECTORS.TABLEHEADER).classList.toggle('actions-menu-active');
});
// Register an observer that will bump up the z-index value of the average overall row when it's pinned to prevent
// the row being cut-off by the user column cells or other components within the report table that have higher
// z-index values.
const observer = new IntersectionObserver(
([e]) => e.target.closest('tr').classList.toggle('pinned', e.intersectionRatio < 1),
{threshold: [1]}
);
observer.observe(document.querySelector(SELECTORS.AVERAGEROWHEADER));
defineAverageRowIntersectionObserver(true);
// Add an event listener to the sticky footer toggled event to re-define the average row intersection observer
// accordingly. This is needed as on narrow screens when scrolling vertically the sticky footer is enabled and
// disabled dynamically.
document.addEventListener(stickyFooterEvents.stickyFooterStateChanged, (e) => {
defineAverageRowIntersectionObserver(e.detail.enabled);
});
if (!document.querySelector(SELECTORS.BEHAT)) {
const grader = document.querySelector(SELECTORS.GRADEPARENT);
@@ -71,3 +72,24 @@ export const init = () => {
});
}
};
/**
* Define the intersection observer that will make sure that the average overall row is properly pinned.
*
* @param {boolean} stickyFooterEnabled Whether the page shows a sticky footer or not.
*/
const defineAverageRowIntersectionObserver = (stickyFooterEnabled) => {
const stickyFooterHeight = stickyFooterEnabled ? document.querySelector(stickyFooterSelectors.STICKYFOOTER).offsetHeight : null;
// Register an observer that will bump up the z-index value of the average overall row when it's pinned to prevent
// the row being cut-off by the user column cells or other components within the report table that have higher
// z-index values. If the page has a sticky footer, we need to make sure that the bottom root margin of the observer
// subtracts the height of the sticky footer to prevent the row being cut-off by the footer.
const intersectionObserver = new IntersectionObserver(
([e]) => e.target.closest('tr').classList.toggle('pinned', e.intersectionRatio < 1),
{
rootMargin: stickyFooterHeight ? `0px 0px -${stickyFooterHeight}px 0px` : "0px",
threshold: [1]
}
);
intersectionObserver.observe(document.querySelector(SELECTORS.AVERAGEROWHEADER));
};
+6
View File
@@ -269,3 +269,9 @@
width: 300px;
max-height: 300px;
}
@media only screen and (min-width: 768px) {
.path-grade-report-grader .gradeparent table {
padding-right: 6em;
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
define("core/sticky-footer",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.registerManager=_exports.init=_exports.enableStickyFooter=_exports.disableStickyFooter=void 0;
define("core/sticky-footer",["exports","core/event_dispatcher"],(function(_exports,_event_dispatcher){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.registerManager=_exports.init=_exports.eventTypes=_exports.enableStickyFooter=_exports.disableStickyFooter=_exports.SELECTORS=void 0;
/**
* Sticky footer wrapper module.
*
@@ -9,6 +9,6 @@ define("core/sticky-footer",["exports"],(function(_exports){Object.definePropert
* @copyright 2023 Ferran Recio <ferran@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
let manager={},enabled=!1,initialized=!1;const SELECTORS_STICKYFOOTER=".stickyfooter",CLASSES_INVISIBLE="v-hidden",enableStickyFooter=()=>{var _document$querySelect;(enabled=!0,void 0!==manager.enableStickyFooter)?manager.enableStickyFooter():null===(_document$querySelect=document.querySelector(SELECTORS_STICKYFOOTER))||void 0===_document$querySelect||_document$querySelect.classList.remove(CLASSES_INVISIBLE)};_exports.enableStickyFooter=enableStickyFooter;const disableStickyFooter=()=>{var _document$querySelect2;(enabled=!1,void 0!==manager.disableStickyFooter)?manager.disableStickyFooter():null===(_document$querySelect2=document.querySelector(SELECTORS_STICKYFOOTER))||void 0===_document$querySelect2||_document$querySelect2.classList.add(CLASSES_INVISIBLE)};_exports.disableStickyFooter=disableStickyFooter;_exports.registerManager=themeManager=>{manager=themeManager,enabled&&enableStickyFooter()};_exports.init=()=>{var _document$querySelect3;if(initialized)return;initialized=!0;(null===(_document$querySelect3=document.querySelector(SELECTORS_STICKYFOOTER))||void 0===_document$querySelect3?void 0:_document$querySelect3.dataset.disable)?disableStickyFooter():enableStickyFooter()}}));
let manager={},enabled=!1,initialized=!1;const SELECTORS={STICKYFOOTER:".stickyfooter"};_exports.SELECTORS=SELECTORS;const CLASSES_INVISIBLE="v-hidden",eventTypes={stickyFooterStateChanged:"core/stickyfooter_state_changed"};_exports.eventTypes=eventTypes;const enableStickyFooter=()=>{var _document$querySelect;(enabled=!0,void 0!==manager.enableStickyFooter)?(manager.enableStickyFooter(),notifyStickyFooterStateChange(!0)):null===(_document$querySelect=document.querySelector(SELECTORS.STICKYFOOTER))||void 0===_document$querySelect||_document$querySelect.classList.remove(CLASSES_INVISIBLE)};_exports.enableStickyFooter=enableStickyFooter;const disableStickyFooter=()=>{var _document$querySelect2;(enabled=!1,void 0!==manager.disableStickyFooter)?(manager.disableStickyFooter(),notifyStickyFooterStateChange(!1)):null===(_document$querySelect2=document.querySelector(SELECTORS.STICKYFOOTER))||void 0===_document$querySelect2||_document$querySelect2.classList.add(CLASSES_INVISIBLE)};_exports.disableStickyFooter=disableStickyFooter;_exports.registerManager=themeManager=>{manager=themeManager,enabled&&enableStickyFooter()};_exports.init=()=>{var _document$querySelect3;if(initialized)return;initialized=!0;(null===(_document$querySelect3=document.querySelector(SELECTORS.STICKYFOOTER))||void 0===_document$querySelect3?void 0:_document$querySelect3.dataset.disable)?disableStickyFooter():enableStickyFooter()};const notifyStickyFooterStateChange=enabled=>{(0,_event_dispatcher.dispatchEvent)(eventTypes.stickyFooterStateChanged,{enabled:enabled},document,{cancelable:!1})}}));
//# sourceMappingURL=sticky-footer.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"sticky-footer.min.js","sources":["../src/sticky-footer.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Sticky footer wrapper module.\n *\n * Themes are responsible for implementing the sticky footer. However,\n * modules can interact with the sticky footer using this module.\n *\n * @module core/sticky-footer\n * @copyright 2023 Ferran Recio <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\nlet manager = {};\n\nlet enabled = false;\n\nlet initialized = false;\n\nconst SELECTORS = {\n STICKYFOOTER: '.stickyfooter',\n};\n\nconst CLASSES = {\n INVISIBLE: 'v-hidden',\n};\n\n/**\n * Enable sticky footer in the page.\n */\nexport const enableStickyFooter = () => {\n enabled = true;\n if (manager.enableStickyFooter === undefined) {\n document.querySelector(SELECTORS.STICKYFOOTER)?.classList.remove(CLASSES.INVISIBLE);\n return;\n }\n manager.enableStickyFooter();\n};\n\n/**\n * Disable sticky footer in the page.\n */\nexport const disableStickyFooter = () => {\n enabled = false;\n if (manager.disableStickyFooter === undefined) {\n document.querySelector(SELECTORS.STICKYFOOTER)?.classList.add(CLASSES.INVISIBLE);\n return;\n }\n manager.disableStickyFooter();\n};\n\n/**\n * Register the theme sticky footer methods.\n *\n * @param {Object} themeManager the manager object with all the needed methods.\n * @param {Function} themeManager.enableStickyFooter enable sticky footer method\n * @param {Function} themeManager.disableStickyFooter disable sticky footer method\n */\nexport const registerManager = (themeManager) => {\n manager = themeManager;\n if (enabled) {\n enableStickyFooter();\n }\n};\n\n/**\n * Initialize the module if the theme does not implement its own init.\n */\nexport const init = () => {\n if (initialized) {\n return;\n }\n initialized = true;\n\n const isDisabled = document.querySelector(SELECTORS.STICKYFOOTER)?.dataset.disable;\n if (isDisabled) {\n disableStickyFooter();\n } else {\n enableStickyFooter();\n }\n};\n"],"names":["manager","enabled","initialized","SELECTORS","CLASSES","enableStickyFooter","undefined","document","querySelector","classList","remove","disableStickyFooter","add","themeManager","_document$querySelect3","dataset","disable"],"mappings":";;;;;;;;;;;IA2BIA,QAAU,GAEVC,SAAU,EAEVC,aAAc,QAEZC,uBACY,gBAGZC,kBACS,WAMFC,mBAAqB,gCAC9BJ,SAAU,OACyBK,IAA/BN,QAAQK,oBAIZL,QAAQK,mDAHJE,SAASC,cAAcL,gFAAyBM,UAAUC,OAAON,yEAS5DO,oBAAsB,iCAC/BV,SAAU,OAC0BK,IAAhCN,QAAQW,qBAIZX,QAAQW,qDAHJJ,SAASC,cAAcL,kFAAyBM,UAAUG,IAAIR,8FAatCS,eAC5Bb,QAAUa,aACNZ,SACAI,oCAOY,mCACZH,mBAGJA,aAAc,kCAEKK,SAASC,cAAcL,iEAAvBW,uBAAgDC,QAAQC,SAEvEL,sBAEAN"}
{"version":3,"file":"sticky-footer.min.js","sources":["../src/sticky-footer.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Sticky footer wrapper module.\n *\n * Themes are responsible for implementing the sticky footer. However,\n * modules can interact with the sticky footer using this module.\n *\n * @module core/sticky-footer\n * @copyright 2023 Ferran Recio <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {dispatchEvent} from 'core/event_dispatcher';\n\nlet manager = {};\n\nlet enabled = false;\n\nlet initialized = false;\n\nexport const SELECTORS = {\n STICKYFOOTER: '.stickyfooter',\n};\n\nconst CLASSES = {\n INVISIBLE: 'v-hidden',\n};\n\nexport const eventTypes = {\n stickyFooterStateChanged: 'core/stickyfooter_state_changed',\n};\n\n/**\n * Enable sticky footer in the page.\n */\nexport const enableStickyFooter = () => {\n enabled = true;\n if (manager.enableStickyFooter === undefined) {\n document.querySelector(SELECTORS.STICKYFOOTER)?.classList.remove(CLASSES.INVISIBLE);\n return;\n }\n manager.enableStickyFooter();\n notifyStickyFooterStateChange(true);\n};\n\n/**\n * Disable sticky footer in the page.\n */\nexport const disableStickyFooter = () => {\n enabled = false;\n if (manager.disableStickyFooter === undefined) {\n document.querySelector(SELECTORS.STICKYFOOTER)?.classList.add(CLASSES.INVISIBLE);\n return;\n }\n manager.disableStickyFooter();\n notifyStickyFooterStateChange(false);\n};\n\n/**\n * Register the theme sticky footer methods.\n *\n * @param {Object} themeManager the manager object with all the needed methods.\n * @param {Function} themeManager.enableStickyFooter enable sticky footer method\n * @param {Function} themeManager.disableStickyFooter disable sticky footer method\n */\nexport const registerManager = (themeManager) => {\n manager = themeManager;\n if (enabled) {\n enableStickyFooter();\n }\n};\n\n/**\n * Initialize the module if the theme does not implement its own init.\n */\nexport const init = () => {\n if (initialized) {\n return;\n }\n initialized = true;\n\n const isDisabled = document.querySelector(SELECTORS.STICKYFOOTER)?.dataset.disable;\n if (isDisabled) {\n disableStickyFooter();\n } else {\n enableStickyFooter();\n }\n};\n\n/**\n * Dispatch an event to notify that the state (enabled/disabled) of the sticky footer has changed.\n *\n * @param {boolean} enabled Whether the sticky footer has been enabled or disabled.\n */\nconst notifyStickyFooterStateChange = (enabled) => {\n dispatchEvent(eventTypes.stickyFooterStateChanged, {enabled: enabled}, document, {cancelable: false});\n};\n"],"names":["manager","enabled","initialized","SELECTORS","STICKYFOOTER","CLASSES","eventTypes","stickyFooterStateChanged","enableStickyFooter","undefined","notifyStickyFooterStateChange","document","querySelector","classList","remove","disableStickyFooter","add","themeManager","_document$querySelect3","dataset","disable","cancelable"],"mappings":";;;;;;;;;;;IA4BIA,QAAU,GAEVC,SAAU,EAEVC,aAAc,QAELC,UAAY,CACrBC,aAAc,oDAGZC,kBACS,WAGFC,WAAa,CACtBC,yBAA0B,wEAMjBC,mBAAqB,gCAC9BP,SAAU,OACyBQ,IAA/BT,QAAQQ,qBAIZR,QAAQQ,qBACRE,+BAA8B,kCAJ1BC,SAASC,cAAcT,UAAUC,sEAAeS,UAAUC,OAAOT,yEAU5DU,oBAAsB,iCAC/Bd,SAAU,OAC0BQ,IAAhCT,QAAQe,sBAIZf,QAAQe,sBACRL,+BAA8B,mCAJ1BC,SAASC,cAAcT,UAAUC,wEAAeS,UAAUG,IAAIX,8FActCY,eAC5BjB,QAAUiB,aACNhB,SACAO,oCAOY,mCACZN,mBAGJA,aAAc,kCAEKS,SAASC,cAAcT,UAAUC,uDAAjCc,uBAAgDC,QAAQC,SAEvEL,sBAEAP,4BASFE,8BAAiCT,8CACrBK,WAAWC,yBAA0B,CAACN,QAASA,SAAUU,SAAU,CAACU,YAAY"}
+17 -1
View File
@@ -24,6 +24,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import {dispatchEvent} from 'core/event_dispatcher';
let manager = {};
@@ -31,7 +32,7 @@ let enabled = false;
let initialized = false;
const SELECTORS = {
export const SELECTORS = {
STICKYFOOTER: '.stickyfooter',
};
@@ -39,6 +40,10 @@ const CLASSES = {
INVISIBLE: 'v-hidden',
};
export const eventTypes = {
stickyFooterStateChanged: 'core/stickyfooter_state_changed',
};
/**
* Enable sticky footer in the page.
*/
@@ -49,6 +54,7 @@ export const enableStickyFooter = () => {
return;
}
manager.enableStickyFooter();
notifyStickyFooterStateChange(true);
};
/**
@@ -61,6 +67,7 @@ export const disableStickyFooter = () => {
return;
}
manager.disableStickyFooter();
notifyStickyFooterStateChange(false);
};
/**
@@ -93,3 +100,12 @@ export const init = () => {
enableStickyFooter();
}
};
/**
* Dispatch an event to notify that the state (enabled/disabled) of the sticky footer has changed.
*
* @param {boolean} enabled Whether the sticky footer has been enabled or disabled.
*/
const notifyStickyFooterStateChange = (enabled) => {
dispatchEvent(eventTypes.stickyFooterStateChanged, {enabled: enabled}, document, {cancelable: false});
};
+10
View File
@@ -656,6 +656,16 @@
.show-drawer-left .gradeparent th.header {
left: -1rem;
}
&.hasstickyfooter {
.gradeparent {
tr.lastrow {
// Hack used by the observer to help detecting when the sticky 'Overall average' row is pinned when
// sticky footer is present.
bottom: calc(#{$stickyfooter-height} - 1px);
}
}
}
}
/**
+3
View File
@@ -35868,6 +35868,9 @@ p.arrow_button {
.path-grade-report-grader .show-drawer-left .gradeparent th.header {
left: -1rem;
}
.path-grade-report-grader.hasstickyfooter .gradeparent tr.lastrow {
bottom: calc(max(96px, 0.9375rem * 3) - 1px);
}
/**
* User report.
+3
View File
@@ -35868,6 +35868,9 @@ p.arrow_button {
.path-grade-report-grader .show-drawer-left .gradeparent th.header {
left: -1rem;
}
.path-grade-report-grader.hasstickyfooter .gradeparent tr.lastrow {
bottom: calc(max(96px, 0.9375rem * 3) - 1px);
}
/**
* User report.