mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 04:22:07 +02:00
MDL-67883 core: Make core ready for MoodleNet.
This commit is contained in:
parent
111b293f61
commit
16d77f1884
@ -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'),
|
||||
|
2
course/amd/build/activitychooser.min.js
vendored
2
course/amd/build/activitychooser.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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];
|
||||
};
|
||||
|
86
course/classes/local/entity/activity_chooser_footer.php
Normal file
86
course/classes/local/entity/activity_chooser_footer.php
Normal file
@ -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');
|
||||
|
BIN
pix/MoodleNet.png
Normal file
BIN
pix/MoodleNet.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
1
pix/MoodleNet.svg
Normal file
1
pix/MoodleNet.svg
Normal file
@ -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)) {
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user