MDL-67883 core: Make core ready for MoodleNet.
This commit is contained in:
@@ -74,7 +74,4 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
|
||||
new lang_string('configallowemojipickerincompatible', 'admin')
|
||||
));
|
||||
}
|
||||
|
||||
$optionalsubsystems->add(new admin_setting_configcheckbox('enablemoodlenet', new lang_string('enablemoodlenet', 'admin'),
|
||||
new lang_string('enablemoodlenet_desc', 'admin'), 1, 1, 0));
|
||||
}
|
||||
|
||||
@@ -186,6 +186,7 @@ if ($hassiteconfig
|
||||
'email' => new lang_string('email'),
|
||||
'city' => new lang_string('city'),
|
||||
'country' => new lang_string('country'),
|
||||
'moodlenetprofile' => new lang_string('moodlenetprofile', 'user'),
|
||||
'timezone' => new lang_string('timezone'),
|
||||
'webpage' => new lang_string('webpage'),
|
||||
'icqnumber' => new lang_string('icqnumber'),
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
|
||||
define ("core_course/local/activitychooser/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.unfavouriteModule=a.favouriteModule=a.activityModules=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){return b.default.call([{methodname:"core_course_get_course_content_items",args:{courseid:a}}])[0]};a.activityModules=c;var d=function(a,c){return b.default.call([{methodname:"core_course_add_content_item_to_user_favourites",args:{componentname:a,contentitemid:c}}])[0]};a.favouriteModule=d;var e=function(a,c){return b.default.call([{methodname:"core_course_remove_content_item_from_user_favourites",args:{componentname:a,contentitemid:c}}])[0]};a.unfavouriteModule=e});
|
||||
define ("core_course/local/activitychooser/repository",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.fetchFooterData=a.unfavouriteModule=a.favouriteModule=a.activityModules=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);var c=function(a){return b.default.call([{methodname:"core_course_get_course_content_items",args:{courseid:a}}])[0]};a.activityModules=c;var d=function(a,c){return b.default.call([{methodname:"core_course_add_content_item_to_user_favourites",args:{componentname:a,contentitemid:c}}])[0]};a.favouriteModule=d;var e=function(a,c){return b.default.call([{methodname:"core_course_remove_content_item_from_user_favourites",args:{componentname:a,contentitemid:c}}])[0]};a.unfavouriteModule=e;var f=function(a,c){return b.default.call([{methodname:"core_course_get_activity_chooser_footer",args:{courseid:a,sectionid:c}}])[0]};a.fetchFooterData=f});
|
||||
//# sourceMappingURL=repository.min.js.map
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["../../../src/local/activitychooser/repository.js"],"names":["activityModules","courseid","ajax","call","methodname","args","favouriteModule","modName","modID","componentname","contentitemid","unfavouriteModule"],"mappings":"0NAsBA,uDASO,GAAMA,CAAAA,CAAe,CAAG,SAACC,CAAD,CAAc,CAOzC,MAAOC,WAAKC,IAAL,CAAU,CAND,CACZC,UAAU,CAAE,sCADA,CAEZC,IAAI,CAAE,CACFJ,QAAQ,CAAEA,CADR,CAFM,CAMC,CAAV,EAAqB,CAArB,CACV,CARM,C,oBAmBA,GAAMK,CAAAA,CAAe,CAAG,SAACC,CAAD,CAAUC,CAAV,CAAoB,CAQ/C,MAAON,WAAKC,IAAL,CAAU,CAPD,CACZC,UAAU,CAAE,iDADA,CAEZC,IAAI,CAAE,CACFI,aAAa,CAAEF,CADb,CAEFG,aAAa,CAAEF,CAFb,CAFM,CAOC,CAAV,EAAqB,CAArB,CACV,CATM,C,oBAoBA,GAAMG,CAAAA,CAAiB,CAAG,SAACJ,CAAD,CAAUC,CAAV,CAAoB,CAQjD,MAAON,WAAKC,IAAL,CAAU,CAPD,CACZC,UAAU,CAAE,sDADA,CAEZC,IAAI,CAAE,CACFI,aAAa,CAAEF,CADb,CAEFG,aAAa,CAAEF,CAFb,CAFM,CAOC,CAAV,EAAqB,CAArB,CACV,CATM,C","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 *\n * @module core_course/repository\n * @package core_course\n * @copyright 2019 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ajax from 'core/ajax';\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method activityModules\n * @param {Number} courseid What course to fetch the modules for\n * @return {object} jQuery promise\n */\nexport const activityModules = (courseid) => {\n const request = {\n methodname: 'core_course_get_course_content_items',\n args: {\n courseid: courseid,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is a users' favourite.\n *\n * @method favouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const favouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_add_content_item_to_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is no longer a users' favourite.\n *\n * @method unfavouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const unfavouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_remove_content_item_from_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n return ajax.call([request])[0];\n};\n"],"file":"repository.min.js"}
|
||||
{"version":3,"sources":["../../../src/local/activitychooser/repository.js"],"names":["activityModules","courseid","ajax","call","methodname","args","favouriteModule","modName","modID","componentname","contentitemid","unfavouriteModule","fetchFooterData","sectionid"],"mappings":"4OAsBA,uDASO,GAAMA,CAAAA,CAAe,CAAG,SAACC,CAAD,CAAc,CAOzC,MAAOC,WAAKC,IAAL,CAAU,CAND,CACZC,UAAU,CAAE,sCADA,CAEZC,IAAI,CAAE,CACFJ,QAAQ,CAAEA,CADR,CAFM,CAMC,CAAV,EAAqB,CAArB,CACV,CARM,C,oBAmBA,GAAMK,CAAAA,CAAe,CAAG,SAACC,CAAD,CAAUC,CAAV,CAAoB,CAQ/C,MAAON,WAAKC,IAAL,CAAU,CAPD,CACZC,UAAU,CAAE,iDADA,CAEZC,IAAI,CAAE,CACFI,aAAa,CAAEF,CADb,CAEFG,aAAa,CAAEF,CAFb,CAFM,CAOC,CAAV,EAAqB,CAArB,CACV,CATM,C,oBAoBA,GAAMG,CAAAA,CAAiB,CAAG,SAACJ,CAAD,CAAUC,CAAV,CAAoB,CAQjD,MAAON,WAAKC,IAAL,CAAU,CAPD,CACZC,UAAU,CAAE,sDADA,CAEZC,IAAI,CAAE,CACFI,aAAa,CAAEF,CADb,CAEFG,aAAa,CAAEF,CAFb,CAFM,CAOC,CAAV,EAAqB,CAArB,CACV,CATM,C,sBAmBA,GAAMI,CAAAA,CAAe,CAAG,SAACX,CAAD,CAAWY,CAAX,CAAyB,CAQpD,MAAOX,WAAKC,IAAL,CAAU,CAPD,CACZC,UAAU,CAAE,yCADA,CAEZC,IAAI,CAAE,CACFJ,QAAQ,CAAEA,CADR,CAEFY,SAAS,CAAEA,CAFT,CAFM,CAOC,CAAV,EAAqB,CAArB,CACV,CATM,C","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 *\n * @module core_course/repository\n * @package core_course\n * @copyright 2019 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ajax from 'core/ajax';\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method activityModules\n * @param {Number} courseid What course to fetch the modules for\n * @return {object} jQuery promise\n */\nexport const activityModules = (courseid) => {\n const request = {\n methodname: 'core_course_get_course_content_items',\n args: {\n courseid: courseid,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is a users' favourite.\n *\n * @method favouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const favouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_add_content_item_to_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is no longer a users' favourite.\n *\n * @method unfavouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const unfavouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_remove_content_item_from_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method fetchFooterData\n * @param {Number} courseid What course to fetch the data for\n * @param {Number} sectionid What section to fetch the data for\n * @return {object} jQuery promise\n */\nexport const fetchFooterData = (courseid, sectionid) => {\n const request = {\n methodname: 'core_course_get_activity_chooser_footer',\n args: {\n courseid: courseid,\n sectionid: sectionid,\n },\n };\n return ajax.call([request])[0];\n};\n"],"file":"repository.min.js"}
|
||||
@@ -85,6 +85,20 @@ const registerListenerEvents = (courseId, chooserConfig) => {
|
||||
};
|
||||
})();
|
||||
|
||||
const fetchFooterData = (() => {
|
||||
let footerInnerPromise = null;
|
||||
|
||||
return (sectionId) => {
|
||||
if (!footerInnerPromise) {
|
||||
footerInnerPromise = new Promise((resolve) => {
|
||||
resolve(Repository.fetchFooterData(courseId, sectionId));
|
||||
});
|
||||
}
|
||||
|
||||
return footerInnerPromise;
|
||||
};
|
||||
})();
|
||||
|
||||
CustomEvents.define(document, events);
|
||||
|
||||
// Display module chooser event listeners.
|
||||
@@ -115,7 +129,8 @@ const registerListenerEvents = (courseId, chooserConfig) => {
|
||||
bodyPromiseResolver = resolve;
|
||||
});
|
||||
|
||||
const sectionModal = buildModal(bodyPromise);
|
||||
const footerData = await fetchFooterData(caller.dataset.sectionid);
|
||||
const sectionModal = buildModal(bodyPromise, footerData);
|
||||
|
||||
// Now we have a modal we should start fetching data.
|
||||
const data = await fetchModuleData();
|
||||
@@ -127,6 +142,7 @@ const registerListenerEvents = (courseId, chooserConfig) => {
|
||||
sectionModal,
|
||||
builtModuleData,
|
||||
partiallyAppliedFavouriteManager(data, caller.dataset.sectionid),
|
||||
footerData,
|
||||
);
|
||||
|
||||
bodyPromiseResolver(await Templates.render(
|
||||
@@ -221,13 +237,15 @@ const templateDataBuilder = (data, chooserConfig) => {
|
||||
*
|
||||
* @method buildModal
|
||||
* @param {Promise} bodyPromise
|
||||
* @param {String|Boolean} footer Either a footer to add or nothing
|
||||
* @return {Object} The modal ready to display immediately and render body in later.
|
||||
*/
|
||||
const buildModal = bodyPromise => {
|
||||
const buildModal = (bodyPromise, footer) => {
|
||||
return ModalFactory.create({
|
||||
type: ModalFactory.types.DEFAULT,
|
||||
title: getString('addresourceoractivity'),
|
||||
body: bodyPromise,
|
||||
footer: footer.customfootertemplate,
|
||||
large: true,
|
||||
templateContext: {
|
||||
classes: 'modchooser'
|
||||
|
||||
@@ -31,6 +31,7 @@ import {addIconToContainer} from 'core/loadingicon';
|
||||
import * as Repository from 'core_course/local/activitychooser/repository';
|
||||
import Notification from 'core/notification';
|
||||
import {debounce} from 'core/utils';
|
||||
const getPlugin = pluginName => import(pluginName);
|
||||
|
||||
/**
|
||||
* Given an event from the main module 'page' navigate to it's help section via a carousel.
|
||||
@@ -38,8 +39,13 @@ import {debounce} from 'core/utils';
|
||||
* @method showModuleHelp
|
||||
* @param {jQuery} carousel Our initialized carousel to manipulate
|
||||
* @param {Object} moduleData Data of the module to carousel to
|
||||
* @param {jQuery} modal We need to figure out if the current modal has a footer.
|
||||
*/
|
||||
const showModuleHelp = (carousel, moduleData) => {
|
||||
const showModuleHelp = (carousel, moduleData, modal = null) => {
|
||||
// If we have a real footer then we need to change temporarily.
|
||||
if (modal !== null && moduleData.showFooter === true) {
|
||||
modal.setFooter(Templates.render('core_course/local/activitychooser/footer_partial', moduleData));
|
||||
}
|
||||
const help = carousel.find(selectors.regions.help)[0];
|
||||
help.innerHTML = '';
|
||||
help.classList.add('m-auto');
|
||||
@@ -107,8 +113,9 @@ const manageFavouriteState = async(modalBody, caller, partialFavourite) => {
|
||||
* @param {Promise} modal Our modal that we are working with
|
||||
* @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}
|
||||
* @param {Function} partialFavourite Partially applied function we need to manage favourite status
|
||||
* @param {Object} footerData Our base footer object.
|
||||
*/
|
||||
const registerListenerEvents = (modal, mappedModules, partialFavourite) => {
|
||||
const registerListenerEvents = (modal, mappedModules, partialFavourite, footerData) => {
|
||||
const bodyClickListener = async(e) => {
|
||||
if (e.target.closest(selectors.actions.optionActions.showSummary)) {
|
||||
const carousel = $(modal.getBody()[0].querySelector(selectors.regions.carousel));
|
||||
@@ -116,7 +123,9 @@ const registerListenerEvents = (modal, mappedModules, partialFavourite) => {
|
||||
const module = e.target.closest(selectors.regions.chooserOption.container);
|
||||
const moduleName = module.dataset.modname;
|
||||
const moduleData = mappedModules.get(moduleName);
|
||||
showModuleHelp(carousel, moduleData);
|
||||
// We need to know if the overall modal has a footer so we know when to show a real / vs fake footer.
|
||||
moduleData.showFooter = modal.hasFooterContent();
|
||||
showModuleHelp(carousel, moduleData, modal);
|
||||
}
|
||||
|
||||
if (e.target.closest(selectors.actions.optionActions.manageFavourite)) {
|
||||
@@ -128,7 +137,7 @@ const registerListenerEvents = (modal, mappedModules, partialFavourite) => {
|
||||
const firstChooserOption = sectionChooserOptions
|
||||
.querySelector(selectors.regions.chooserOption.container);
|
||||
toggleFocusableChooserOption(firstChooserOption, true);
|
||||
initChooserOptionsKeyboardNavigation(modal.getBody()[0], mappedModules, sectionChooserOptions);
|
||||
initChooserOptionsKeyboardNavigation(modal.getBody()[0], mappedModules, sectionChooserOptions, modal);
|
||||
}
|
||||
|
||||
// From the help screen go back to the module overview.
|
||||
@@ -150,7 +159,18 @@ const registerListenerEvents = (modal, mappedModules, partialFavourite) => {
|
||||
const searchInput = modal.getBody()[0].querySelector(selectors.actions.search);
|
||||
searchInput.value = "";
|
||||
searchInput.focus();
|
||||
toggleSearchResultsView(modal.getBody()[0], mappedModules, searchInput.value);
|
||||
toggleSearchResultsView(modal, mappedModules, searchInput.value);
|
||||
}
|
||||
};
|
||||
|
||||
// We essentially have two types of footer.
|
||||
// A fake one that is handled within the template for chooser_help and then all of the stuff for
|
||||
// modal.footer. We need to ensure we know exactly what type of footer we are using so we know what we
|
||||
// need to manage. The below code handles a real footer going to a mnet carousel item.
|
||||
const footerClickListener = async(e) => {
|
||||
if (footerData.footer === true) {
|
||||
const footerjs = await getPlugin(footerData.customfooterjs);
|
||||
await footerjs.footerClickListener(e, footerData, modal);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,7 +203,7 @@ const registerListenerEvents = (modal, mappedModules, partialFavourite) => {
|
||||
// The search input is triggered.
|
||||
searchInput.addEventListener('input', debounce(() => {
|
||||
// Display the search results.
|
||||
toggleSearchResultsView(body, mappedModules, searchInput.value);
|
||||
toggleSearchResultsView(modal, mappedModules, searchInput.value);
|
||||
}, 300));
|
||||
return body;
|
||||
})
|
||||
@@ -197,12 +217,22 @@ const registerListenerEvents = (modal, mappedModules, partialFavourite) => {
|
||||
|
||||
toggleFocusableChooserOption(firstChooserOption, true);
|
||||
initTabsKeyboardNavigation(body);
|
||||
initChooserOptionsKeyboardNavigation(body, mappedModules, sectionChooserOptions);
|
||||
initChooserOptionsKeyboardNavigation(body, mappedModules, sectionChooserOptions, modal);
|
||||
|
||||
return body;
|
||||
})
|
||||
.catch();
|
||||
|
||||
modal.getFooterPromise()
|
||||
|
||||
// The return value of getBodyPromise is a jquery object containing the body NodeElement.
|
||||
.then(footer => footer[0])
|
||||
// Add the listener for clicks on the footer.
|
||||
.then(footer => {
|
||||
footer.addEventListener('click', footerClickListener);
|
||||
return footer;
|
||||
})
|
||||
.catch();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -283,8 +313,9 @@ const initTabsKeyboardNavigation = (body) => {
|
||||
* @param {HTMLElement} body Our modal that we are working with
|
||||
* @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}
|
||||
* @param {HTMLElement} chooserOptionsContainer The section that contains the chooser items
|
||||
* @param {Object} modal Our created modal for the section
|
||||
*/
|
||||
const initChooserOptionsKeyboardNavigation = (body, mappedModules, chooserOptionsContainer) => {
|
||||
const initChooserOptionsKeyboardNavigation = (body, mappedModules, chooserOptionsContainer, modal = null) => {
|
||||
const chooserOptions = chooserOptionsContainer.querySelectorAll(selectors.regions.chooserOption.container);
|
||||
|
||||
Array.from(chooserOptions).forEach((element) => {
|
||||
@@ -303,7 +334,10 @@ const initChooserOptionsKeyboardNavigation = (body, mappedModules, chooserOption
|
||||
pause: true,
|
||||
keyboard: false
|
||||
});
|
||||
showModuleHelp(carousel, moduleData);
|
||||
|
||||
// We need to know if the overall modal has a footer so we know when to show a real / vs fake footer.
|
||||
moduleData.showFooter = modal.hasFooterContent();
|
||||
showModuleHelp(carousel, moduleData, modal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,11 +458,12 @@ const renderSearchResults = async(searchResultsContainer, searchResultsData) =>
|
||||
* Toggle (display/hide) the search results depending on the value of the search query
|
||||
*
|
||||
* @method toggleSearchResultsView
|
||||
* @param {HTMLElement} modalBody The body of the created modal for the section
|
||||
* @param {Object} modal Our created modal for the section
|
||||
* @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}
|
||||
* @param {String} searchQuery The search query
|
||||
*/
|
||||
const toggleSearchResultsView = async(modalBody, mappedModules, searchQuery) => {
|
||||
const toggleSearchResultsView = async(modal, mappedModules, searchQuery) => {
|
||||
const modalBody = modal.getBody()[0];
|
||||
const searchResultsContainer = modalBody.querySelector(selectors.regions.searchResults);
|
||||
const chooserContainer = modalBody.querySelector(selectors.regions.chooser);
|
||||
const clearSearchButton = modalBody.querySelector(selectors.elements.clearsearch);
|
||||
@@ -443,7 +478,7 @@ const toggleSearchResultsView = async(modalBody, mappedModules, searchQuery) =>
|
||||
// Set the first result item to be focusable.
|
||||
toggleFocusableChooserOption(firstSearchResultItem, true);
|
||||
// Register keyboard events on the created search result items.
|
||||
initChooserOptionsKeyboardNavigation(modalBody, mappedModules, searchResultItemsContainer);
|
||||
initChooserOptionsKeyboardNavigation(modalBody, mappedModules, searchResultItemsContainer, modal);
|
||||
}
|
||||
// Display the "clear" search button in the activity chooser search bar.
|
||||
searchIcon.classList.add('d-none');
|
||||
@@ -513,7 +548,7 @@ const setupKeyboardAccessibility = (modal, mappedModules) => {
|
||||
disableFocusAllChooserOptions(prevActiveSectionChooserOptions);
|
||||
// Enable the focus of the first chooser option in the current active section.
|
||||
toggleFocusableChooserOption(firstChooserOption, true);
|
||||
initChooserOptionsKeyboardNavigation(body[0], mappedModules, activeSectionChooserOptions);
|
||||
initChooserOptionsKeyboardNavigation(body[0], mappedModules, activeSectionChooserOptions, modal);
|
||||
});
|
||||
return;
|
||||
}).catch(Notification.exception);
|
||||
@@ -539,8 +574,9 @@ const disableFocusAllChooserOptions = (sectionChooserOptions) => {
|
||||
* @param {Promise} modalPromise Our created modal for the section
|
||||
* @param {Array} sectionModules An array of all of the built module information
|
||||
* @param {Function} partialFavourite Partially applied function we need to manage favourite status
|
||||
* @param {Object} footerData Our base footer object.
|
||||
*/
|
||||
export const displayChooser = (modalPromise, sectionModules, partialFavourite) => {
|
||||
export const displayChooser = (modalPromise, sectionModules, partialFavourite, footerData) => {
|
||||
// Make a map so we can quickly fetch a specific module's object for either rendering or searching.
|
||||
const mappedModules = new Map();
|
||||
sectionModules.forEach((module) => {
|
||||
@@ -549,7 +585,7 @@ export const displayChooser = (modalPromise, sectionModules, partialFavourite) =
|
||||
|
||||
// Register event listeners.
|
||||
modalPromise.then(modal => {
|
||||
registerListenerEvents(modal, mappedModules, partialFavourite);
|
||||
registerListenerEvents(modal, mappedModules, partialFavourite, footerData);
|
||||
|
||||
// We want to focus on the first chooser option element as soon as the modal is opened.
|
||||
setupKeyboardAccessibility(modal, mappedModules);
|
||||
|
||||
@@ -78,3 +78,22 @@ export const unfavouriteModule = (modName, modID) => {
|
||||
};
|
||||
return ajax.call([request])[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch all the information on modules we'll need in the activity chooser.
|
||||
*
|
||||
* @method fetchFooterData
|
||||
* @param {Number} courseid What course to fetch the data for
|
||||
* @param {Number} sectionid What section to fetch the data for
|
||||
* @return {object} jQuery promise
|
||||
*/
|
||||
export const fetchFooterData = (courseid, sectionid) => {
|
||||
const request = {
|
||||
methodname: 'core_course_get_activity_chooser_footer',
|
||||
args: {
|
||||
courseid: courseid,
|
||||
sectionid: sectionid,
|
||||
},
|
||||
};
|
||||
return ajax.call([request])[0];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Activity Chooser footer data class.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage course
|
||||
* @copyright 2020 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_course\local\entity;
|
||||
|
||||
/**
|
||||
* A class to represent the Activity Chooser footer data.
|
||||
*
|
||||
* @package core
|
||||
* @subpackage course
|
||||
* @copyright 2020 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class activity_chooser_footer {
|
||||
|
||||
/** @var string $footerjspath The path to the plugin JS file to dynamically import later. */
|
||||
protected $footerjspath;
|
||||
|
||||
/** @var string $footertemplate The rendered template for the footer. */
|
||||
protected $footertemplate;
|
||||
|
||||
/** @var string $carouseltemplate The rendered template for the footer. */
|
||||
protected $carouseltemplate;
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
*
|
||||
* @param string $footerjspath JS file to dynamically import later.
|
||||
* @param string $footertemplate Footer template that has been rendered.
|
||||
* @param string|null $carouseltemplate Carousel template that may have been rendered.
|
||||
*/
|
||||
public function __construct(string $footerjspath, string $footertemplate, ?string $carouseltemplate = '') {
|
||||
$this->footerjspath = $footerjspath;
|
||||
$this->footertemplate = $footertemplate;
|
||||
$this->carouseltemplate = $carouseltemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the footer JS file path for this plugin.
|
||||
*
|
||||
* @return string The JS file to call functions from.
|
||||
*/
|
||||
public function get_footer_js_file(): string {
|
||||
return $this->footerjspath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the footer rendered template for this plugin.
|
||||
*
|
||||
* @return string The template that has been rendered for the chooser footer.
|
||||
*/
|
||||
public function get_footer_template(): string {
|
||||
return $this->footertemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the carousel rendered template for this plugin.
|
||||
*
|
||||
* @return string The template that has been rendered for the chooser carousel.
|
||||
*/
|
||||
public function get_carousel_template(): string {
|
||||
return $this->carouseltemplate;
|
||||
}
|
||||
}
|
||||
@@ -4336,4 +4336,74 @@ class core_course_external extends external_api {
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function get_activity_chooser_footer_parameters() {
|
||||
return new external_function_parameters([
|
||||
'courseid' => new external_value(PARAM_INT, 'ID of the course', VALUE_REQUIRED),
|
||||
'sectionid' => new external_value(PARAM_INT, 'ID of the section', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a course ID we need to build up a footre for the chooser.
|
||||
*
|
||||
* @param int $courseid The course we want to fetch the modules for
|
||||
* @param int $sectionid The section we want to fetch the modules for
|
||||
* @return array
|
||||
*/
|
||||
public static function get_activity_chooser_footer(int $courseid, int $sectionid) {
|
||||
[
|
||||
'courseid' => $courseid,
|
||||
'sectionid' => $sectionid,
|
||||
] = self::validate_parameters(self::get_activity_chooser_footer_parameters(), [
|
||||
'courseid' => $courseid,
|
||||
'sectionid' => $sectionid,
|
||||
]);
|
||||
|
||||
$coursecontext = context_course::instance($courseid);
|
||||
self::validate_context($coursecontext);
|
||||
|
||||
$pluginswithfunction = get_plugins_with_function('custom_chooser_footer', 'lib.php');
|
||||
if ($pluginswithfunction) {
|
||||
foreach ($pluginswithfunction as $plugintype => $plugins) {
|
||||
foreach ($plugins as $pluginfunction) {
|
||||
$footerdata = $pluginfunction($courseid, $sectionid);
|
||||
break; // Only a single plugin can modify the footer.
|
||||
}
|
||||
break; // Only a single plugin can modify the footer.
|
||||
}
|
||||
return [
|
||||
'footer' => true,
|
||||
'customfooterjs' => $footerdata->get_footer_js_file(),
|
||||
'customfootertemplate' => $footerdata->get_footer_template(),
|
||||
'customcarouseltemplate' => $footerdata->get_carousel_template(),
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
'footer' => false,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function get_activity_chooser_footer_returns() {
|
||||
return new external_single_structure(
|
||||
[
|
||||
'footer' => new external_value(PARAM_BOOL, 'Is a footer being return by this request?', VALUE_REQUIRED),
|
||||
'customfooterjs' => new external_value(PARAM_RAW, 'The path to the plugin JS file', VALUE_OPTIONAL),
|
||||
'customfootertemplate' => new external_value(PARAM_RAW, 'The prerendered footer', VALUE_OPTIONAL),
|
||||
'customcarouseltemplate' => new external_value(PARAM_RAW, 'Either "" or the prerendered carousel page',
|
||||
VALUE_OPTIONAL),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,5 +147,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item" data-region="help"></div>
|
||||
<!--The following div is used as a place for additional plugins to have widgets in the chooser.-->
|
||||
<div class="carousel-item" data-region="pluginCarousel"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_course/local/activitychooser/footer_partial
|
||||
|
||||
Chooser favourite template partial.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div class="w-100 d-flex justify-content-between" data-region="chooser-option-summary-actions-container">
|
||||
<button data-action="close-chooser-option-summary" class="closeoptionsummary btn btn-secondary" tabindex="0" data-modname="{{componentname}}_{{link}}">
|
||||
{{#str}} back {{/str}}
|
||||
</button>
|
||||
<a href="{{link}}" title="{{#str}} addnew, moodle, {{title}} {{/str}}" data-action="add-chooser-option" class="addoption btn btn-primary" tabindex="0">
|
||||
{{#str}} add {{/str}}
|
||||
</a>
|
||||
</div>
|
||||
@@ -44,12 +44,9 @@
|
||||
{{{help}}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions fixed-bottom w-100 d-flex justify-content-between position-absolute py-3 px-4" data-region="chooser-option-summary-actions-container">
|
||||
<button data-action="close-chooser-option-summary" class="closeoptionsummary btn btn-secondary" tabindex="0" data-modname="{{componentname}}_{{link}}">
|
||||
{{#str}} back {{/str}}
|
||||
</button>
|
||||
<a href="{{link}}" title="{{#str}} addnew, moodle, {{title}} {{/str}}" data-action="add-chooser-option" class="addoption btn btn-primary" tabindex="0">
|
||||
{{#str}} add {{/str}}
|
||||
</a>
|
||||
</div>
|
||||
{{^showFooter}}
|
||||
<div class="fixed-bottom position-absolute py-3 px-4 border-top">
|
||||
{{>core_course/local/activitychooser/footer_partial}}
|
||||
</div>
|
||||
{{/showFooter}}
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,8 @@ Feature: Display and choose from the available activities in course
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher | C | editingteacher |
|
||||
And the following config values are set as admin:
|
||||
| enablemoodlenet | 0 | tool_moodlenet |
|
||||
And I log in as "teacher"
|
||||
And I am on "Course" course homepage with editing mode on
|
||||
|
||||
|
||||
@@ -539,8 +539,6 @@ $string['enableglobalsearch_desc'] = 'If enabled, data will be indexed and synch
|
||||
$string['enablegravatar'] = 'Enable Gravatar';
|
||||
$string['enablegravatar_help'] = 'When enabled Moodle will attempt to fetch a user profile picture from Gravatar if the user has not uploaded an image.';
|
||||
$string['enablemobilewebservice'] = 'Enable web services for mobile devices';
|
||||
$string['enablemoodlenet'] = 'Enable integration with MoodleNet instances';
|
||||
$string['enablemoodlenet_desc'] = 'If enabled, and provided the MoodleNet plugin is installed, users can import content from MoodleNet into this site.';
|
||||
$string['enablerecordcache'] = 'Enable record cache';
|
||||
$string['enablerssfeeds'] = 'Enable RSS feeds';
|
||||
$string['enablesearchareas'] = 'Enable search areas';
|
||||
|
||||
@@ -33,6 +33,7 @@ $string['countparticipantsfound'] = '{$a} participants found';
|
||||
$string['filtersetmatchdescription'] = 'How multiple filters should be combined';
|
||||
$string['match'] = 'Match';
|
||||
$string['matchofthefollowing'] = 'of the following:';
|
||||
$string['moodlenetprofile'] = 'MoodleNet profile';
|
||||
$string['placeholdertypeorselect'] = 'Type or select...';
|
||||
$string['placeholdertype'] = 'Type...';
|
||||
$string['privacy:courserequestpath'] = 'Requested courses';
|
||||
@@ -87,6 +88,7 @@ $string['privacy:metadata:maildisplay'] = 'A preference for the user about displ
|
||||
$string['privacy:metadata:middlename'] = 'The middle name of the user';
|
||||
$string['privacy:metadata:mnethostid'] = 'An identifier for the MNet host if used';
|
||||
$string['privacy:metadata:model'] = 'The device name, occam or iPhone etc..';
|
||||
$string['privacy:metadata:moodlenetprofile'] = 'The MoodleNet profile for the user';
|
||||
$string['privacy:metadata:msn'] = 'The MSN identifier of the user';
|
||||
$string['privacy:metadata:my_pages'] = 'User pages - dashboard and profile. This table does not contain personal data and only used to link dashboard blocks to users';
|
||||
$string['privacy:metadata:my_pages:name'] = 'Page name';
|
||||
|
||||
@@ -872,6 +872,7 @@
|
||||
<FIELD NAME="firstnamephonetic" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="First name phonetic"/>
|
||||
<FIELD NAME="middlename" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Middle name"/>
|
||||
<FIELD NAME="alternatename" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Alternate name - Useful for three-name countries."/>
|
||||
<FIELD NAME="moodlenetprofile" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="Moodle.net profile information"/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
|
||||
@@ -671,6 +671,14 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_course_get_activity_chooser_footer' => array(
|
||||
'classname' => 'core_course_external',
|
||||
'methodname' => 'get_activity_chooser_footer',
|
||||
'classpath' => 'course/externallib.php',
|
||||
'description' => 'Fetch the data for the activity chooser footer.',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_course_toggle_activity_recommendation' => array(
|
||||
'classname' => 'core_course_external',
|
||||
'methodname' => 'toggle_activity_recommendation',
|
||||
|
||||
@@ -2427,5 +2427,19 @@ function xmldb_main_upgrade($oldversion) {
|
||||
upgrade_main_savepoint(true, 2020052200.01);
|
||||
}
|
||||
|
||||
if ($oldversion < 2020060500.01) {
|
||||
// Define field moodlenetprofile to be added to user.
|
||||
$table = new xmldb_table('user');
|
||||
$field = new xmldb_field('moodlenetprofile', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'alternatename');
|
||||
|
||||
// Conditionally launch add field moodlenetprofile.
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2020060500.01);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -165,6 +165,12 @@ function core_myprofile_navigation(core_user\output\myprofile\tree $tree, $user,
|
||||
$tree->add_node($node);
|
||||
}
|
||||
|
||||
if (!isset($hiddenfields['moodlenetprofile']) && $user->moodlenetprofile) {
|
||||
$node = new core_user\output\myprofile\node('contact', 'moodlenetprofile', get_string('moodlenetprofile', 'user'), null,
|
||||
null, $user->moodlenetprofile);
|
||||
$tree->add_node($node);
|
||||
}
|
||||
|
||||
if (!isset($hiddenfields['country']) && $user->country) {
|
||||
$node = new core_user\output\myprofile\node('contact', 'country', get_string('country'), null, null,
|
||||
get_string($user->country, 'countries'));
|
||||
|
||||
@@ -318,6 +318,7 @@ function url_dndupload_handle($uploadinfo) {
|
||||
$data->introformat = FORMAT_HTML;
|
||||
$data->externalurl = clean_param($uploadinfo->content, PARAM_URL);
|
||||
$data->timemodified = time();
|
||||
$data->coursemodule = $uploadinfo->coursemodule;
|
||||
|
||||
// Set the display options to the site defaults.
|
||||
$config = get_config('url');
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 934.36 169.63"><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path d="M762.37,40.25a8.45,8.45,0,0,0-8.44,8.44v88.4l-72-91.84c-1.9-2.41-4.22-4.65-8.28-4.65H671.7A8.56,8.56,0,0,0,663.26,49V160a8.37,8.37,0,0,0,8.27,8.44A8.45,8.45,0,0,0,680,160V69.11l73.63,94.16c2.13,2.48,4.62,4.78,8.42,4.78h.7a7.83,7.83,0,0,0,7.92-8.09V48.69A8.37,8.37,0,0,0,762.37,40.25Z" style="fill:#414443"/><path d="M872.92,119.11c0-23.7-15.06-47.7-43.83-47.7a43.32,43.32,0,0,0-32.44,14.36c-8.25,9.1-12.8,21.37-12.8,34.58v.35c0,27.89,20.21,48.93,47,48.93,14.28,0,25.21-4.37,35.37-14.12a7.4,7.4,0,0,0,2.65-5.59,7.43,7.43,0,0,0-12.5-5.38c-7.52,6.92-15.51,10.15-25.17,10.15-16,0-27.93-11-30.27-27.66H865A7.92,7.92,0,0,0,872.92,119.11ZM828.74,86c11.75,0,24.9,7.35,27.31,27.83H800.93C803.23,97.36,814.46,86,828.74,86Z" style="fill:#414443"/><path d="M926.62,152.4a7.44,7.44,0,0,0-1.88.35,23.35,23.35,0,0,1-6.39.88c-9.38,0-13.75-4.31-13.75-13.57V88.47h22a7.66,7.66,0,0,0,7.74-7.56,7.75,7.75,0,0,0-7.74-7.56h-22V53.44A8.55,8.55,0,0,0,896.16,45a8.27,8.27,0,0,0-8.26,8.44V73.35h-5.82a7.66,7.66,0,0,0-7.56,7.56,7.75,7.75,0,0,0,7.56,7.56h5.82v53.35c0,17.6,9.69,27.28,27.28,27.28a35.66,35.66,0,0,0,13.94-2.57,7.23,7.23,0,0,0,4.89-6.75A7.4,7.4,0,0,0,926.62,152.4Z" style="fill:#414443"/><path d="M153.57,164.26V106.85q0-18-14.87-18t-14.88,18v57.41H94.6V106.85q0-18-14.62-18-14.88,0-14.87,18v57.41H35.88v-60.8q0-18.78,13-28.43Q60.41,66.41,80,66.41q19.83,0,29.23,10.18,8.08-10.19,29.49-10.18,19.56,0,31,8.62,13,9.64,13,28.43v60.8Z" style="fill:#f98012"/><path d="M511.75,164V0H541V164Z" style="fill:#f98012"/><path d="M474.47,164v-9.66q-3.92,5.22-13.32,8.36a49.12,49.12,0,0,1-15.93,2.87q-20.89,0-33.55-14.37T399,115.68c0-13.92,4.11-25.61,12.41-35,7.34-8.3,19.28-14.1,33-14.1,15.49,0,24.54,5.82,30,12.53V0h28.46V164Zm0-54.57q0-7.85-7.44-15t-15.28-7.19A20.73,20.73,0,0,0,434,96.36q-5.75,8.1-5.74,19.84,0,11.49,5.74,19.59,6.54,9.41,17.76,9.4,6.79,0,14.75-6.4t8-13.19Z" style="fill:#f98012"/><path d="M343.91,166.6q-22.2,0-36.69-14.1t-14.5-36.3q0-22.19,14.5-36.29T343.91,65.8q22.18,0,36.82,14.11t14.62,36.29q0,22.2-14.62,36.3T343.91,166.6Zm0-77.29q-10.57,0-16.26,8a32.07,32.07,0,0,0-5.67,19q0,11,5.28,18.63a20.35,20.35,0,0,0,33.3,0q5.54-7.6,5.54-18.63t-5.28-18.63Q354.73,89.31,343.91,89.31Z" style="fill:#f98012"/><path d="M238.15,166.6q-22.2,0-36.69-14.1T187,116.2Q187,94,201.46,79.91T238.15,65.8q22.18,0,36.82,14.11t14.62,36.29q0,22.2-14.62,36.3T238.15,166.6Zm0-77.29q-10.56,0-16.26,8a32.08,32.08,0,0,0-5.68,19q0,11,5.29,18.63a20.35,20.35,0,0,0,33.3,0q5.55-7.6,5.55-18.63t-5.29-18.63Q249,89.31,238.15,89.31Z" style="fill:#f98012"/><path d="M575.64,125.08c.62,7,9.67,21.94,24.55,21.94,14.48,0,21.33-8.36,21.67-11.75l30.81-.27c-3.36,10.28-17,32.13-53,32.13-15,0-28.68-4.66-38.52-14s-14.75-21.46-14.75-36.43q0-23.25,14.75-36.95T599.4,66.07q25.59,0,40,17,13.32,15.67,13.32,42Zm47.78-18a29.09,29.09,0,0,0-7.82-15.4,22,22,0,0,0-15.68-6.53,20.53,20.53,0,0,0-15.28,6.26,31.66,31.66,0,0,0-8.22,15.67Z" style="fill:#f98012"/><path d="M92.65,62l29-21.2-.37-1.29C68.94,45.9,45.11,50.45,0,76.6l.42,1.19,3.59,0a180.84,180.84,0,0,0-.17,26c-5,14.48-.13,24.33,4.45,35,.72-11.15.65-23.34-2.77-35.47a180.08,180.08,0,0,1,.19-25.51l29.91.29a135.7,135.7,0,0,0,.89,17.54c26.72,9.39,53.6,0,67.86-23.19C100.42,68,92.65,62,92.65,62Z" style="fill:#363636"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -1637,6 +1637,17 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
}
|
||||
}
|
||||
|
||||
.modchooser .modal-footer {
|
||||
height: 70px;
|
||||
.moodlenet-logo {
|
||||
.icon {
|
||||
height: 2.5rem;
|
||||
width: 6rem;
|
||||
margin-bottom: .6rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modchoosercontainer.noscroll {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
@@ -1684,7 +1695,7 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
background-color: $white;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
min-height: 640px;
|
||||
height: 640px;
|
||||
|
||||
.content {
|
||||
overflow-y: auto;
|
||||
@@ -2447,6 +2458,10 @@ body.h5p-embed {
|
||||
overflow-wrap: break-word !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
||||
|
||||
.z-index-0 {
|
||||
z-index: 0 !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
||||
|
||||
.z-index-1 {
|
||||
z-index: 1 !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
||||
@@ -2653,4 +2668,4 @@ $picker-emojis-per-row: 7 !default;
|
||||
position: relative;
|
||||
z-index: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11001,6 +11001,13 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
.modchooser .modal-body .carousel-item .loading-icon .icon {
|
||||
margin: 1em auto; }
|
||||
|
||||
.modchooser .modal-footer {
|
||||
height: 70px; }
|
||||
.modchooser .modal-footer .moodlenet-logo .icon {
|
||||
height: 2.5rem;
|
||||
width: 6rem;
|
||||
margin-bottom: .6rem; }
|
||||
|
||||
.modchoosercontainer.noscroll {
|
||||
overflow-y: hidden; }
|
||||
|
||||
@@ -11038,7 +11045,7 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
background-color: #fff;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
min-height: 640px; }
|
||||
height: 640px; }
|
||||
.modchooser .modal-body .optionsummary .content {
|
||||
overflow-y: auto; }
|
||||
.modchooser .modal-body .optionsummary .content .heading .icon {
|
||||
@@ -11631,6 +11638,10 @@ body.h5p-embed .h5pmessages {
|
||||
overflow-wrap: break-word !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
||||
.z-index-0 {
|
||||
z-index: 0 !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
||||
.z-index-1 {
|
||||
z-index: 1 !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
||||
@@ -11208,6 +11208,13 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
.modchooser .modal-body .carousel-item .loading-icon .icon {
|
||||
margin: 1em auto; }
|
||||
|
||||
.modchooser .modal-footer {
|
||||
height: 70px; }
|
||||
.modchooser .modal-footer .moodlenet-logo .icon {
|
||||
height: 2.5rem;
|
||||
width: 6rem;
|
||||
margin-bottom: .6rem; }
|
||||
|
||||
.modchoosercontainer.noscroll {
|
||||
overflow-y: hidden; }
|
||||
|
||||
@@ -11245,7 +11252,7 @@ body#page-lib-editor-tinymce-plugins-moodlemedia-preview {
|
||||
background-color: #fff;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
min-height: 640px; }
|
||||
height: 640px; }
|
||||
.modchooser .modal-body .optionsummary .content {
|
||||
overflow-y: auto; }
|
||||
.modchooser .modal-body .optionsummary .content .heading .icon {
|
||||
@@ -11842,6 +11849,10 @@ body.h5p-embed .h5pmessages {
|
||||
overflow-wrap: break-word !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
||||
.z-index-0 {
|
||||
z-index: 0 !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
||||
.z-index-1 {
|
||||
z-index: 1 !important;
|
||||
/* stylelint-disable-line declaration-no-important */ }
|
||||
|
||||
@@ -104,7 +104,8 @@ class provider implements
|
||||
'lastnamephonetic' => 'privacy:metadata:lastnamephonetic',
|
||||
'firstnamephonetic' => 'privacy:metadata:firstnamephonetic',
|
||||
'middlename' => 'privacy:metadata:middlename',
|
||||
'alternatename' => 'privacy:metadata:alternatename'
|
||||
'alternatename' => 'privacy:metadata:alternatename',
|
||||
'moodlenetprofile' => 'privacy:metadata:moodlenetprofile'
|
||||
];
|
||||
|
||||
$passwordhistory = [
|
||||
|
||||
@@ -300,6 +300,9 @@ function useredit_shared_definition(&$mform, $editoroptions, $filemanageroptions
|
||||
$mform->setDefault('maildisplay', core_user::get_property_default('maildisplay'));
|
||||
$mform->addHelpButton('maildisplay', 'emaildisplay');
|
||||
|
||||
$mform->addElement('text', 'moodlenetprofile', get_string('moodlenetprofile', 'user'));
|
||||
$mform->setType('moodlenetprofile', PARAM_RAW_TRIMMED);
|
||||
|
||||
$mform->addElement('text', 'city', get_string('city'), 'maxlength="120" size="21"');
|
||||
$mform->setType('city', PARAM_TEXT);
|
||||
if (!empty($CFG->defaultcity)) {
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2020060200.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2020060500.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '3.9dev+ (Build: 20200602)'; // Human-friendly version name
|
||||
|
||||
Reference in New Issue
Block a user